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