Home | History | Annotate | Download | only in dom
      1 /*
      2  * (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  * (C) 2000 Gunnstein Lye (gunnstein (at) netcom.no)
      4  * (C) 2000 Frederik Holljen (frederik.holljen (at) hig.no)
      5  * (C) 2001 Peter Kelly (pmk (at) post.com)
      6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  */
     23 
     24 #include "config.h"
     25 #include "Range.h"
     26 #include "RangeException.h"
     27 
     28 #include "ClientRect.h"
     29 #include "ClientRectList.h"
     30 #include "DocumentFragment.h"
     31 #include "FrameView.h"
     32 #include "HTMLElement.h"
     33 #include "NodeWithIndex.h"
     34 #include "ProcessingInstruction.h"
     35 #include "Text.h"
     36 #include "TextIterator.h"
     37 #include "VisiblePosition.h"
     38 #include "htmlediting.h"
     39 #include "markup.h"
     40 #include "visible_units.h"
     41 #include <stdio.h>
     42 #include <wtf/text/CString.h>
     43 #include <wtf/RefCountedLeakCounter.h>
     44 #include <wtf/Vector.h>
     45 
     46 namespace WebCore {
     47 
     48 using namespace std;
     49 
     50 #ifndef NDEBUG
     51 static WTF::RefCountedLeakCounter rangeCounter("Range");
     52 #endif
     53 
     54 inline Range::Range(PassRefPtr<Document> ownerDocument)
     55     : m_ownerDocument(ownerDocument)
     56     , m_start(m_ownerDocument)
     57     , m_end(m_ownerDocument)
     58 {
     59 #ifndef NDEBUG
     60     rangeCounter.increment();
     61 #endif
     62 
     63     m_ownerDocument->attachRange(this);
     64 }
     65 
     66 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument)
     67 {
     68     return adoptRef(new Range(ownerDocument));
     69 }
     70 
     71 inline Range::Range(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
     72     : m_ownerDocument(ownerDocument)
     73     , m_start(m_ownerDocument)
     74     , m_end(m_ownerDocument)
     75 {
     76 #ifndef NDEBUG
     77     rangeCounter.increment();
     78 #endif
     79 
     80     m_ownerDocument->attachRange(this);
     81 
     82     // Simply setting the containers and offsets directly would not do any of the checking
     83     // that setStart and setEnd do, so we call those functions.
     84     ExceptionCode ec = 0;
     85     setStart(startContainer, startOffset, ec);
     86     ASSERT(!ec);
     87     setEnd(endContainer, endOffset, ec);
     88     ASSERT(!ec);
     89 }
     90 
     91 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
     92 {
     93     return adoptRef(new Range(ownerDocument, startContainer, startOffset, endContainer, endOffset));
     94 }
     95 
     96 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end)
     97 {
     98     return adoptRef(new Range(ownerDocument, start.containerNode(), start.computeOffsetInContainerNode(), end.containerNode(), end.computeOffsetInContainerNode()));
     99 }
    100 
    101 Range::~Range()
    102 {
    103     // Always detach (even if we've already detached) to fix https://bugs.webkit.org/show_bug.cgi?id=26044
    104     m_ownerDocument->detachRange(this);
    105 
    106 #ifndef NDEBUG
    107     rangeCounter.decrement();
    108 #endif
    109 }
    110 
    111 void Range::setDocument(Document* document)
    112 {
    113     ASSERT(m_ownerDocument != document);
    114     if (m_ownerDocument)
    115         m_ownerDocument->detachRange(this);
    116     m_ownerDocument = document;
    117     m_start.setToStartOfNode(document);
    118     m_end.setToStartOfNode(document);
    119     m_ownerDocument->attachRange(this);
    120 }
    121 
    122 Node* Range::startContainer(ExceptionCode& ec) const
    123 {
    124     if (!m_start.container()) {
    125         ec = INVALID_STATE_ERR;
    126         return 0;
    127     }
    128 
    129     return m_start.container();
    130 }
    131 
    132 int Range::startOffset(ExceptionCode& ec) const
    133 {
    134     if (!m_start.container()) {
    135         ec = INVALID_STATE_ERR;
    136         return 0;
    137     }
    138 
    139     return m_start.offset();
    140 }
    141 
    142 Node* Range::endContainer(ExceptionCode& ec) const
    143 {
    144     if (!m_start.container()) {
    145         ec = INVALID_STATE_ERR;
    146         return 0;
    147     }
    148 
    149     return m_end.container();
    150 }
    151 
    152 int Range::endOffset(ExceptionCode& ec) const
    153 {
    154     if (!m_start.container()) {
    155         ec = INVALID_STATE_ERR;
    156         return 0;
    157     }
    158 
    159     return m_end.offset();
    160 }
    161 
    162 Node* Range::commonAncestorContainer(ExceptionCode& ec) const
    163 {
    164     if (!m_start.container()) {
    165         ec = INVALID_STATE_ERR;
    166         return 0;
    167     }
    168 
    169     return commonAncestorContainer(m_start.container(), m_end.container());
    170 }
    171 
    172 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
    173 {
    174     for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
    175         for (Node* parentB = containerB; parentB; parentB = parentB->parentNode()) {
    176             if (parentA == parentB)
    177                 return parentA;
    178         }
    179     }
    180     return 0;
    181 }
    182 
    183 bool Range::collapsed(ExceptionCode& ec) const
    184 {
    185     if (!m_start.container()) {
    186         ec = INVALID_STATE_ERR;
    187         return 0;
    188     }
    189 
    190     return m_start == m_end;
    191 }
    192 
    193 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
    194 {
    195     if (!m_start.container()) {
    196         ec = INVALID_STATE_ERR;
    197         return;
    198     }
    199 
    200     if (!refNode) {
    201         ec = NOT_FOUND_ERR;
    202         return;
    203     }
    204 
    205     if (refNode->document() != m_ownerDocument) {
    206         ec = WRONG_DOCUMENT_ERR;
    207         return;
    208     }
    209 
    210     ec = 0;
    211     Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
    212     if (ec)
    213         return;
    214 
    215     m_start.set(refNode, offset, childNode);
    216 
    217     // check if different root container
    218     Node* endRootContainer = m_end.container();
    219     while (endRootContainer->parentNode())
    220         endRootContainer = endRootContainer->parentNode();
    221     Node* startRootContainer = m_start.container();
    222     while (startRootContainer->parentNode())
    223         startRootContainer = startRootContainer->parentNode();
    224     if (startRootContainer != endRootContainer)
    225         collapse(true, ec);
    226     // check if new start after end
    227     else if (compareBoundaryPoints(m_start, m_end, ec) > 0) {
    228         ASSERT(!ec);
    229         collapse(true, ec);
    230     }
    231 }
    232 
    233 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionCode& ec)
    234 {
    235     if (!m_start.container()) {
    236         ec = INVALID_STATE_ERR;
    237         return;
    238     }
    239 
    240     if (!refNode) {
    241         ec = NOT_FOUND_ERR;
    242         return;
    243     }
    244 
    245     if (refNode->document() != m_ownerDocument) {
    246         ec = WRONG_DOCUMENT_ERR;
    247         return;
    248     }
    249 
    250     ec = 0;
    251     Node* childNode = checkNodeWOffset(refNode.get(), offset, ec);
    252     if (ec)
    253         return;
    254 
    255     m_end.set(refNode, offset, childNode);
    256 
    257     // check if different root container
    258     Node* endRootContainer = m_end.container();
    259     while (endRootContainer->parentNode())
    260         endRootContainer = endRootContainer->parentNode();
    261     Node* startRootContainer = m_start.container();
    262     while (startRootContainer->parentNode())
    263         startRootContainer = startRootContainer->parentNode();
    264     if (startRootContainer != endRootContainer)
    265         collapse(false, ec);
    266     // check if new end before start
    267     if (compareBoundaryPoints(m_start, m_end, ec) > 0) {
    268         ASSERT(!ec);
    269         collapse(false, ec);
    270     }
    271 }
    272 
    273 void Range::collapse(bool toStart, ExceptionCode& ec)
    274 {
    275     if (!m_start.container()) {
    276         ec = INVALID_STATE_ERR;
    277         return;
    278     }
    279 
    280     if (toStart)
    281         m_end = m_start;
    282     else
    283         m_start = m_end;
    284 }
    285 
    286 bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec)
    287 {
    288     if (!m_start.container()) {
    289         ec = INVALID_STATE_ERR;
    290         return false;
    291     }
    292 
    293     if (!refNode) {
    294         ec = HIERARCHY_REQUEST_ERR;
    295         return false;
    296     }
    297 
    298     if (!refNode->attached()) {
    299         // Firefox doesn't throw an exception for this case; it returns false.
    300         return false;
    301     }
    302 
    303     if (refNode->document() != m_ownerDocument) {
    304         ec = WRONG_DOCUMENT_ERR;
    305         return false;
    306     }
    307 
    308     ec = 0;
    309     checkNodeWOffset(refNode, offset, ec);
    310     if (ec)
    311         return false;
    312 
    313     return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), ec) >= 0 && !ec
    314         && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), ec) <= 0 && !ec;
    315 }
    316 
    317 short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) const
    318 {
    319     // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
    320     // This method returns -1, 0 or 1 depending on if the point described by the
    321     // refNode node and an offset within the node is before, same as, or after the range respectively.
    322 
    323     if (!m_start.container()) {
    324         ec = INVALID_STATE_ERR;
    325         return 0;
    326     }
    327 
    328     if (!refNode) {
    329         ec = HIERARCHY_REQUEST_ERR;
    330         return 0;
    331     }
    332 
    333     if (!refNode->attached() || refNode->document() != m_ownerDocument) {
    334         ec = WRONG_DOCUMENT_ERR;
    335         return 0;
    336     }
    337 
    338     ec = 0;
    339     checkNodeWOffset(refNode, offset, ec);
    340     if (ec)
    341         return 0;
    342 
    343     // compare to start, and point comes before
    344     if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), ec) < 0)
    345         return -1;
    346 
    347     if (ec)
    348         return 0;
    349 
    350     // compare to end, and point comes after
    351     if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), ec) > 0 && !ec)
    352         return 1;
    353 
    354     // point is in the middle of this range, or on the boundary points
    355     return 0;
    356 }
    357 
    358 Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec) const
    359 {
    360     // http://developer.mozilla.org/en/docs/DOM:range.compareNode
    361     // This method returns 0, 1, 2, or 3 based on if the node is before, after,
    362     // before and after(surrounds), or inside the range, respectively
    363 
    364     if (!refNode) {
    365         ec = NOT_FOUND_ERR;
    366         return NODE_BEFORE;
    367     }
    368 
    369     if (!m_start.container() && refNode->attached()) {
    370         ec = INVALID_STATE_ERR;
    371         return NODE_BEFORE;
    372     }
    373 
    374     if (m_start.container() && !refNode->attached()) {
    375         // Firefox doesn't throw an exception for this case; it returns 0.
    376         return NODE_BEFORE;
    377     }
    378 
    379     if (refNode->document() != m_ownerDocument) {
    380         // Firefox doesn't throw an exception for this case; it returns 0.
    381         return NODE_BEFORE;
    382     }
    383 
    384     ContainerNode* parentNode = refNode->parentNode();
    385     int nodeIndex = refNode->nodeIndex();
    386 
    387     if (!parentNode) {
    388         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
    389         // but we throw to match firefox behavior
    390         ec = NOT_FOUND_ERR;
    391         return NODE_BEFORE;
    392     }
    393 
    394     if (comparePoint(parentNode, nodeIndex, ec) < 0) { // starts before
    395         if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
    396             return NODE_BEFORE_AND_AFTER;
    397         return NODE_BEFORE; // ends before or in the range
    398     } else { // starts at or after the range start
    399         if (comparePoint(parentNode, nodeIndex + 1, ec) > 0) // ends after the range
    400             return NODE_AFTER;
    401         return NODE_INSIDE; // ends inside the range
    402     }
    403 }
    404 
    405 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionCode& ec) const
    406 {
    407     if (!m_start.container()) {
    408         ec = INVALID_STATE_ERR;
    409         return 0;
    410     }
    411 
    412     if (!sourceRange) {
    413         ec = NOT_FOUND_ERR;
    414         return 0;
    415     }
    416 
    417     ec = 0;
    418     Node* thisCont = commonAncestorContainer(ec);
    419     if (ec)
    420         return 0;
    421     Node* sourceCont = sourceRange->commonAncestorContainer(ec);
    422     if (ec)
    423         return 0;
    424 
    425     if (thisCont->document() != sourceCont->document()) {
    426         ec = WRONG_DOCUMENT_ERR;
    427         return 0;
    428     }
    429 
    430     Node* thisTop = thisCont;
    431     Node* sourceTop = sourceCont;
    432     while (thisTop->parentNode())
    433         thisTop = thisTop->parentNode();
    434     while (sourceTop->parentNode())
    435         sourceTop = sourceTop->parentNode();
    436     if (thisTop != sourceTop) { // in different DocumentFragments
    437         ec = WRONG_DOCUMENT_ERR;
    438         return 0;
    439     }
    440 
    441     switch (how) {
    442         case START_TO_START:
    443             return compareBoundaryPoints(m_start, sourceRange->m_start, ec);
    444         case START_TO_END:
    445             return compareBoundaryPoints(m_end, sourceRange->m_start, ec);
    446         case END_TO_END:
    447             return compareBoundaryPoints(m_end, sourceRange->m_end, ec);
    448         case END_TO_START:
    449             return compareBoundaryPoints(m_start, sourceRange->m_end, ec);
    450     }
    451 
    452     ec = SYNTAX_ERR;
    453     return 0;
    454 }
    455 
    456 short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionCode& ec)
    457 {
    458     ASSERT(containerA);
    459     ASSERT(containerB);
    460 
    461     if (!containerA)
    462         return -1;
    463     if (!containerB)
    464         return 1;
    465 
    466     // see DOM2 traversal & range section 2.5
    467 
    468     // case 1: both points have the same container
    469     if (containerA == containerB) {
    470         if (offsetA == offsetB)
    471             return 0;           // A is equal to B
    472         if (offsetA < offsetB)
    473             return -1;          // A is before B
    474         else
    475             return 1;           // A is after B
    476     }
    477 
    478     // case 2: node C (container B or an ancestor) is a child node of A
    479     Node* c = containerB;
    480     while (c && c->parentNode() != containerA)
    481         c = c->parentNode();
    482     if (c) {
    483         int offsetC = 0;
    484         Node* n = containerA->firstChild();
    485         while (n != c && offsetC < offsetA) {
    486             offsetC++;
    487             n = n->nextSibling();
    488         }
    489 
    490         if (offsetA <= offsetC)
    491             return -1;              // A is before B
    492         else
    493             return 1;               // A is after B
    494     }
    495 
    496     // case 3: node C (container A or an ancestor) is a child node of B
    497     c = containerA;
    498     while (c && c->parentNode() != containerB)
    499         c = c->parentNode();
    500     if (c) {
    501         int offsetC = 0;
    502         Node* n = containerB->firstChild();
    503         while (n != c && offsetC < offsetB) {
    504             offsetC++;
    505             n = n->nextSibling();
    506         }
    507 
    508         if (offsetC < offsetB)
    509             return -1;              // A is before B
    510         else
    511             return 1;               // A is after B
    512     }
    513 
    514     // case 4: containers A & B are siblings, or children of siblings
    515     // ### we need to do a traversal here instead
    516     Node* commonAncestor = commonAncestorContainer(containerA, containerB);
    517     if (!commonAncestor) {
    518         ec = WRONG_DOCUMENT_ERR;
    519         return 0;
    520     }
    521     Node* childA = containerA;
    522     while (childA && childA->parentNode() != commonAncestor)
    523         childA = childA->parentNode();
    524     if (!childA)
    525         childA = commonAncestor;
    526     Node* childB = containerB;
    527     while (childB && childB->parentNode() != commonAncestor)
    528         childB = childB->parentNode();
    529     if (!childB)
    530         childB = commonAncestor;
    531 
    532     if (childA == childB)
    533         return 0; // A is equal to B
    534 
    535     Node* n = commonAncestor->firstChild();
    536     while (n) {
    537         if (n == childA)
    538             return -1; // A is before B
    539         if (n == childB)
    540             return 1; // A is after B
    541         n = n->nextSibling();
    542     }
    543 
    544     // Should never reach this point.
    545     ASSERT_NOT_REACHED();
    546     return 0;
    547 }
    548 
    549 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode& ec)
    550 {
    551     return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset(), ec);
    552 }
    553 
    554 bool Range::boundaryPointsValid() const
    555 {
    556     ExceptionCode ec = 0;
    557     return m_start.container() && compareBoundaryPoints(m_start, m_end, ec) <= 0 && !ec;
    558 }
    559 
    560 void Range::deleteContents(ExceptionCode& ec)
    561 {
    562     checkDeleteExtract(ec);
    563     if (ec)
    564         return;
    565 
    566     processContents(DELETE_CONTENTS, ec);
    567 }
    568 
    569 bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
    570 {
    571     // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
    572     // Returns a bool if the node intersects the range.
    573 
    574     if (!refNode) {
    575         ec = NOT_FOUND_ERR;
    576         return false;
    577     }
    578 
    579     if ((!m_start.container() && refNode->attached())
    580             || (m_start.container() && !refNode->attached())
    581             || refNode->document() != m_ownerDocument) {
    582         // Firefox doesn't throw an exception for these cases; it returns false.
    583         return false;
    584     }
    585 
    586     ContainerNode* parentNode = refNode->parentNode();
    587     int nodeIndex = refNode->nodeIndex();
    588 
    589     if (!parentNode) {
    590         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
    591         // but we throw to match firefox behavior
    592         ec = NOT_FOUND_ERR;
    593         return false;
    594     }
    595 
    596     if (comparePoint(parentNode, nodeIndex, ec) < 0 && // starts before start
    597         comparePoint(parentNode, nodeIndex + 1, ec) < 0) { // ends before start
    598         return false;
    599     } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after end
    600                comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after end
    601         return false;
    602     }
    603 
    604     return true; // all other cases
    605 }
    606 
    607 static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot)
    608 {
    609     if (node == commonRoot)
    610         return 0;
    611 
    612     ASSERT(commonRoot->contains(node));
    613 
    614     while (node->parentNode() != commonRoot)
    615         node = node->parentNode();
    616 
    617     return node;
    618 }
    619 
    620 static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offset, Node* commonRoot)
    621 {
    622     ASSERT(container);
    623     ASSERT(commonRoot);
    624     ASSERT(commonRoot->contains(container));
    625 
    626     if (container == commonRoot) {
    627         container = container->firstChild();
    628         for (unsigned i = 0; container && i < offset; i++)
    629             container = container->nextSibling();
    630     } else {
    631         while (container->parentNode() != commonRoot)
    632             container = container->parentNode();
    633     }
    634 
    635     return container;
    636 }
    637 
    638 static inline unsigned lengthOfContentsInNode(Node* node)
    639 {
    640     // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
    641     switch (node->nodeType()) {
    642     case Node::TEXT_NODE:
    643     case Node::CDATA_SECTION_NODE:
    644     case Node::COMMENT_NODE:
    645         return static_cast<CharacterData*>(node)->length();
    646     case Node::PROCESSING_INSTRUCTION_NODE:
    647         return static_cast<ProcessingInstruction*>(node)->data().length();
    648     case Node::ELEMENT_NODE:
    649     case Node::ATTRIBUTE_NODE:
    650     case Node::ENTITY_REFERENCE_NODE:
    651     case Node::ENTITY_NODE:
    652     case Node::DOCUMENT_NODE:
    653     case Node::DOCUMENT_TYPE_NODE:
    654     case Node::DOCUMENT_FRAGMENT_NODE:
    655     case Node::NOTATION_NODE:
    656     case Node::XPATH_NAMESPACE_NODE:
    657         return node->childNodeCount();
    658     }
    659     ASSERT_NOT_REACHED();
    660     return 0;
    661 }
    662 
    663 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
    664 {
    665     typedef Vector<RefPtr<Node> > NodeVector;
    666 
    667     RefPtr<DocumentFragment> fragment;
    668     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
    669         fragment = DocumentFragment::create(m_ownerDocument.get());
    670 
    671     ec = 0;
    672     if (collapsed(ec))
    673         return fragment.release();
    674     if (ec)
    675         return 0;
    676 
    677     Node* commonRoot = commonAncestorContainer(ec);
    678     if (ec)
    679         return 0;
    680     ASSERT(commonRoot);
    681 
    682     if (m_start.container() == m_end.container()) {
    683         processContentsBetweenOffsets(action, fragment, m_start.container(), m_start.offset(), m_end.offset(), ec);
    684         return fragment;
    685     }
    686 
    687     // what is the highest node that partially selects the start / end of the range?
    688     Node* partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot);
    689     Node* partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot);
    690 
    691     // Start and end containers are different.
    692     // There are three possibilities here:
    693     // 1. Start container == commonRoot (End container must be a descendant)
    694     // 2. End container == commonRoot (Start container must be a descendant)
    695     // 3. Neither is commonRoot, they are both descendants
    696     //
    697     // In case 3, we grab everything after the start (up until a direct child
    698     // of commonRoot) into leftContents, and everything before the end (up until
    699     // a direct child of commonRoot) into rightContents. Then we process all
    700     // commonRoot children between leftContents and rightContents
    701     //
    702     // In case 1 or 2, we skip either processing of leftContents or rightContents,
    703     // in which case the last lot of nodes either goes from the first or last
    704     // child of commonRoot.
    705     //
    706     // These are deleted, cloned, or extracted (i.e. both) depending on action.
    707 
    708     RefPtr<Node> leftContents;
    709     if (m_start.container() != commonRoot) {
    710         leftContents = processContentsBetweenOffsets(action, 0, m_start.container(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec);
    711         leftContents = processAncestorsAndTheirSiblings(action, m_start.container(), ProcessContentsForward, leftContents, commonRoot, ec);
    712     }
    713 
    714     RefPtr<Node> rightContents;
    715     if (m_end.container() != commonRoot) {
    716         rightContents = processContentsBetweenOffsets(action, 0, m_end.container(), 0, m_end.offset(), ec);
    717         rightContents = processAncestorsAndTheirSiblings(action, m_end.container(), ProcessContentsBackward, rightContents, commonRoot, ec);
    718     }
    719 
    720     // delete all children of commonRoot between the start and end container
    721     Node* processStart = childOfCommonRootBeforeOffset(m_start.container(), m_start.offset(), commonRoot);
    722     if (m_start.container() != commonRoot) // processStart contains nodes before m_start.
    723         processStart = processStart->nextSibling();
    724     Node* processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.offset(), commonRoot);
    725 
    726     // Collapse the range, making sure that the result is not within a node that was partially selected.
    727     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
    728         if (partialStart)
    729             setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec);
    730         else if (partialEnd)
    731             setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec);
    732         if (ec)
    733             return 0;
    734         m_end = m_start;
    735     }
    736 
    737     // Now add leftContents, stuff in between, and rightContents to the fragment
    738     // (or just delete the stuff in between)
    739 
    740     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
    741         fragment->appendChild(leftContents, ec);
    742 
    743     if (processStart) {
    744         NodeVector nodes;
    745         for (Node* n = processStart; n && n != processEnd; n = n->nextSibling())
    746             nodes.append(n);
    747         processNodes(action, nodes, commonRoot, fragment, ec);
    748     }
    749 
    750     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
    751         fragment->appendChild(rightContents, ec);
    752 
    753     return fragment.release();
    754 }
    755 
    756 static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
    757 {
    758     if (data->length() - endOffset)
    759         data->deleteData(endOffset, data->length() - endOffset, ec);
    760     if (startOffset)
    761         data->deleteData(0, startOffset, ec);
    762 }
    763 
    764 PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment,
    765     Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec)
    766 {
    767     ASSERT(container);
    768     ASSERT(startOffset <= endOffset);
    769 
    770     // This switch statement must be consistent with that of lengthOfContentsInNode.
    771     RefPtr<Node> result;
    772     switch (container->nodeType()) {
    773     case Node::TEXT_NODE:
    774     case Node::CDATA_SECTION_NODE:
    775     case Node::COMMENT_NODE:
    776         ASSERT(endOffset <= static_cast<CharacterData*>(container)->length());
    777         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    778             RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true));
    779             deleteCharacterData(c, startOffset, endOffset, ec);
    780             if (fragment) {
    781                 result = fragment;
    782                 result->appendChild(c.release(), ec);
    783             } else
    784                 result = c.release();
    785         }
    786         if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
    787             static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, ec);
    788         break;
    789     case Node::PROCESSING_INSTRUCTION_NODE:
    790         ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length());
    791         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    792             RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true));
    793             c->setData(c->data().substring(startOffset, endOffset - startOffset), ec);
    794             if (fragment) {
    795                 result = fragment;
    796                 result->appendChild(c.release(), ec);
    797             } else
    798                 result = c.release();
    799         }
    800         if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
    801             ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container);
    802             String data(pi->data());
    803             data.remove(startOffset, endOffset - startOffset);
    804             pi->setData(data, ec);
    805         }
    806         break;
    807     case Node::ELEMENT_NODE:
    808     case Node::ATTRIBUTE_NODE:
    809     case Node::ENTITY_REFERENCE_NODE:
    810     case Node::ENTITY_NODE:
    811     case Node::DOCUMENT_NODE:
    812     case Node::DOCUMENT_TYPE_NODE:
    813     case Node::DOCUMENT_FRAGMENT_NODE:
    814     case Node::NOTATION_NODE:
    815     case Node::XPATH_NAMESPACE_NODE:
    816         // FIXME: Should we assert that some nodes never appear here?
    817         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    818             if (fragment)
    819                 result = fragment;
    820             else
    821                 result = container->cloneNode(false);
    822         }
    823 
    824         Node* n = container->firstChild();
    825         Vector<RefPtr<Node> > nodes;
    826         for (unsigned i = startOffset; n && i; i--)
    827             n = n->nextSibling();
    828         for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling())
    829             nodes.append(n);
    830 
    831         processNodes(action, nodes, container, result, ec);
    832         break;
    833     }
    834 
    835     return result;
    836 }
    837 
    838 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec)
    839 {
    840     for (unsigned i = 0; i < nodes.size(); i++) {
    841         switch (action) {
    842         case DELETE_CONTENTS:
    843             oldContainer->removeChild(nodes[i].get(), ec);
    844             break;
    845         case EXTRACT_CONTENTS:
    846             newContainer->appendChild(nodes[i].release(), ec); // will remove n from its parent
    847             break;
    848         case CLONE_CONTENTS:
    849             newContainer->appendChild(nodes[i]->cloneNode(true), ec);
    850             break;
    851         }
    852     }
    853 }
    854 
    855 PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedContainer, Node* commonRoot, ExceptionCode& ec)
    856 {
    857     RefPtr<Node> clonedContainer = passedClonedContainer;
    858     Vector<RefPtr<Node> > ancestors;
    859     for (ContainerNode* n = container->parentNode(); n && n != commonRoot; n = n->parentNode())
    860         ancestors.append(n);
    861 
    862     RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsForward ? container->nextSibling() : container->previousSibling();
    863     for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != ancestors.end(); it++) {
    864         RefPtr<Node> ancestor = *it;
    865         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    866             if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // Might have been removed already during mutation event.
    867                 clonedAncestor->appendChild(clonedContainer, ec);
    868                 clonedContainer = clonedAncestor;
    869             }
    870         }
    871 
    872         // Copy siblings of an ancestor of start/end containers
    873         // FIXME: This assertion may fail if DOM is modified during mutation event
    874         // FIXME: Share code with Range::processNodes
    875         ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor);
    876         RefPtr<Node> next;
    877         for (Node* child = firstChildInAncestorToProcess.get(); child; child = next.get()) {
    878             next = direction == ProcessContentsForward ? child->nextSibling() : child->previousSibling();
    879             switch (action) {
    880             case DELETE_CONTENTS:
    881                 ancestor->removeChild(child, ec);
    882                 break;
    883             case EXTRACT_CONTENTS: // will remove child from ancestor
    884                 if (direction == ProcessContentsForward)
    885                     clonedContainer->appendChild(child, ec);
    886                 else
    887                     clonedContainer->insertBefore(child, clonedContainer->firstChild(), ec);
    888                 break;
    889             case CLONE_CONTENTS:
    890                 if (direction == ProcessContentsForward)
    891                     clonedContainer->appendChild(child->cloneNode(true), ec);
    892                 else
    893                     clonedContainer->insertBefore(child->cloneNode(true), clonedContainer->firstChild(), ec);
    894                 break;
    895             }
    896         }
    897         firstChildInAncestorToProcess = direction == ProcessContentsForward ? ancestor->nextSibling() : ancestor->previousSibling();
    898     }
    899 
    900     return clonedContainer;
    901 }
    902 
    903 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
    904 {
    905     checkDeleteExtract(ec);
    906     if (ec)
    907         return 0;
    908 
    909     return processContents(EXTRACT_CONTENTS, ec);
    910 }
    911 
    912 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionCode& ec)
    913 {
    914     if (!m_start.container()) {
    915         ec = INVALID_STATE_ERR;
    916         return 0;
    917     }
    918 
    919     return processContents(CLONE_CONTENTS, ec);
    920 }
    921 
    922 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec)
    923 {
    924     RefPtr<Node> newNode = prpNewNode;
    925 
    926     ec = 0;
    927 
    928     if (!m_start.container()) {
    929         ec = INVALID_STATE_ERR;
    930         return;
    931     }
    932 
    933     if (!newNode) {
    934         ec = NOT_FOUND_ERR;
    935         return;
    936     }
    937 
    938     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
    939     // the Range is read-only.
    940     if (containedByReadOnly()) {
    941         ec = NO_MODIFICATION_ALLOWED_ERR;
    942         return;
    943     }
    944 
    945     // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
    946     // does not allow children of the type of newNode or if newNode is an ancestor of the container.
    947 
    948     // an extra one here - if a text node is going to split, it must have a parent to insert into
    949     bool startIsText = m_start.container()->isTextNode();
    950     if (startIsText && !m_start.container()->parentNode()) {
    951         ec = HIERARCHY_REQUEST_ERR;
    952         return;
    953     }
    954 
    955     // In the case where the container is a text node, we check against the container's parent, because
    956     // text nodes get split up upon insertion.
    957     Node* checkAgainst;
    958     if (startIsText)
    959         checkAgainst = m_start.container()->parentNode();
    960     else
    961         checkAgainst = m_start.container();
    962 
    963     Node::NodeType newNodeType = newNode->nodeType();
    964     int numNewChildren;
    965     if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) {
    966         // check each child node, not the DocumentFragment itself
    967         numNewChildren = 0;
    968         for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) {
    969             if (!checkAgainst->childTypeAllowed(c->nodeType())) {
    970                 ec = HIERARCHY_REQUEST_ERR;
    971                 return;
    972             }
    973             ++numNewChildren;
    974         }
    975     } else {
    976         numNewChildren = 1;
    977         if (!checkAgainst->childTypeAllowed(newNodeType)) {
    978             ec = HIERARCHY_REQUEST_ERR;
    979             return;
    980         }
    981     }
    982 
    983     for (Node* n = m_start.container(); n; n = n->parentNode()) {
    984         if (n == newNode) {
    985             ec = HIERARCHY_REQUEST_ERR;
    986             return;
    987         }
    988     }
    989 
    990     // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
    991     if (newNodeType == Node::ATTRIBUTE_NODE || newNodeType == Node::ENTITY_NODE
    992             || newNodeType == Node::NOTATION_NODE || newNodeType == Node::DOCUMENT_NODE) {
    993         ec = RangeException::INVALID_NODE_TYPE_ERR;
    994         return;
    995     }
    996 
    997     bool collapsed = m_start == m_end;
    998     if (startIsText) {
    999         RefPtr<Text> newText = static_cast<Text*>(m_start.container())->splitText(m_start.offset(), ec);
   1000         if (ec)
   1001             return;
   1002         m_start.container()->parentNode()->insertBefore(newNode.release(), newText.get(), ec);
   1003         if (ec)
   1004             return;
   1005 
   1006         // This special case doesn't seem to match the DOM specification, but it's currently required
   1007         // to pass Acid3. We might later decide to remove this.
   1008         if (collapsed)
   1009             m_end.setToBeforeChild(newText.get());
   1010     } else {
   1011         RefPtr<Node> lastChild;
   1012         if (collapsed)
   1013             lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
   1014 
   1015         int startOffset = m_start.offset();
   1016         m_start.container()->insertBefore(newNode.release(), m_start.container()->childNode(startOffset), ec);
   1017         if (ec)
   1018             return;
   1019 
   1020         // This special case doesn't seem to match the DOM specification, but it's currently required
   1021         // to pass Acid3. We might later decide to remove this.
   1022         if (collapsed)
   1023             m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get());
   1024     }
   1025 }
   1026 
   1027 String Range::toString(ExceptionCode& ec) const
   1028 {
   1029     if (!m_start.container()) {
   1030         ec = INVALID_STATE_ERR;
   1031         return String();
   1032     }
   1033 
   1034     Vector<UChar> result;
   1035 
   1036     Node* pastLast = pastLastNode();
   1037     for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) {
   1038         if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
   1039             String data = static_cast<CharacterData*>(n)->data();
   1040             int length = data.length();
   1041             int start = (n == m_start.container()) ? min(max(0, m_start.offset()), length) : 0;
   1042             int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
   1043             result.append(data.characters() + start, end - start);
   1044         }
   1045     }
   1046 
   1047     return String::adopt(result);
   1048 }
   1049 
   1050 String Range::toHTML() const
   1051 {
   1052     return createMarkup(this);
   1053 }
   1054 
   1055 String Range::text() const
   1056 {
   1057     if (!m_start.container())
   1058         return String();
   1059 
   1060     // We need to update layout, since plainText uses line boxes in the render tree.
   1061     // FIXME: As with innerText, we'd like this to work even if there are no render objects.
   1062     m_start.container()->document()->updateLayout();
   1063 
   1064     return plainText(this);
   1065 }
   1066 
   1067 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionCode& ec) const
   1068 {
   1069     if (!m_start.container()) {
   1070         ec = INVALID_STATE_ERR;
   1071         return 0;
   1072     }
   1073 
   1074     Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
   1075     if (!element || !element->isHTMLElement()) {
   1076         ec = NOT_SUPPORTED_ERR;
   1077         return 0;
   1078     }
   1079 
   1080     // Logic from deprecatedCreateContextualFragment should just be moved into
   1081     // this function.  Range::createContextualFragment semantics do not make
   1082     // sense for the rest of the DOM implementation to use.
   1083     RefPtr<DocumentFragment> fragment = toHTMLElement(element)->deprecatedCreateContextualFragment(markup);
   1084     if (!fragment) {
   1085         ec = NOT_SUPPORTED_ERR;
   1086         return 0;
   1087     }
   1088 
   1089     return fragment.release();
   1090 }
   1091 
   1092 
   1093 void Range::detach(ExceptionCode& ec)
   1094 {
   1095     // Check first to see if we've already detached:
   1096     if (!m_start.container()) {
   1097         ec = INVALID_STATE_ERR;
   1098         return;
   1099     }
   1100 
   1101     m_ownerDocument->detachRange(this);
   1102 
   1103     m_start.clear();
   1104     m_end.clear();
   1105 }
   1106 
   1107 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionCode& ec) const
   1108 {
   1109     switch (n->nodeType()) {
   1110         case Node::DOCUMENT_TYPE_NODE:
   1111         case Node::ENTITY_NODE:
   1112         case Node::NOTATION_NODE:
   1113             ec = RangeException::INVALID_NODE_TYPE_ERR;
   1114             return 0;
   1115         case Node::CDATA_SECTION_NODE:
   1116         case Node::COMMENT_NODE:
   1117         case Node::TEXT_NODE:
   1118             if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length())
   1119                 ec = INDEX_SIZE_ERR;
   1120             return 0;
   1121         case Node::PROCESSING_INSTRUCTION_NODE:
   1122             if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length())
   1123                 ec = INDEX_SIZE_ERR;
   1124             return 0;
   1125         case Node::ATTRIBUTE_NODE:
   1126         case Node::DOCUMENT_FRAGMENT_NODE:
   1127         case Node::DOCUMENT_NODE:
   1128         case Node::ELEMENT_NODE:
   1129         case Node::ENTITY_REFERENCE_NODE:
   1130         case Node::XPATH_NAMESPACE_NODE: {
   1131             if (!offset)
   1132                 return 0;
   1133             Node* childBefore = n->childNode(offset - 1);
   1134             if (!childBefore)
   1135                 ec = INDEX_SIZE_ERR;
   1136             return childBefore;
   1137         }
   1138     }
   1139     ASSERT_NOT_REACHED();
   1140     return 0;
   1141 }
   1142 
   1143 void Range::checkNodeBA(Node* n, ExceptionCode& ec) const
   1144 {
   1145     // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
   1146     // Attr, Document or DocumentFragment node or part of a shadow DOM tree
   1147     // or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation node.
   1148 
   1149     switch (n->nodeType()) {
   1150         case Node::ATTRIBUTE_NODE:
   1151         case Node::DOCUMENT_FRAGMENT_NODE:
   1152         case Node::DOCUMENT_NODE:
   1153         case Node::ENTITY_NODE:
   1154         case Node::NOTATION_NODE:
   1155             ec = RangeException::INVALID_NODE_TYPE_ERR;
   1156             return;
   1157         case Node::CDATA_SECTION_NODE:
   1158         case Node::COMMENT_NODE:
   1159         case Node::DOCUMENT_TYPE_NODE:
   1160         case Node::ELEMENT_NODE:
   1161         case Node::ENTITY_REFERENCE_NODE:
   1162         case Node::PROCESSING_INSTRUCTION_NODE:
   1163         case Node::TEXT_NODE:
   1164         case Node::XPATH_NAMESPACE_NODE:
   1165             break;
   1166     }
   1167 
   1168     Node* root = n;
   1169     while (ContainerNode* parent = root->parentNode())
   1170         root = parent;
   1171 
   1172     switch (root->nodeType()) {
   1173         case Node::ATTRIBUTE_NODE:
   1174         case Node::DOCUMENT_NODE:
   1175         case Node::DOCUMENT_FRAGMENT_NODE:
   1176             break;
   1177         case Node::CDATA_SECTION_NODE:
   1178         case Node::COMMENT_NODE:
   1179         case Node::DOCUMENT_TYPE_NODE:
   1180         case Node::ELEMENT_NODE:
   1181         case Node::ENTITY_NODE:
   1182         case Node::ENTITY_REFERENCE_NODE:
   1183         case Node::NOTATION_NODE:
   1184         case Node::PROCESSING_INSTRUCTION_NODE:
   1185         case Node::TEXT_NODE:
   1186         case Node::XPATH_NAMESPACE_NODE:
   1187             if (root->isShadowRoot())
   1188                 break;
   1189             ec = RangeException::INVALID_NODE_TYPE_ERR;
   1190             return;
   1191     }
   1192 }
   1193 
   1194 PassRefPtr<Range> Range::cloneRange(ExceptionCode& ec) const
   1195 {
   1196     if (!m_start.container()) {
   1197         ec = INVALID_STATE_ERR;
   1198         return 0;
   1199     }
   1200 
   1201     return Range::create(m_ownerDocument, m_start.container(), m_start.offset(), m_end.container(), m_end.offset());
   1202 }
   1203 
   1204 void Range::setStartAfter(Node* refNode, ExceptionCode& ec)
   1205 {
   1206     if (!m_start.container()) {
   1207         ec = INVALID_STATE_ERR;
   1208         return;
   1209     }
   1210 
   1211     if (!refNode) {
   1212         ec = NOT_FOUND_ERR;
   1213         return;
   1214     }
   1215 
   1216     if (refNode->document() != m_ownerDocument) {
   1217         ec = WRONG_DOCUMENT_ERR;
   1218         return;
   1219     }
   1220 
   1221     ec = 0;
   1222     checkNodeBA(refNode, ec);
   1223     if (ec)
   1224         return;
   1225 
   1226     setStart(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
   1227 }
   1228 
   1229 void Range::setEndBefore(Node* refNode, ExceptionCode& ec)
   1230 {
   1231     if (!m_start.container()) {
   1232         ec = INVALID_STATE_ERR;
   1233         return;
   1234     }
   1235 
   1236     if (!refNode) {
   1237         ec = NOT_FOUND_ERR;
   1238         return;
   1239     }
   1240 
   1241     if (refNode->document() != m_ownerDocument) {
   1242         ec = WRONG_DOCUMENT_ERR;
   1243         return;
   1244     }
   1245 
   1246     ec = 0;
   1247     checkNodeBA(refNode, ec);
   1248     if (ec)
   1249         return;
   1250 
   1251     setEnd(refNode->parentNode(), refNode->nodeIndex(), ec);
   1252 }
   1253 
   1254 void Range::setEndAfter(Node* refNode, ExceptionCode& ec)
   1255 {
   1256     if (!m_start.container()) {
   1257         ec = INVALID_STATE_ERR;
   1258         return;
   1259     }
   1260 
   1261     if (!refNode) {
   1262         ec = NOT_FOUND_ERR;
   1263         return;
   1264     }
   1265 
   1266     if (refNode->document() != m_ownerDocument) {
   1267         ec = WRONG_DOCUMENT_ERR;
   1268         return;
   1269     }
   1270 
   1271     ec = 0;
   1272     checkNodeBA(refNode, ec);
   1273     if (ec)
   1274         return;
   1275 
   1276     setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, ec);
   1277 
   1278 }
   1279 
   1280 void Range::selectNode(Node* refNode, ExceptionCode& ec)
   1281 {
   1282     if (!m_start.container()) {
   1283         ec = INVALID_STATE_ERR;
   1284         return;
   1285     }
   1286 
   1287     if (!refNode) {
   1288         ec = NOT_FOUND_ERR;
   1289         return;
   1290     }
   1291 
   1292     // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
   1293     // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
   1294     // node.
   1295     for (ContainerNode* anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
   1296         switch (anc->nodeType()) {
   1297             case Node::ATTRIBUTE_NODE:
   1298             case Node::CDATA_SECTION_NODE:
   1299             case Node::COMMENT_NODE:
   1300             case Node::DOCUMENT_FRAGMENT_NODE:
   1301             case Node::DOCUMENT_NODE:
   1302             case Node::ELEMENT_NODE:
   1303             case Node::ENTITY_REFERENCE_NODE:
   1304             case Node::PROCESSING_INSTRUCTION_NODE:
   1305             case Node::TEXT_NODE:
   1306             case Node::XPATH_NAMESPACE_NODE:
   1307                 break;
   1308             case Node::DOCUMENT_TYPE_NODE:
   1309             case Node::ENTITY_NODE:
   1310             case Node::NOTATION_NODE:
   1311                 ec = RangeException::INVALID_NODE_TYPE_ERR;
   1312                 return;
   1313         }
   1314     }
   1315 
   1316     switch (refNode->nodeType()) {
   1317         case Node::CDATA_SECTION_NODE:
   1318         case Node::COMMENT_NODE:
   1319         case Node::DOCUMENT_TYPE_NODE:
   1320         case Node::ELEMENT_NODE:
   1321         case Node::ENTITY_REFERENCE_NODE:
   1322         case Node::PROCESSING_INSTRUCTION_NODE:
   1323         case Node::TEXT_NODE:
   1324         case Node::XPATH_NAMESPACE_NODE:
   1325             break;
   1326         case Node::ATTRIBUTE_NODE:
   1327         case Node::DOCUMENT_FRAGMENT_NODE:
   1328         case Node::DOCUMENT_NODE:
   1329         case Node::ENTITY_NODE:
   1330         case Node::NOTATION_NODE:
   1331             ec = RangeException::INVALID_NODE_TYPE_ERR;
   1332             return;
   1333     }
   1334 
   1335     if (m_ownerDocument != refNode->document())
   1336         setDocument(refNode->document());
   1337 
   1338     ec = 0;
   1339     setStartBefore(refNode, ec);
   1340     if (ec)
   1341         return;
   1342     setEndAfter(refNode, ec);
   1343 }
   1344 
   1345 void Range::selectNodeContents(Node* refNode, ExceptionCode& ec)
   1346 {
   1347     if (!m_start.container()) {
   1348         ec = INVALID_STATE_ERR;
   1349         return;
   1350     }
   1351 
   1352     if (!refNode) {
   1353         ec = NOT_FOUND_ERR;
   1354         return;
   1355     }
   1356 
   1357     // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
   1358     // or DocumentType node.
   1359     for (Node* n = refNode; n; n = n->parentNode()) {
   1360         switch (n->nodeType()) {
   1361             case Node::ATTRIBUTE_NODE:
   1362             case Node::CDATA_SECTION_NODE:
   1363             case Node::COMMENT_NODE:
   1364             case Node::DOCUMENT_FRAGMENT_NODE:
   1365             case Node::DOCUMENT_NODE:
   1366             case Node::ELEMENT_NODE:
   1367             case Node::ENTITY_REFERENCE_NODE:
   1368             case Node::PROCESSING_INSTRUCTION_NODE:
   1369             case Node::TEXT_NODE:
   1370             case Node::XPATH_NAMESPACE_NODE:
   1371                 break;
   1372             case Node::DOCUMENT_TYPE_NODE:
   1373             case Node::ENTITY_NODE:
   1374             case Node::NOTATION_NODE:
   1375                 ec = RangeException::INVALID_NODE_TYPE_ERR;
   1376                 return;
   1377         }
   1378     }
   1379 
   1380     if (m_ownerDocument != refNode->document())
   1381         setDocument(refNode->document());
   1382 
   1383     m_start.setToStartOfNode(refNode);
   1384     m_end.setToEndOfNode(refNode);
   1385 }
   1386 
   1387 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec)
   1388 {
   1389     RefPtr<Node> newParent = passNewParent;
   1390 
   1391     if (!m_start.container()) {
   1392         ec = INVALID_STATE_ERR;
   1393         return;
   1394     }
   1395 
   1396     if (!newParent) {
   1397         ec = NOT_FOUND_ERR;
   1398         return;
   1399     }
   1400 
   1401     // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
   1402     // Document, or DocumentFragment node.
   1403     switch (newParent->nodeType()) {
   1404         case Node::ATTRIBUTE_NODE:
   1405         case Node::DOCUMENT_FRAGMENT_NODE:
   1406         case Node::DOCUMENT_NODE:
   1407         case Node::DOCUMENT_TYPE_NODE:
   1408         case Node::ENTITY_NODE:
   1409         case Node::NOTATION_NODE:
   1410             ec = RangeException::INVALID_NODE_TYPE_ERR;
   1411             return;
   1412         case Node::CDATA_SECTION_NODE:
   1413         case Node::COMMENT_NODE:
   1414         case Node::ELEMENT_NODE:
   1415         case Node::ENTITY_REFERENCE_NODE:
   1416         case Node::PROCESSING_INSTRUCTION_NODE:
   1417         case Node::TEXT_NODE:
   1418         case Node::XPATH_NAMESPACE_NODE:
   1419             break;
   1420     }
   1421 
   1422     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
   1423     // the Range is read-only.
   1424     if (containedByReadOnly()) {
   1425         ec = NO_MODIFICATION_ALLOWED_ERR;
   1426         return;
   1427     }
   1428 
   1429     // Raise a HIERARCHY_REQUEST_ERR if m_start.container() doesn't accept children like newParent.
   1430     Node* parentOfNewParent = m_start.container();
   1431 
   1432     // If m_start.container() is a character data node, it will be split and it will be its parent that will
   1433     // need to accept newParent (or in the case of a comment, it logically "would" be inserted into the parent,
   1434     // although this will fail below for another reason).
   1435     if (parentOfNewParent->isCharacterDataNode())
   1436         parentOfNewParent = parentOfNewParent->parentNode();
   1437     if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->nodeType())) {
   1438         ec = HIERARCHY_REQUEST_ERR;
   1439         return;
   1440     }
   1441 
   1442     if (m_start.container() == newParent || m_start.container()->isDescendantOf(newParent.get())) {
   1443         ec = HIERARCHY_REQUEST_ERR;
   1444         return;
   1445     }
   1446 
   1447     // FIXME: Do we need a check if the node would end up with a child node of a type not
   1448     // allowed by the type of node?
   1449 
   1450     // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text node.
   1451     Node* startNonTextContainer = m_start.container();
   1452     if (startNonTextContainer->nodeType() == Node::TEXT_NODE)
   1453         startNonTextContainer = startNonTextContainer->parentNode();
   1454     Node* endNonTextContainer = m_end.container();
   1455     if (endNonTextContainer->nodeType() == Node::TEXT_NODE)
   1456         endNonTextContainer = endNonTextContainer->parentNode();
   1457     if (startNonTextContainer != endNonTextContainer) {
   1458         ec = RangeException::BAD_BOUNDARYPOINTS_ERR;
   1459         return;
   1460     }
   1461 
   1462     ec = 0;
   1463     while (Node* n = newParent->firstChild()) {
   1464         toContainerNode(newParent.get())->removeChild(n, ec);
   1465         if (ec)
   1466             return;
   1467     }
   1468     RefPtr<DocumentFragment> fragment = extractContents(ec);
   1469     if (ec)
   1470         return;
   1471     insertNode(newParent, ec);
   1472     if (ec)
   1473         return;
   1474     newParent->appendChild(fragment.release(), ec);
   1475     if (ec)
   1476         return;
   1477     selectNode(newParent.get(), ec);
   1478 }
   1479 
   1480 void Range::setStartBefore(Node* refNode, ExceptionCode& ec)
   1481 {
   1482     if (!m_start.container()) {
   1483         ec = INVALID_STATE_ERR;
   1484         return;
   1485     }
   1486 
   1487     if (!refNode) {
   1488         ec = NOT_FOUND_ERR;
   1489         return;
   1490     }
   1491 
   1492     if (refNode->document() != m_ownerDocument) {
   1493         ec = WRONG_DOCUMENT_ERR;
   1494         return;
   1495     }
   1496 
   1497     ec = 0;
   1498     checkNodeBA(refNode, ec);
   1499     if (ec)
   1500         return;
   1501 
   1502     setStart(refNode->parentNode(), refNode->nodeIndex(), ec);
   1503 }
   1504 
   1505 void Range::checkDeleteExtract(ExceptionCode& ec)
   1506 {
   1507     if (!m_start.container()) {
   1508         ec = INVALID_STATE_ERR;
   1509         return;
   1510     }
   1511 
   1512     ec = 0;
   1513     if (!commonAncestorContainer(ec) || ec)
   1514         return;
   1515 
   1516     Node* pastLast = pastLastNode();
   1517     for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) {
   1518         if (n->isReadOnlyNode()) {
   1519             ec = NO_MODIFICATION_ALLOWED_ERR;
   1520             return;
   1521         }
   1522         if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
   1523             ec = HIERARCHY_REQUEST_ERR;
   1524             return;
   1525         }
   1526     }
   1527 
   1528     if (containedByReadOnly()) {
   1529         ec = NO_MODIFICATION_ALLOWED_ERR;
   1530         return;
   1531     }
   1532 }
   1533 
   1534 bool Range::containedByReadOnly() const
   1535 {
   1536     for (Node* n = m_start.container(); n; n = n->parentNode()) {
   1537         if (n->isReadOnlyNode())
   1538             return true;
   1539     }
   1540     for (Node* n = m_end.container(); n; n = n->parentNode()) {
   1541         if (n->isReadOnlyNode())
   1542             return true;
   1543     }
   1544     return false;
   1545 }
   1546 
   1547 Node* Range::firstNode() const
   1548 {
   1549     if (!m_start.container())
   1550         return 0;
   1551     if (m_start.container()->offsetInCharacters())
   1552         return m_start.container();
   1553     if (Node* child = m_start.container()->childNode(m_start.offset()))
   1554         return child;
   1555     if (!m_start.offset())
   1556         return m_start.container();
   1557     return m_start.container()->traverseNextSibling();
   1558 }
   1559 
   1560 Position Range::editingStartPosition() const
   1561 {
   1562     // This function is used by range style computations to avoid bugs like:
   1563     // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
   1564     // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up
   1565     // with a spurious "mixed" style.
   1566 
   1567     VisiblePosition visiblePosition = Position(m_start.container(), m_start.offset(), Position::PositionIsOffsetInAnchor);
   1568     if (visiblePosition.isNull())
   1569         return Position();
   1570 
   1571     ExceptionCode ec = 0;
   1572     // if the selection is a caret, just return the position, since the style
   1573     // behind us is relevant
   1574     if (collapsed(ec))
   1575         return visiblePosition.deepEquivalent();
   1576 
   1577     // if the selection starts just before a paragraph break, skip over it
   1578     if (isEndOfParagraph(visiblePosition))
   1579         return visiblePosition.next().deepEquivalent().downstream();
   1580 
   1581     // otherwise, make sure to be at the start of the first selected node,
   1582     // instead of possibly at the end of the last node before the selection
   1583     return visiblePosition.deepEquivalent().downstream();
   1584 }
   1585 
   1586 Node* Range::shadowTreeRootNode() const
   1587 {
   1588     return startContainer() ? startContainer()->shadowTreeRootNode() : 0;
   1589 }
   1590 
   1591 Node* Range::pastLastNode() const
   1592 {
   1593     if (!m_start.container() || !m_end.container())
   1594         return 0;
   1595     if (m_end.container()->offsetInCharacters())
   1596         return m_end.container()->traverseNextSibling();
   1597     if (Node* child = m_end.container()->childNode(m_end.offset()))
   1598         return child;
   1599     return m_end.container()->traverseNextSibling();
   1600 }
   1601 
   1602 IntRect Range::boundingBox()
   1603 {
   1604     IntRect result;
   1605     Vector<IntRect> rects;
   1606     textRects(rects);
   1607     const size_t n = rects.size();
   1608     for (size_t i = 0; i < n; ++i)
   1609         result.unite(rects[i]);
   1610     return result;
   1611 }
   1612 
   1613 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight)
   1614 {
   1615     Node* startContainer = m_start.container();
   1616     Node* endContainer = m_end.container();
   1617 
   1618     if (!startContainer || !endContainer)
   1619         return;
   1620 
   1621     Node* stopNode = pastLastNode();
   1622     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
   1623         RenderObject* r = node->renderer();
   1624         if (!r || !r->isText())
   1625             continue;
   1626         RenderText* renderText = toRenderText(r);
   1627         int startOffset = node == startContainer ? m_start.offset() : 0;
   1628         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
   1629         renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight);
   1630     }
   1631 }
   1632 
   1633 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight) const
   1634 {
   1635     Node* startContainer = m_start.container();
   1636     Node* endContainer = m_end.container();
   1637 
   1638     if (!startContainer || !endContainer)
   1639         return;
   1640 
   1641     Node* stopNode = pastLastNode();
   1642     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
   1643         RenderObject* r = node->renderer();
   1644         if (!r || !r->isText())
   1645             continue;
   1646         RenderText* renderText = toRenderText(r);
   1647         int startOffset = node == startContainer ? m_start.offset() : 0;
   1648         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
   1649         renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight);
   1650     }
   1651 }
   1652 
   1653 #ifndef NDEBUG
   1654 #define FormatBufferSize 1024
   1655 void Range::formatForDebugger(char* buffer, unsigned length) const
   1656 {
   1657     String result;
   1658     String s;
   1659 
   1660     if (!m_start.container() || !m_end.container())
   1661         result = "<empty>";
   1662     else {
   1663         char s[FormatBufferSize];
   1664         result += "from offset ";
   1665         result += String::number(m_start.offset());
   1666         result += " of ";
   1667         m_start.container()->formatForDebugger(s, FormatBufferSize);
   1668         result += s;
   1669         result += " to offset ";
   1670         result += String::number(m_end.offset());
   1671         result += " of ";
   1672         m_end.container()->formatForDebugger(s, FormatBufferSize);
   1673         result += s;
   1674     }
   1675 
   1676     strncpy(buffer, result.utf8().data(), length - 1);
   1677 }
   1678 #undef FormatBufferSize
   1679 #endif
   1680 
   1681 bool areRangesEqual(const Range* a, const Range* b)
   1682 {
   1683     if (a == b)
   1684         return true;
   1685     if (!a || !b)
   1686         return false;
   1687     return a->startPosition() == b->startPosition() && a->endPosition() == b->endPosition();
   1688 }
   1689 
   1690 PassRefPtr<Range> rangeOfContents(Node* node)
   1691 {
   1692     ASSERT(node);
   1693     RefPtr<Range> range = Range::create(node->document());
   1694     int exception = 0;
   1695     range->selectNodeContents(node, exception);
   1696     return range.release();
   1697 }
   1698 
   1699 int Range::maxStartOffset() const
   1700 {
   1701     if (!m_start.container())
   1702         return 0;
   1703     if (!m_start.container()->offsetInCharacters())
   1704         return m_start.container()->childNodeCount();
   1705     return m_start.container()->maxCharacterOffset();
   1706 }
   1707 
   1708 int Range::maxEndOffset() const
   1709 {
   1710     if (!m_end.container())
   1711         return 0;
   1712     if (!m_end.container()->offsetInCharacters())
   1713         return m_end.container()->childNodeCount();
   1714     return m_end.container()->maxCharacterOffset();
   1715 }
   1716 
   1717 static inline void boundaryNodeChildrenChanged(RangeBoundaryPoint& boundary, ContainerNode* container)
   1718 {
   1719     if (!boundary.childBefore())
   1720         return;
   1721     if (boundary.container() != container)
   1722         return;
   1723     boundary.invalidateOffset();
   1724 }
   1725 
   1726 void Range::nodeChildrenChanged(ContainerNode* container)
   1727 {
   1728     ASSERT(container);
   1729     ASSERT(container->document() == m_ownerDocument);
   1730     boundaryNodeChildrenChanged(m_start, container);
   1731     boundaryNodeChildrenChanged(m_end, container);
   1732 }
   1733 
   1734 static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode* container)
   1735 {
   1736     for (Node* nodeToBeRemoved = container->firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) {
   1737         if (boundary.childBefore() == nodeToBeRemoved) {
   1738             boundary.setToStartOfNode(container);
   1739             return;
   1740         }
   1741 
   1742         for (Node* n = boundary.container(); n; n = n->parentNode()) {
   1743             if (n == nodeToBeRemoved) {
   1744                 boundary.setToStartOfNode(container);
   1745                 return;
   1746             }
   1747         }
   1748     }
   1749 }
   1750 
   1751 void Range::nodeChildrenWillBeRemoved(ContainerNode* container)
   1752 {
   1753     ASSERT(container);
   1754     ASSERT(container->document() == m_ownerDocument);
   1755     boundaryNodeChildrenWillBeRemoved(m_start, container);
   1756     boundaryNodeChildrenWillBeRemoved(m_end, container);
   1757 }
   1758 
   1759 static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved)
   1760 {
   1761     if (boundary.childBefore() == nodeToBeRemoved) {
   1762         boundary.childBeforeWillBeRemoved();
   1763         return;
   1764     }
   1765 
   1766     for (Node* n = boundary.container(); n; n = n->parentNode()) {
   1767         if (n == nodeToBeRemoved) {
   1768             boundary.setToBeforeChild(nodeToBeRemoved);
   1769             return;
   1770         }
   1771     }
   1772 }
   1773 
   1774 void Range::nodeWillBeRemoved(Node* node)
   1775 {
   1776     ASSERT(node);
   1777     ASSERT(node->document() == m_ownerDocument);
   1778     ASSERT(node != m_ownerDocument);
   1779     ASSERT(node->parentNode());
   1780     boundaryNodeWillBeRemoved(m_start, node);
   1781     boundaryNodeWillBeRemoved(m_end, node);
   1782 }
   1783 
   1784 static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
   1785 {
   1786     if (boundary.container() != text)
   1787         return;
   1788     unsigned boundaryOffset = boundary.offset();
   1789     if (offset >= boundaryOffset)
   1790         return;
   1791     boundary.setOffset(boundaryOffset + length);
   1792 }
   1793 
   1794 void Range::textInserted(Node* text, unsigned offset, unsigned length)
   1795 {
   1796     ASSERT(text);
   1797     ASSERT(text->document() == m_ownerDocument);
   1798     boundaryTextInserted(m_start, text, offset, length);
   1799     boundaryTextInserted(m_end, text, offset, length);
   1800 }
   1801 
   1802 static inline void boundaryTextRemoved(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
   1803 {
   1804     if (boundary.container() != text)
   1805         return;
   1806     unsigned boundaryOffset = boundary.offset();
   1807     if (offset >= boundaryOffset)
   1808         return;
   1809     if (offset + length >= boundaryOffset)
   1810         boundary.setOffset(offset);
   1811     else
   1812         boundary.setOffset(boundaryOffset - length);
   1813 }
   1814 
   1815 void Range::textRemoved(Node* text, unsigned offset, unsigned length)
   1816 {
   1817     ASSERT(text);
   1818     ASSERT(text->document() == m_ownerDocument);
   1819     boundaryTextRemoved(m_start, text, offset, length);
   1820     boundaryTextRemoved(m_end, text, offset, length);
   1821 }
   1822 
   1823 static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset)
   1824 {
   1825     if (boundary.container() == oldNode.node())
   1826         boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);
   1827     else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())
   1828         boundary.set(oldNode.node()->previousSibling(), offset, 0);
   1829 }
   1830 
   1831 void Range::textNodesMerged(NodeWithIndex& oldNode, unsigned offset)
   1832 {
   1833     ASSERT(oldNode.node());
   1834     ASSERT(oldNode.node()->document() == m_ownerDocument);
   1835     ASSERT(oldNode.node()->parentNode());
   1836     ASSERT(oldNode.node()->isTextNode());
   1837     ASSERT(oldNode.node()->previousSibling());
   1838     ASSERT(oldNode.node()->previousSibling()->isTextNode());
   1839     boundaryTextNodesMerged(m_start, oldNode, offset);
   1840     boundaryTextNodesMerged(m_end, oldNode, offset);
   1841 }
   1842 
   1843 static inline void boundaryTextNodesSplit(RangeBoundaryPoint& boundary, Text* oldNode)
   1844 {
   1845     if (boundary.container() != oldNode)
   1846         return;
   1847     unsigned boundaryOffset = boundary.offset();
   1848     if (boundaryOffset <= oldNode->length())
   1849         return;
   1850     boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);
   1851 }
   1852 
   1853 void Range::textNodeSplit(Text* oldNode)
   1854 {
   1855     ASSERT(oldNode);
   1856     ASSERT(oldNode->document() == m_ownerDocument);
   1857     ASSERT(oldNode->parentNode());
   1858     ASSERT(oldNode->isTextNode());
   1859     ASSERT(oldNode->nextSibling());
   1860     ASSERT(oldNode->nextSibling()->isTextNode());
   1861     boundaryTextNodesSplit(m_start, oldNode);
   1862     boundaryTextNodesSplit(m_end, oldNode);
   1863 }
   1864 
   1865 void Range::expand(const String& unit, ExceptionCode& ec)
   1866 {
   1867     VisiblePosition start(startPosition());
   1868     VisiblePosition end(endPosition());
   1869     if (unit == "word") {
   1870         start = startOfWord(start);
   1871         end = endOfWord(end);
   1872     } else if (unit == "sentence") {
   1873         start = startOfSentence(start);
   1874         end = endOfSentence(end);
   1875     } else if (unit == "block") {
   1876         start = startOfParagraph(start);
   1877         end = endOfParagraph(end);
   1878     } else if (unit == "document") {
   1879         start = startOfDocument(start);
   1880         end = endOfDocument(end);
   1881     } else
   1882         return;
   1883     setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec);
   1884     setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
   1885 }
   1886 
   1887 PassRefPtr<ClientRectList> Range::getClientRects() const
   1888 {
   1889     if (!m_start.container())
   1890         return 0;
   1891 
   1892     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
   1893 
   1894     Vector<FloatQuad> quads;
   1895     getBorderAndTextQuads(quads);
   1896 
   1897     return ClientRectList::create(quads);
   1898 }
   1899 
   1900 PassRefPtr<ClientRect> Range::getBoundingClientRect() const
   1901 {
   1902     FloatRect rect = boundingRect();
   1903     return rect.isEmpty() ? 0 : ClientRect::create(rect);
   1904 }
   1905 
   1906 static void adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(Vector<FloatQuad>& quads, Document* document, RenderObject* renderer)
   1907 {
   1908     FrameView* view = document->view();
   1909     if (!view)
   1910         return;
   1911 
   1912     float pageScale = 1;
   1913     if (Page* page = document->page()) {
   1914         if (Frame* frame = page->mainFrame())
   1915             pageScale = frame->pageScaleFactor();
   1916     }
   1917 
   1918     IntRect visibleContentRect = view->visibleContentRect();
   1919     for (size_t i = 0; i < quads.size(); ++i) {
   1920         quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
   1921         adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
   1922         if (pageScale != 1)
   1923             adjustFloatQuadForPageScale(quads[i], pageScale);
   1924     }
   1925 }
   1926 
   1927 void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
   1928 {
   1929     Node* startContainer = m_start.container();
   1930     Node* endContainer = m_end.container();
   1931     Node* stopNode = pastLastNode();
   1932 
   1933     HashSet<Node*> nodeSet;
   1934     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
   1935         if (node->isElementNode())
   1936             nodeSet.add(node);
   1937     }
   1938 
   1939     for (Node* node = firstNode(); node != stopNode; node = node->traverseNextNode()) {
   1940         if (node->isElementNode()) {
   1941             if (!nodeSet.contains(node->parentNode())) {
   1942                 if (RenderBoxModelObject* renderBoxModelObject = static_cast<Element*>(node)->renderBoxModelObject()) {
   1943                     Vector<FloatQuad> elementQuads;
   1944                     renderBoxModelObject->absoluteQuads(elementQuads);
   1945                     adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(elementQuads, m_ownerDocument.get(), renderBoxModelObject);
   1946 
   1947                     quads.append(elementQuads);
   1948                 }
   1949             }
   1950         } else if (node->isTextNode()) {
   1951             if (RenderObject* renderer = static_cast<Text*>(node)->renderer()) {
   1952                 RenderText* renderText = toRenderText(renderer);
   1953                 int startOffset = (node == startContainer) ? m_start.offset() : 0;
   1954                 int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX;
   1955 
   1956                 Vector<FloatQuad> textQuads;
   1957                 renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
   1958                 adjustFloatQuadsForScrollAndAbsoluteZoomAndPageScale(textQuads, m_ownerDocument.get(), renderText);
   1959 
   1960                 quads.append(textQuads);
   1961             }
   1962         }
   1963     }
   1964 }
   1965 
   1966 
   1967 FloatRect Range::boundingRect() const
   1968 {
   1969     if (!m_start.container())
   1970         return FloatRect();
   1971 
   1972     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
   1973 
   1974     Vector<FloatQuad> quads;
   1975     getBorderAndTextQuads(quads);
   1976     if (quads.isEmpty())
   1977         return FloatRect();
   1978 
   1979     FloatRect result;
   1980     for (size_t i = 0; i < quads.size(); ++i)
   1981         result.unite(quads[i].boundingBox());
   1982 
   1983     return result;
   1984 }
   1985 
   1986 } // namespace WebCore
   1987 
   1988 #ifndef NDEBUG
   1989 
   1990 void showTree(const WebCore::Range* range)
   1991 {
   1992     if (range && range->boundaryPointsValid()) {
   1993         range->startContainer()->showTreeAndMark(range->startContainer(), "S", range->endContainer(), "E");
   1994         fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset(), range->endOffset());
   1995     }
   1996 }
   1997 
   1998 #endif
   1999