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