LayoutTests:
[WebKit-https.git] / WebCore / dom / ContainerNode.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2001 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26 #include "ContainerNode.h"
27
28 #include "DeleteButtonController.h"
29 #include "Document.h"
30 #include "Editor.h"
31 #include "EventNames.h"
32 #include "ExceptionCode.h"
33 #include "FrameView.h"
34 #include "InlineTextBox.h"
35 #include "MutationEvent.h"
36 #include "RenderTheme.h"
37 #include "RootInlineBox.h"
38 #include "SystemTime.h"
39 #include <wtf/Vector.h>
40
41 namespace WebCore {
42
43 using namespace EventNames;
44
45 static void dispatchChildInsertionEvents(Node*, ExceptionCode&);
46 static void dispatchChildRemovalEvents(Node*, ExceptionCode&);
47
48 typedef Vector<std::pair<NodeCallback, Node*> > NodeCallbackQueue;
49 static NodeCallbackQueue* s_postAttachCallbackQueue = 0;
50
51 static size_t s_attachDepth = 0;
52
53 ContainerNode::ContainerNode(Document* doc)
54     : EventTargetNode(doc), m_firstChild(0), m_lastChild(0)
55 {
56 }
57
58 void ContainerNode::removeAllChildren()
59 {
60     // Avoid deep recursion when destroying the node tree.
61     static bool alreadyInsideDestructor; 
62     bool topLevel = !alreadyInsideDestructor;
63     if (topLevel)
64         alreadyInsideDestructor = true;
65     
66     // List of nodes to be deleted.
67     static Node *head;
68     static Node *tail;
69     
70     // We have to tell all children that their parent has died.
71     Node *n;
72     Node *next;
73
74     for (n = m_firstChild; n != 0; n = next ) {
75         next = n->nextSibling();
76         n->setPreviousSibling(0);
77         n->setNextSibling(0);
78         n->setParent(0);
79         
80         if ( !n->refCount() ) {
81             // Add the node to the list of nodes to be deleted.
82             // Reuse the nextSibling pointer for this purpose.
83             if (tail)
84                 tail->setNextSibling(n);
85             else
86                 head = n;
87             tail = n;
88         } else if (n->inDocument())
89             n->removedFromDocument();
90     }
91     
92     // Only for the top level call, do the actual deleting.
93     if (topLevel) {
94         while ((n = head) != 0) {
95             next = n->nextSibling();
96             n->setNextSibling(0);
97
98             head = next;
99             if (next == 0)
100                 tail = 0;
101             
102             delete n;
103         }
104         
105         alreadyInsideDestructor = false;
106         m_firstChild = 0;
107         m_lastChild = 0;
108     }
109 }
110
111 ContainerNode::~ContainerNode()
112 {
113     removeAllChildren();
114 }
115
116
117 Node* ContainerNode::virtualFirstChild() const
118 {
119     return m_firstChild;
120 }
121
122 Node* ContainerNode::virtualLastChild() const
123 {
124     return m_lastChild;
125 }
126
127 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
128 {
129     // Check that this node is not "floating".
130     // If it is, it can be deleted as a side effect of sending mutation events.
131     ASSERT(refCount() || parent());
132
133     ec = 0;
134
135     // insertBefore(node, 0) is equivalent to appendChild(node)
136     if (!refChild)
137         return appendChild(newChild, ec);
138
139     // Make sure adding the new child is OK.
140     checkAddChild(newChild.get(), ec);
141     if (ec)
142         return false;
143
144     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
145     if (refChild->parentNode() != this) {
146         ec = NOT_FOUND_ERR;
147         return false;
148     }
149
150     bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
151
152     // If newChild is a DocumentFragment with no children; there's nothing to do.
153     // Just return true
154     if (isFragment && !newChild->firstChild())
155         return true;
156
157     // Now actually add the child(ren)
158     if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
159         return true;
160
161     RefPtr<Node> next = refChild;
162
163     RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
164     while (child) {
165         RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
166
167         // If child is already present in the tree, first remove it from the old location.
168         if (Node* oldParent = child->parentNode())
169             oldParent->removeChild(child.get(), ec);
170         if (ec)
171             return 0;
172
173         // FIXME: After sending the mutation events, "this" could be destroyed.
174         // We can prevent that by doing a "ref", but first we have to make sure
175         // that no callers call with ref count == 0 and parent = 0 (as of this
176         // writing, there are definitely callers who call that way).
177
178         // Due to arbitrary code running in response to a DOM mutation event it's
179         // possible that "next" is no longer a child of "this".
180         // It's also possible that "child" has been inserted elsewhere.
181         // In either of those cases, we'll just stop.
182         if (next->parentNode() != this)
183             break;
184         if (child->parentNode())
185             break;
186
187         ASSERT(!child->nextSibling());
188         ASSERT(!child->previousSibling());
189
190         // Add child before "next".
191         forbidEventDispatch();
192         Node* prev = next->previousSibling();
193         ASSERT(m_lastChild != prev);
194         next->setPreviousSibling(child.get());
195         if (prev) {
196             ASSERT(m_firstChild != next);
197             ASSERT(prev->nextSibling() == next);
198             prev->setNextSibling(child.get());
199         } else {
200             ASSERT(m_firstChild == next);
201             m_firstChild = child.get();
202         }
203         child->setParent(this);
204         child->setPreviousSibling(prev);
205         child->setNextSibling(next.get());
206         allowEventDispatch();
207
208         // Dispatch the mutation events.
209         dispatchChildInsertionEvents(child.get(), ec);
210                 
211         // Add child to the rendering tree.
212         if (attached() && !child->attached() && child->parent() == this)
213             child->attach();
214
215         child = nextChild.release();
216     }
217
218     document()->setDocumentChanged(true);
219     dispatchSubtreeModifiedEvent();
220     return true;
221 }
222
223 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec)
224 {
225     // Check that this node is not "floating".
226     // If it is, it can be deleted as a side effect of sending mutation events.
227     ASSERT(refCount() || parent());
228
229     ec = 0;
230
231     if (oldChild == newChild) // nothing to do
232         return true;
233     
234     // Make sure replacing the old child with the new is ok
235     checkReplaceChild(newChild.get(), oldChild, ec);
236     if (ec)
237         return false;
238
239     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
240     if (!oldChild || oldChild->parentNode() != this) {
241         ec = NOT_FOUND_ERR;
242         return false;
243     }
244
245     RefPtr<Node> prev = oldChild->previousSibling();
246
247     // Remove the node we're replacing
248     RefPtr<Node> removedChild = oldChild;
249     removeChild(oldChild, ec);
250     if (ec)
251         return false;
252
253     // FIXME: After sending the mutation events, "this" could be destroyed.
254     // We can prevent that by doing a "ref", but first we have to make sure
255     // that no callers call with ref count == 0 and parent = 0 (as of this
256     // writing, there are definitely callers who call that way).
257
258     bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
259
260     // Add the new child(ren)
261     RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
262     while (child) {
263         // If the new child is already in the right place, we're done.
264         if (prev && (prev == child || prev == child->previousSibling()))
265             break;
266
267         // For a fragment we have more children to do.
268         RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
269
270         // Remove child from its old position.
271         if (Node* oldParent = child->parentNode())
272             oldParent->removeChild(child.get(), ec);
273         if (ec)
274             return 0;
275
276         // Due to arbitrary code running in response to a DOM mutation event it's
277         // possible that "prev" is no longer a child of "this".
278         // It's also possible that "child" has been inserted elsewhere.
279         // In either of those cases, we'll just stop.
280         if (prev && prev->parentNode() != this)
281             break;
282         if (child->parentNode())
283             break;
284
285         ASSERT(!child->nextSibling());
286         ASSERT(!child->previousSibling());
287
288         // Add child after "prev".
289         forbidEventDispatch();
290         Node* next;
291         if (prev) {
292             next = prev->nextSibling();
293             ASSERT(m_firstChild != next);
294             prev->setNextSibling(child.get());
295         } else {
296             next = m_firstChild;
297             m_firstChild = child.get();
298         }
299         if (next) {
300             ASSERT(m_lastChild != prev);
301             ASSERT(next->previousSibling() == prev);
302             next->setPreviousSibling(child.get());
303         } else {
304             ASSERT(m_lastChild == prev);
305             m_lastChild = child.get();
306         }
307         child->setParent(this);
308         child->setPreviousSibling(prev.get());
309         child->setNextSibling(next);
310         allowEventDispatch();
311
312         // Dispatch the mutation events
313         dispatchChildInsertionEvents(child.get(), ec);
314                 
315         // Add child to the rendering tree
316         if (attached() && !child->attached() && child->parent() == this)
317             child->attach();
318
319         prev = child;
320         child = nextChild.release();
321     }
322
323     // ### set style in case it's attached
324     document()->setDocumentChanged(true);
325     dispatchSubtreeModifiedEvent();
326     return true;
327 }
328
329 void ContainerNode::willRemove()
330 {
331     for (Node *n = m_firstChild; n != 0; n = n->nextSibling())
332         n->willRemove();
333     EventTargetNode::willRemove();
334 }
335
336 static ExceptionCode willRemoveChild(Node *child)
337 {
338     ExceptionCode ec = 0;
339
340     // fire removed from document mutation events.
341     dispatchChildRemovalEvents(child, ec);
342     if (ec)
343         return ec;
344
345     if (child->attached())
346         child->willRemove();
347     
348     return 0;
349 }
350
351 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
352 {
353     // Check that this node is not "floating".
354     // If it is, it can be deleted as a side effect of sending mutation events.
355     ASSERT(refCount() || parent());
356
357     ec = 0;
358
359     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
360     if (isReadOnlyNode()) {
361         ec = NO_MODIFICATION_ALLOWED_ERR;
362         return false;
363     }
364
365     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
366     if (!oldChild || oldChild->parentNode() != this) {
367         ec = NOT_FOUND_ERR;
368         return false;
369     }
370
371     RefPtr<Node> child = oldChild;
372     
373     // dispatch pre-removal mutation events
374     if (document()->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) {
375         EventTargetNodeCast(child.get())->dispatchEvent(new MutationEvent(DOMNodeRemovedEvent, true, false,
376             this, String(), String(), String(), 0), ec, true);
377         if (ec)
378             return false;
379     }
380
381     ec = willRemoveChild(child.get());
382     if (ec)
383         return false;
384
385     // Mutation events might have moved this child into a different parent.
386     if (child->parentNode() != this) {
387         ec = NOT_FOUND_ERR;
388         return false;
389     }
390
391     // FIXME: After sending the mutation events, "this" could be destroyed.
392     // We can prevent that by doing a "ref", but first we have to make sure
393     // that no callers call with ref count == 0 and parent = 0 (as of this
394     // writing, there are definitely callers who call that way).
395
396     forbidEventDispatch();
397
398     // Remove from rendering tree
399     if (child->attached())
400         child->detach();
401
402     // Remove the child
403     Node *prev, *next;
404     prev = child->previousSibling();
405     next = child->nextSibling();
406
407     if (next)
408         next->setPreviousSibling(prev);
409     if (prev)
410         prev->setNextSibling(next);
411     if (m_firstChild == child)
412         m_firstChild = next;
413     if (m_lastChild == child)
414         m_lastChild = prev;
415
416     child->setPreviousSibling(0);
417     child->setNextSibling(0);
418     child->setParent(0);
419
420     allowEventDispatch();
421
422     document()->setDocumentChanged(true);
423
424     // Dispatch post-removal mutation events
425     dispatchSubtreeModifiedEvent();
426
427     if (child->inDocument())
428         child->removedFromDocument();
429     else
430         child->removedFromTree(true);
431
432     return child;
433 }
434
435 // this differs from other remove functions because it forcibly removes all the children,
436 // regardless of read-only status or event exceptions, e.g.
437 void ContainerNode::removeChildren()
438 {
439     Node *n;
440     
441     if (!m_firstChild)
442         return;
443
444     // do any prep work needed before actually starting to detach
445     // and remove... e.g. stop loading frames, fire unload events
446     for (n = m_firstChild; n; n = n->nextSibling())
447         willRemoveChild(n);
448     
449     forbidEventDispatch();
450     while ((n = m_firstChild) != 0) {
451         Node *next = n->nextSibling();
452         
453         n->ref();
454
455         // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744)
456         n->setPreviousSibling(0);
457         n->setNextSibling(0);
458         n->setParent(0);
459         
460         m_firstChild = next;
461         if (n == m_lastChild)
462             m_lastChild = 0;
463
464         if (n->attached())
465             n->detach();
466         
467         if (n->inDocument())
468             n->removedFromDocument();
469
470         n->deref();
471     }
472     allowEventDispatch();
473     
474     // Dispatch a single post-removal mutation event denoting a modified subtree.
475     dispatchSubtreeModifiedEvent();
476 }
477
478
479 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
480 {
481     // Check that this node is not "floating".
482     // If it is, it can be deleted as a side effect of sending mutation events.
483     ASSERT(refCount() || parent());
484
485     ec = 0;
486
487     // Make sure adding the new child is ok
488     checkAddChild(newChild.get(), ec);
489     if (ec)
490         return 0;
491     
492     if (newChild == m_lastChild) // nothing to do
493         return newChild;
494
495     bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
496
497     // If newChild is a DocumentFragment with no children.... there's nothing to do.
498     // Just return the document fragment
499     if (isFragment && !newChild->firstChild())
500         return true;
501
502     // Now actually add the child(ren)
503     RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
504     while (child) {
505         // For a fragment we have more children to do.
506         RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
507
508         // If child is already present in the tree, first remove it
509         if (Node* oldParent = child->parentNode()) {
510             oldParent->removeChild(child.get(), ec);
511             if (ec)
512                 return 0;
513             
514             // If the child has a parent again, just stop what we're doing, because
515             // that means someone is doing something with DOM mutation -- can't re-parent
516             // a child that already has a parent.
517             if (child->parentNode())
518                 break;
519         }
520
521         // Append child to the end of the list
522         forbidEventDispatch();
523         child->setParent(this);
524         if (m_lastChild) {
525             child->setPreviousSibling(m_lastChild);
526             m_lastChild->setNextSibling(child.get());
527         } else
528             m_firstChild = child.get();
529         m_lastChild = child.get();
530         allowEventDispatch();
531
532         // Dispatch the mutation events
533         dispatchChildInsertionEvents(child.get(), ec);
534
535         // Add child to the rendering tree
536         if (attached() && !child->attached() && child->parent() == this)
537             child->attach();
538         
539         child = nextChild.release();
540     }
541
542     document()->setDocumentChanged(true);
543     dispatchSubtreeModifiedEvent();
544     return true;
545 }
546
547 bool ContainerNode::hasChildNodes() const
548 {
549     return m_firstChild;
550 }
551
552 ContainerNode* ContainerNode::addChild(PassRefPtr<Node> newChild)
553 {
554     // This function is only used during parsing.
555     // It does not send any DOM mutation events.
556
557     // Check for consistency with DTD, but only when parsing HTML.
558     if (document()->isHTMLDocument() && !childAllowed(newChild.get()))
559         return 0;
560
561     forbidEventDispatch();
562     newChild->setParent(this);
563     if (m_lastChild) {
564         newChild->setPreviousSibling(m_lastChild);
565         m_lastChild->setNextSibling(newChild.get());
566     } else
567         m_firstChild = newChild.get();
568     m_lastChild = newChild.get();
569     allowEventDispatch();
570
571     if (inDocument())
572         newChild->insertedIntoDocument();
573     if (document()->hasNodeLists())
574         notifyNodeListsChildrenChanged();
575     childrenChanged();
576     
577     if (newChild->isElementNode())
578         return static_cast<ContainerNode*>(newChild.get());
579     return this;
580 }
581
582 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node)
583 {
584     if (!s_postAttachCallbackQueue)
585         s_postAttachCallbackQueue = new NodeCallbackQueue;
586     
587     s_postAttachCallbackQueue->append(std::pair<NodeCallback, Node*>(callback, node));
588 }
589
590 void ContainerNode::attach()
591 {
592     ++s_attachDepth;
593
594     for (Node* child = m_firstChild; child; child = child->nextSibling())
595         child->attach();
596     EventTargetNode::attach();
597
598     if (s_attachDepth == 1) {
599         if (s_postAttachCallbackQueue) {
600             // We recalculate size() each time through the loop because a callback
601             // can add more callbacks to the end of the queue.
602             for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
603                 std::pair<NodeCallback, Node*>& pair = (*s_postAttachCallbackQueue)[i];
604                 NodeCallback callback = pair.first;
605                 Node* node = pair.second;
606                 
607                 callback(node);
608             }
609             s_postAttachCallbackQueue->clear();
610         }
611     }    
612     --s_attachDepth;
613 }
614
615 void ContainerNode::detach()
616 {
617     for (Node* child = m_firstChild; child; child = child->nextSibling())
618         child->detach();
619     EventTargetNode::detach();
620 }
621
622 void ContainerNode::insertedIntoDocument()
623 {
624     EventTargetNode::insertedIntoDocument();
625     for (Node *child = m_firstChild; child; child = child->nextSibling())
626         child->insertedIntoDocument();
627 }
628
629 void ContainerNode::removedFromDocument()
630 {
631     EventTargetNode::removedFromDocument();
632     for (Node *child = m_firstChild; child; child = child->nextSibling())
633         child->removedFromDocument();
634 }
635
636 void ContainerNode::insertedIntoTree(bool deep)
637 {
638     EventTargetNode::insertedIntoTree(deep);
639     if (deep) {
640         for (Node *child = m_firstChild; child; child = child->nextSibling())
641             child->insertedIntoTree(deep);
642     }
643 }
644
645 void ContainerNode::removedFromTree(bool deep)
646 {
647     EventTargetNode::removedFromTree(deep);
648     if (deep) {
649         for (Node *child = m_firstChild; child; child = child->nextSibling())
650             child->removedFromTree(deep);
651     }
652 }
653
654 void ContainerNode::cloneChildNodes(Node *clone)
655 {
656     // disable the delete button so it's elements are not serialized into the markup
657     if (document()->frame())
658         document()->frame()->editor()->deleteButtonController()->disable();
659     ExceptionCode ec = 0;
660     for (Node* n = firstChild(); n && !ec; n = n->nextSibling())
661         clone->appendChild(n->cloneNode(true), ec);
662     if (document()->frame())
663         document()->frame()->editor()->deleteButtonController()->enable();
664 }
665
666 bool ContainerNode::getUpperLeftCorner(int &xPos, int &yPos) const
667 {
668     if (!renderer())
669         return false;
670     RenderObject *o = renderer();
671     RenderObject *p = o;
672
673     xPos = yPos = 0;
674     if (!o->isInline() || o->isReplaced()) {
675         o->absolutePosition(xPos, yPos);
676         return true;
677     }
678
679     // find the next text/image child, to get a position
680     while(o) {
681         p = o;
682         if (o->firstChild())
683             o = o->firstChild();
684         else if(o->nextSibling())
685             o = o->nextSibling();
686         else {
687             RenderObject *next = 0;
688             while (!next && o->parent()) {
689                 o = o->parent();
690                 next = o->nextSibling();
691             }
692             o = next;
693
694             if (!o)
695                 break;
696         }
697
698         if (!o->isInline() || o->isReplaced()) {
699             o->absolutePosition(xPos, yPos);
700             return true;
701         }
702
703         if (p->element() && p->element() == this && o->isText() && !o->isBR() && !static_cast<RenderText*>(o)->firstTextBox()) {
704                 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
705         } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
706             o->container()->absolutePosition(xPos, yPos);
707             if (o->isText() && static_cast<RenderText *>(o)->firstTextBox()) {
708                 xPos += static_cast<RenderText *>(o)->minXPos();
709                 yPos += static_cast<RenderText *>(o)->firstTextBox()->root()->topOverflow();
710             } else {
711                 xPos += o->xPos();
712                 yPos += o->yPos();
713             }
714             return true;
715         }
716     }
717     
718     // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
719     // at the end of the document.  Scroll to the bottom.
720     if (!o && document()->view()) {
721         yPos += document()->view()->contentsHeight();
722         return true;
723     }
724     return false;
725 }
726
727 bool ContainerNode::getLowerRightCorner(int &xPos, int &yPos) const
728 {
729     if (!renderer())
730         return false;
731
732     RenderObject *o = renderer();
733     xPos = yPos = 0;
734     if (!o->isInline() || o->isReplaced())
735     {
736         o->absolutePosition(xPos, yPos);
737         xPos += o->width();
738         yPos += o->height() + o->borderTopExtra() + o->borderBottomExtra();
739         return true;
740     }
741     // find the last text/image child, to get a position
742     while(o) {
743         if(o->lastChild())
744             o = o->lastChild();
745         else if(o->previousSibling())
746             o = o->previousSibling();
747         else {
748             RenderObject *prev = 0;
749             while(!prev) {
750                 o = o->parent();
751                 if(!o) return false;
752                 prev = o->previousSibling();
753             }
754             o = prev;
755         }
756         if (o->isText() || o->isReplaced()) {
757             o->container()->absolutePosition(xPos, yPos);
758             if (o->isText())
759                 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
760             else
761                 xPos += o->xPos()+o->width();
762             yPos += o->yPos()+o->height();
763             return true;
764         }
765     }
766     return true;
767 }
768
769 IntRect ContainerNode::getRect() const
770 {
771     int xPos = 0, yPos = 0, xEnd = 0, yEnd = 0;
772     bool foundUpperLeft = getUpperLeftCorner(xPos,yPos);
773     bool foundLowerRight = getLowerRightCorner(xEnd,yEnd);
774     
775     // If we've found one corner, but not the other,
776     // then we should just return a point at the corner that we did find.
777     if (foundUpperLeft != foundLowerRight)
778     {
779         if (foundUpperLeft) {
780             xEnd = xPos;
781             yEnd = yPos;
782         } else {
783             xPos = xEnd;
784             yPos = yEnd;
785         }
786     } 
787
788     if (xEnd < xPos)
789         xEnd = xPos;
790     if (yEnd < yPos)
791         yEnd = yPos;
792         
793     return IntRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
794 }
795
796 void ContainerNode::setFocus(bool received)
797 {
798     if (m_focused == received) return;
799
800     EventTargetNode::setFocus(received);
801
802     // note that we need to recalc the style
803     setChanged();
804 }
805
806 void ContainerNode::setActive(bool down, bool pause)
807 {
808     if (down == active()) return;
809
810     EventTargetNode::setActive(down);
811
812     // note that we need to recalc the style
813     // FIXME: Move to Element
814     if (renderer()) {
815         bool reactsToPress = renderer()->style()->affectedByActiveRules();
816         if (reactsToPress)
817             setChanged();
818         if (renderer() && renderer()->style()->hasAppearance()) {
819             if (theme()->stateChanged(renderer(), PressedState))
820                 reactsToPress = true;
821         }
822         if (reactsToPress && pause) {
823             // The delay here is subtle.  It relies on an assumption, namely that the amount of time it takes
824             // to repaint the "down" state of the control is about the same time as it would take to repaint the
825             // "up" state.  Once you assume this, you can just delay for 100ms - that time (assuming that after you
826             // leave this method, it will be about that long before the flush of the up state happens again).
827 #ifdef HAVE_FUNC_USLEEP
828             double startTime = currentTime();
829 #endif
830
831             // Ensure there are no pending changes
832             Document::updateDocumentsRendering();
833             // Do an immediate repaint.
834             if (renderer())
835                 renderer()->repaint(true);
836             
837             // FIXME: Find a substitute for usleep for Win32.
838             // Better yet, come up with a way of doing this that doesn't use this sort of thing at all.            
839 #ifdef HAVE_FUNC_USLEEP
840             // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
841             double remainingTime = 0.1 - (currentTime() - startTime);
842             if (remainingTime > 0)
843                 usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
844 #endif
845         }
846     }
847 }
848
849 void ContainerNode::setHovered(bool over)
850 {
851     if (over == hovered()) return;
852
853     EventTargetNode::setHovered(over);
854
855     // note that we need to recalc the style
856     // FIXME: Move to Element
857     if (renderer()) {
858         if (renderer()->style()->affectedByHoverRules())
859             setChanged();
860         if (renderer() && renderer()->style()->hasAppearance())
861             theme()->stateChanged(renderer(), HoverState);
862     }
863 }
864
865 unsigned ContainerNode::childNodeCount() const
866 {
867     unsigned count = 0;
868     Node *n;
869     for (n = firstChild(); n; n = n->nextSibling())
870         count++;
871     return count;
872 }
873
874 Node *ContainerNode::childNode(unsigned index) const
875 {
876     unsigned i;
877     Node *n = firstChild();
878     for (i = 0; n != 0 && i < index; i++)
879         n = n->nextSibling();
880     return n;
881 }
882
883 static void dispatchChildInsertionEvents(Node* child, ExceptionCode& ec)
884 {
885     ASSERT(!eventDispatchForbidden());
886
887     RefPtr<Node> c = child;
888     RefPtr<Document> doc = child->document();
889
890     if (c->parentNode() && c->parentNode()->inDocument())
891         c->insertedIntoDocument();
892     else
893         c->insertedIntoTree(true);
894
895     if (c->parentNode() && 
896         doc->hasListenerType(Document::DOMNODEINSERTED_LISTENER) &&
897         c->isEventTargetNode()) {
898         ec = 0;
899         EventTargetNodeCast(c.get())->dispatchEvent(new MutationEvent(DOMNodeInsertedEvent, true, false,
900             c->parentNode(), String(), String(), String(), 0), ec, true);
901         if (ec)
902             return;
903     }
904
905     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
906     if (c->inDocument() && doc->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER))
907         for (; c; c = c->traverseNextNode(child)) {
908             if (!c->isEventTargetNode())
909                 continue;
910           
911             ec = 0;
912             EventTargetNodeCast(c.get())->dispatchEvent(new MutationEvent(DOMNodeInsertedIntoDocumentEvent, false, false,
913                 0, String(), String(), String(), 0), ec, true);
914             if (ec)
915                 return;
916         }
917 }
918
919 static void dispatchChildRemovalEvents(Node* child, ExceptionCode& ec)
920 {
921     RefPtr<Node> c = child;
922     RefPtr<Document> doc = child->document();
923
924     // update auxiliary doc info (e.g. iterators) to note that node is being removed
925     doc->notifyBeforeNodeRemoval(child); // ### use events instead
926
927     // dispatch pre-removal mutation events
928     if (c->parentNode() && 
929         doc->hasListenerType(Document::DOMNODEREMOVED_LISTENER) &&
930         c->isEventTargetNode()) {
931         ec = 0;
932         EventTargetNodeCast(c.get())->dispatchEvent(new MutationEvent(DOMNodeRemovedEvent, true, false,
933             c->parentNode(), String(), String(), String(), 0), ec, true);
934         if (ec)
935             return;
936     }
937
938     // dispatch the DOMNodeRemovedFromDocument event to all descendants
939     if (c->inDocument() && doc->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER))
940         for (; c; c = c->traverseNextNode(child)) {
941             if (!c->isEventTargetNode())
942                 continue;
943             ec = 0;
944             EventTargetNodeCast(c.get())->dispatchEvent(new MutationEvent(DOMNodeRemovedFromDocumentEvent, false, false,
945                 0, String(), String(), String(), 0), ec, true);
946             if (ec)
947                 return;
948         }
949 }
950
951 }