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