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