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