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