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