webengine/osswebengine/WebCore/dom/Range.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /**
       
     2  * (C) 1999 Lars Knoll (knoll@kde.org)
       
     3  * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
       
     4  * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
       
     5  * (C) 2001 Peter Kelly (pmk@post.com)
       
     6  * Copyright (C) 2004, 2005, 2006, 2007 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 
       
    27 #include "Document.h"
       
    28 #include "DocumentFragment.h"
       
    29 #include "ExceptionCode.h"
       
    30 #include "HTMLElement.h"
       
    31 #include "HTMLNames.h"
       
    32 #include "ProcessingInstruction.h"
       
    33 #include "RangeException.h"
       
    34 #include "RenderBlock.h"
       
    35 #include "Text.h"
       
    36 #include "TextIterator.h"
       
    37 #include "markup.h"
       
    38 #include "visible_units.h"
       
    39 
       
    40 namespace WebCore {
       
    41 
       
    42 using namespace std;
       
    43 using namespace HTMLNames;
       
    44 
       
    45 #ifndef NDEBUG
       
    46 class RangeCounter {
       
    47 public:
       
    48     static unsigned count;
       
    49     ~RangeCounter()
       
    50     {
       
    51         if (count)
       
    52             fprintf(stderr, "LEAK: %u Range\n", count);
       
    53     }
       
    54 };
       
    55 unsigned RangeCounter::count = 0;
       
    56 static RangeCounter rangeCounter;
       
    57 #endif
       
    58 
       
    59 Range::Range(Document* ownerDocument)
       
    60     : m_ownerDocument(ownerDocument)
       
    61     , m_startContainer(ownerDocument)
       
    62     , m_startOffset(0)
       
    63     , m_endContainer(ownerDocument)
       
    64     , m_endOffset(0)
       
    65     , m_detached(false)
       
    66 {
       
    67 #ifndef NDEBUG
       
    68     ++RangeCounter::count;
       
    69 #endif
       
    70 }
       
    71 
       
    72 Range::Range(Document* ownerDocument,
       
    73               Node* startContainer, int startOffset,
       
    74               Node* endContainer, int endOffset)
       
    75     : m_ownerDocument(ownerDocument)
       
    76     , m_startContainer(ownerDocument)
       
    77     , m_startOffset(0)
       
    78     , m_endContainer(ownerDocument)
       
    79     , m_endOffset(0)
       
    80     , m_detached(false)
       
    81 {
       
    82 #ifndef NDEBUG
       
    83     ++RangeCounter::count;
       
    84 #endif
       
    85     // Simply setting the containers and offsets directly would not do any of the checking
       
    86     // that setStart and setEnd do, so we must call those functions.
       
    87     ExceptionCode ec = 0;
       
    88     setStart(startContainer, startOffset, ec);
       
    89     ASSERT(ec == 0);
       
    90     setEnd(endContainer, endOffset, ec);
       
    91     ASSERT(ec == 0);
       
    92 }
       
    93 
       
    94 Range::Range(Document* ownerDocument, const Position& start, const Position& end)
       
    95     : m_ownerDocument(ownerDocument)
       
    96     , m_startContainer(ownerDocument)
       
    97     , m_startOffset(0)
       
    98     , m_endContainer(ownerDocument)
       
    99     , m_endOffset(0)
       
   100     , m_detached(false)
       
   101 {
       
   102 #ifndef NDEBUG
       
   103     ++RangeCounter::count;
       
   104 #endif
       
   105     // Simply setting the containers and offsets directly would not do any of the checking
       
   106     // that setStart and setEnd do, so we must call those functions.
       
   107     ExceptionCode ec = 0;
       
   108     setStart(start.node(), start.offset(), ec);
       
   109     ASSERT(ec == 0);
       
   110     setEnd(end.node(), end.offset(), ec);
       
   111     ASSERT(ec == 0);
       
   112 }
       
   113 
       
   114 Range::~Range()
       
   115 {
       
   116 #ifndef NDEBUG
       
   117     --RangeCounter::count;
       
   118 #endif
       
   119 }
       
   120 
       
   121 Node *Range::startContainer(ExceptionCode& ec) const
       
   122 {
       
   123     if (m_detached) {
       
   124         ec = INVALID_STATE_ERR;
       
   125         return 0;
       
   126     }
       
   127 
       
   128     return m_startContainer.get();
       
   129 }
       
   130 
       
   131 int Range::startOffset(ExceptionCode& ec) const
       
   132 {
       
   133     if (m_detached) {
       
   134         ec = INVALID_STATE_ERR;
       
   135         return 0;
       
   136     }
       
   137 
       
   138     return m_startOffset;
       
   139 }
       
   140 
       
   141 Node *Range::endContainer(ExceptionCode& ec) const
       
   142 {
       
   143     if (m_detached) {
       
   144         ec = INVALID_STATE_ERR;
       
   145         return 0;
       
   146     }
       
   147 
       
   148     return m_endContainer.get();
       
   149 }
       
   150 
       
   151 int Range::endOffset(ExceptionCode& ec) const
       
   152 {
       
   153     if (m_detached) {
       
   154         ec = INVALID_STATE_ERR;
       
   155         return 0;
       
   156     }
       
   157 
       
   158     return m_endOffset;
       
   159 }
       
   160 
       
   161 Node *Range::commonAncestorContainer(ExceptionCode& ec) const
       
   162 {
       
   163     if (m_detached) {
       
   164         ec = INVALID_STATE_ERR;
       
   165         return 0;
       
   166     }
       
   167 
       
   168     Node *com = commonAncestorContainer(m_startContainer.get(), m_endContainer.get());
       
   169     if (!com) //  should never happen
       
   170         ec = WRONG_DOCUMENT_ERR;
       
   171     return com;
       
   172 }
       
   173 
       
   174 Node *Range::commonAncestorContainer(Node *containerA, Node *containerB)
       
   175 {
       
   176     Node *parentStart;
       
   177 
       
   178     for (parentStart = containerA; parentStart; parentStart = parentStart->parentNode()) {
       
   179         Node *parentEnd = containerB;
       
   180         while (parentEnd && (parentStart != parentEnd))
       
   181             parentEnd = parentEnd->parentNode();
       
   182         if (parentStart == parentEnd)
       
   183             break;
       
   184     }
       
   185         
       
   186     return parentStart;
       
   187 }
       
   188 
       
   189 bool Range::collapsed(ExceptionCode& ec) const
       
   190 {
       
   191     if (m_detached) {
       
   192         ec = INVALID_STATE_ERR;
       
   193         return 0;
       
   194     }
       
   195 
       
   196     return (m_startContainer == m_endContainer && m_startOffset == m_endOffset);
       
   197 }
       
   198 
       
   199 void Range::setStart( Node *refNode, int offset, ExceptionCode& ec)
       
   200 {
       
   201     if (m_detached) {
       
   202         ec = INVALID_STATE_ERR;
       
   203         return;
       
   204     }
       
   205 
       
   206     if (!refNode) {
       
   207         ec = NOT_FOUND_ERR;
       
   208         return;
       
   209     }
       
   210 
       
   211     if (refNode->document() != m_ownerDocument) {
       
   212         ec = WRONG_DOCUMENT_ERR;
       
   213         return;
       
   214     }
       
   215 
       
   216     checkNodeWOffset( refNode, offset, ec );
       
   217     if (ec)
       
   218         return;
       
   219 
       
   220     m_startContainer = refNode;
       
   221     m_startOffset = offset;
       
   222 
       
   223     // check if different root container
       
   224     Node* endRootContainer = m_endContainer.get();
       
   225     while (endRootContainer->parentNode())
       
   226         endRootContainer = endRootContainer->parentNode();
       
   227     Node* startRootContainer = m_startContainer.get();
       
   228     while (startRootContainer->parentNode())
       
   229         startRootContainer = startRootContainer->parentNode();
       
   230     if (startRootContainer != endRootContainer)
       
   231         collapse(true, ec);
       
   232     // check if new start after end
       
   233     else if (compareBoundaryPoints(m_startContainer.get(), m_startOffset, m_endContainer.get(), m_endOffset) > 0)
       
   234         collapse(true, ec);
       
   235 }
       
   236 
       
   237 void Range::setEnd( Node *refNode, int offset, ExceptionCode& ec)
       
   238 {
       
   239     if (m_detached) {
       
   240         ec = INVALID_STATE_ERR;
       
   241         return;
       
   242     }
       
   243 
       
   244     if (!refNode) {
       
   245         ec = NOT_FOUND_ERR;
       
   246         return;
       
   247     }
       
   248 
       
   249     if (refNode->document() != m_ownerDocument) {
       
   250         ec = WRONG_DOCUMENT_ERR;
       
   251         return;
       
   252     }
       
   253 
       
   254     checkNodeWOffset( refNode, offset, ec );
       
   255     if (ec)
       
   256         return;
       
   257 
       
   258     m_endContainer = refNode;
       
   259     m_endOffset = offset;
       
   260 
       
   261     // check if different root container
       
   262     Node* endRootContainer = m_endContainer.get();
       
   263     while (endRootContainer->parentNode())
       
   264         endRootContainer = endRootContainer->parentNode();
       
   265     Node* startRootContainer = m_startContainer.get();
       
   266     while (startRootContainer->parentNode())
       
   267         startRootContainer = startRootContainer->parentNode();
       
   268     if (startRootContainer != endRootContainer)
       
   269         collapse(false, ec);
       
   270     // check if new end before start
       
   271     if (compareBoundaryPoints(m_startContainer.get(), m_startOffset, m_endContainer.get(), m_endOffset) > 0)
       
   272         collapse(false, ec);
       
   273 }
       
   274 
       
   275 void Range::collapse( bool toStart, ExceptionCode& ec)
       
   276 {
       
   277     if (m_detached) {
       
   278         ec = INVALID_STATE_ERR;
       
   279         return;
       
   280     }
       
   281 
       
   282     if (toStart) {  // collapse to start
       
   283         m_endContainer = m_startContainer;
       
   284         m_endOffset = m_startOffset;
       
   285     } else {        // collapse to end
       
   286         m_startContainer = m_endContainer;
       
   287         m_startOffset = m_endOffset;
       
   288     }
       
   289 }
       
   290 
       
   291 bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec)
       
   292 {
       
   293     if (!refNode) {
       
   294         ec = NOT_FOUND_ERR;
       
   295         return false;
       
   296     }
       
   297 
       
   298     if (m_detached && refNode->attached()) {
       
   299         ec = INVALID_STATE_ERR;
       
   300         return false;
       
   301     }
       
   302 
       
   303     if (!m_detached && !refNode->attached()) {
       
   304         // firefox doesn't throw an exception for this case; it returns false
       
   305         return false;
       
   306     }
       
   307 
       
   308     if (refNode->document() != m_ownerDocument) {
       
   309         ec = WRONG_DOCUMENT_ERR;
       
   310         return false;
       
   311     }
       
   312 
       
   313     checkNodeWOffset(refNode, offset, ec);
       
   314     if (ec)
       
   315         return false;
       
   316 
       
   317 
       
   318     // point is not before the start and not after the end
       
   319     if ((compareBoundaryPoints(refNode, offset, m_startContainer.get(), m_startOffset) != -1) && 
       
   320         (compareBoundaryPoints(refNode, offset, m_endContainer.get(), m_endOffset) != 1))
       
   321         return true;
       
   322     else
       
   323         return false;
       
   324 }
       
   325 
       
   326 short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec)
       
   327 {
       
   328     // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
       
   329     // This method returns -1, 0 or 1 depending on if the point described by the 
       
   330     // refNode node and an offset within the node is before, same as, or after the range respectively.
       
   331 
       
   332     if (!refNode) {
       
   333         ec = NOT_FOUND_ERR;
       
   334         return 0;
       
   335     }
       
   336 
       
   337     if (m_detached && refNode->attached()) {
       
   338         ec = INVALID_STATE_ERR;
       
   339         return 0;
       
   340     }
       
   341 
       
   342     if (!m_detached && !refNode->attached()) {
       
   343         // firefox doesn't throw an exception for this case; it returns -1
       
   344         return -1;
       
   345     }
       
   346 
       
   347     if (refNode->document() != m_ownerDocument) {
       
   348         ec = WRONG_DOCUMENT_ERR;
       
   349         return 0;
       
   350     }
       
   351 
       
   352     checkNodeWOffset(refNode, offset, ec);
       
   353     if (ec)
       
   354         return 0;
       
   355 
       
   356     // compare to start, and point comes before
       
   357     if (compareBoundaryPoints(refNode, offset, m_startContainer.get(), m_startOffset) == -1)
       
   358         return -1;
       
   359 
       
   360     // compare to end, and point comes after
       
   361     else if (compareBoundaryPoints(refNode, offset, m_endContainer.get(), m_endOffset) == 1)
       
   362         return 1;
       
   363     
       
   364     // point is in the middle of this range, or on the boundary points
       
   365     else
       
   366         return 0;
       
   367 }
       
   368 
       
   369 Range::CompareResults Range::compareNode(Node* refNode, ExceptionCode& ec)
       
   370 {
       
   371     // http://developer.mozilla.org/en/docs/DOM:range.compareNode
       
   372     // This method returns 0, 1, 2, or 3 based on if the node is before, after,
       
   373     // before and after(surrounds), or inside the range, respectively
       
   374 
       
   375     if (!refNode) {
       
   376         ec = NOT_FOUND_ERR;
       
   377         return NODE_BEFORE;
       
   378     }
       
   379     
       
   380     if (m_detached && refNode->attached()) {
       
   381         ec = INVALID_STATE_ERR;
       
   382         return NODE_BEFORE;
       
   383     }
       
   384 
       
   385     if (!m_detached && !refNode->attached()) {
       
   386         // firefox doesn't throw an exception for this case; it returns 0
       
   387         return NODE_BEFORE;
       
   388     }
       
   389 
       
   390     if (refNode->document() != m_ownerDocument) {
       
   391         // firefox doesn't throw an exception for this case; it returns 0
       
   392         return NODE_BEFORE;
       
   393     }
       
   394 
       
   395     Node* parentNode = refNode->parentNode();
       
   396     unsigned nodeIndex = refNode->nodeIndex();
       
   397     
       
   398     if (!parentNode) {
       
   399         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
       
   400         // but we throw to match firefox behavior
       
   401         ec = NOT_FOUND_ERR;
       
   402         return NODE_BEFORE;
       
   403     }
       
   404 
       
   405     if (comparePoint(parentNode, nodeIndex, ec) == -1) { // starts before
       
   406         if (comparePoint(parentNode, nodeIndex + 1, ec) == 1) // ends after the range
       
   407             return NODE_BEFORE_AND_AFTER;
       
   408         return NODE_BEFORE; // ends before or in the range
       
   409     } else { // starts at or after the range start
       
   410         if (comparePoint(parentNode, nodeIndex + 1, ec) == 1) // ends after the range
       
   411             return NODE_AFTER;
       
   412         return NODE_INSIDE; // ends inside the range
       
   413     }
       
   414 }
       
   415 
       
   416 
       
   417 short Range::compareBoundaryPoints(CompareHow how, const Range *sourceRange, ExceptionCode& ec) const
       
   418 {
       
   419     if (m_detached) {
       
   420         ec = INVALID_STATE_ERR;
       
   421         return 0;
       
   422     }
       
   423 
       
   424     if (!sourceRange) {
       
   425         ec = NOT_FOUND_ERR;
       
   426         return 0;
       
   427     }
       
   428 
       
   429     Node *thisCont = commonAncestorContainer(ec);
       
   430     Node *sourceCont = sourceRange->commonAncestorContainer(ec);
       
   431     if (ec)
       
   432         return 0;
       
   433 
       
   434     if (thisCont->document() != sourceCont->document()) {
       
   435         ec = WRONG_DOCUMENT_ERR;
       
   436         return 0;
       
   437     }
       
   438 
       
   439     Node *thisTop = thisCont;
       
   440     Node *sourceTop = sourceCont;
       
   441     while (thisTop->parentNode())
       
   442         thisTop = thisTop->parentNode();
       
   443     while (sourceTop->parentNode())
       
   444         sourceTop = sourceTop->parentNode();
       
   445     if (thisTop != sourceTop) { // in different DocumentFragments
       
   446         ec = WRONG_DOCUMENT_ERR;
       
   447         return 0;
       
   448     }
       
   449 
       
   450     switch(how)
       
   451     {
       
   452     case START_TO_START:
       
   453         return compareBoundaryPoints( m_startContainer.get(), m_startOffset,
       
   454                                       sourceRange->startContainer(ec), sourceRange->startOffset(ec) );
       
   455         break;
       
   456     case START_TO_END:
       
   457         return compareBoundaryPoints( m_startContainer.get(), m_startOffset,
       
   458                                       sourceRange->endContainer(ec), sourceRange->endOffset(ec) );
       
   459         break;
       
   460     case END_TO_END:
       
   461         return compareBoundaryPoints( m_endContainer.get(), m_endOffset,
       
   462                                       sourceRange->endContainer(ec), sourceRange->endOffset(ec) );
       
   463         break;
       
   464     case END_TO_START:
       
   465         return compareBoundaryPoints( m_endContainer.get(), m_endOffset,
       
   466                                       sourceRange->startContainer(ec), sourceRange->startOffset(ec) );
       
   467         break;
       
   468     default:
       
   469         ec = SYNTAX_ERR;
       
   470         return 0;
       
   471     }
       
   472 }
       
   473 
       
   474 short Range::compareBoundaryPoints( Node *containerA, int offsetA, Node *containerB, int offsetB )
       
   475 {
       
   476     ASSERT(containerA && containerB);
       
   477     if (!containerA)
       
   478         return -1;
       
   479     if (!containerB)
       
   480         return 1;
       
   481     // see DOM2 traversal & range section 2.5
       
   482 
       
   483     // case 1: both points have the same container
       
   484     if(containerA == containerB) {
       
   485         if (offsetA == offsetB)
       
   486             return 0;           // A is equal to B
       
   487         if (offsetA < offsetB)
       
   488             return -1;          // A is before B
       
   489         else
       
   490             return 1;           // A is after B
       
   491     }
       
   492 
       
   493     // case 2: node C (container B or an ancestor) is a child node of A
       
   494     Node *c = containerB;
       
   495     while (c && c->parentNode() != containerA)
       
   496         c = c->parentNode();
       
   497     if (c) {
       
   498         int offsetC = 0;
       
   499         Node *n = containerA->firstChild();
       
   500         while (n != c && offsetC < offsetA) {
       
   501             offsetC++;
       
   502             n = n->nextSibling();
       
   503         }
       
   504 
       
   505         if (offsetA <= offsetC)
       
   506             return -1;              // A is before B
       
   507         else
       
   508             return 1;               // A is after B
       
   509     }
       
   510 
       
   511     // case 3: node C (container A or an ancestor) is a child node of B
       
   512     c = containerA;
       
   513     while (c && c->parentNode() != containerB)
       
   514         c = c->parentNode();
       
   515     if (c) {
       
   516         int offsetC = 0;
       
   517         Node *n = containerB->firstChild();
       
   518         while (n != c && offsetC < offsetB) {
       
   519             offsetC++;
       
   520             n = n->nextSibling();
       
   521         }
       
   522 
       
   523         if(offsetC < offsetB)
       
   524             return -1;              // A is before B
       
   525         else
       
   526             return 1;               // A is after B
       
   527     }
       
   528 
       
   529     // case 4: containers A & B are siblings, or children of siblings
       
   530     // ### we need to do a traversal here instead
       
   531     Node *cmnRoot = commonAncestorContainer(containerA,containerB);
       
   532     if (!cmnRoot)
       
   533         return 0;
       
   534     Node *childA = containerA;
       
   535     while (childA && childA->parentNode() != cmnRoot)
       
   536         childA = childA->parentNode();
       
   537     if (!childA)
       
   538         childA = cmnRoot;
       
   539     Node *childB = containerB;
       
   540     while (childB && childB->parentNode() != cmnRoot)
       
   541         childB = childB->parentNode();
       
   542     if (!childB)
       
   543         childB = cmnRoot;
       
   544 
       
   545     if (childA == childB)
       
   546         return 0; // A is equal to B
       
   547 
       
   548     Node *n = cmnRoot->firstChild();
       
   549     while (n) {
       
   550         if (n == childA)
       
   551             return -1; // A is before B
       
   552         if (n == childB)
       
   553             return 1; // A is after B
       
   554         n = n->nextSibling();
       
   555     }
       
   556 
       
   557     // Should never reach this point.
       
   558     ASSERT(0);
       
   559     return 0;
       
   560 }
       
   561 
       
   562 short Range::compareBoundaryPoints( const Position &a, const Position &b )
       
   563 {
       
   564     return compareBoundaryPoints(a.node(), a.offset(), b.node(), b.offset());
       
   565 }
       
   566 
       
   567 bool Range::boundaryPointsValid() const
       
   568 {
       
   569     return m_startContainer && m_endContainer && compareBoundaryPoints(m_startContainer.get(), m_startOffset, m_endContainer.get(), m_endOffset) <= 0;
       
   570 }
       
   571 
       
   572 void Range::deleteContents(ExceptionCode& ec) {
       
   573     if (m_detached) {
       
   574         ec = INVALID_STATE_ERR;
       
   575         return;
       
   576     }
       
   577 
       
   578     checkDeleteExtract(ec);
       
   579     if (ec)
       
   580         return;
       
   581 
       
   582     processContents(DELETE_CONTENTS,ec);
       
   583 }
       
   584 
       
   585 bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
       
   586 {
       
   587     // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
       
   588     // Returns a bool if the node intersects the range.
       
   589 
       
   590     if (!refNode) {
       
   591         ec = NOT_FOUND_ERR;
       
   592         return false;
       
   593     }
       
   594     
       
   595     if (m_detached && refNode->attached() ||
       
   596         !m_detached && !refNode->attached() ||
       
   597         refNode->document() != m_ownerDocument)
       
   598         // firefox doesn't throw an exception for these case; it returns false
       
   599         return false;
       
   600 
       
   601     Node* parentNode = refNode->parentNode();
       
   602     unsigned nodeIndex = refNode->nodeIndex();
       
   603     
       
   604     if (!parentNode) {
       
   605         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
       
   606         // but we throw to match firefox behavior
       
   607         ec = NOT_FOUND_ERR;
       
   608         return false;
       
   609     }
       
   610 
       
   611     if (comparePoint(parentNode, nodeIndex, ec) == -1 && // starts before start
       
   612         comparePoint(parentNode, nodeIndex + 1, ec) == -1) { // ends before start
       
   613         return false;
       
   614     } else if(comparePoint(parentNode, nodeIndex, ec) == 1 && // starts after end
       
   615               comparePoint(parentNode, nodeIndex + 1, ec) == 1) { // ends after end
       
   616         return false;
       
   617     }
       
   618     
       
   619     return true;    //all other cases
       
   620 }
       
   621 
       
   622 PassRefPtr<DocumentFragment> Range::processContents ( ActionType action, ExceptionCode& ec)
       
   623 {
       
   624     // ### when mutation events are implemented, we will have to take into account
       
   625     // situations where the tree is being transformed while we delete - ugh!
       
   626 
       
   627     // ### perhaps disable node deletion notification for this range while we do this?
       
   628 
       
   629     if (collapsed(ec))
       
   630         return 0;
       
   631     if (ec)
       
   632         return 0;
       
   633 
       
   634     Node *cmnRoot = commonAncestorContainer(ec);
       
   635     if (ec)
       
   636         return 0;
       
   637 
       
   638     // what is the highest node that partially selects the start of the range?
       
   639     Node *partialStart = 0;
       
   640     if (m_startContainer != cmnRoot) {
       
   641         partialStart = m_startContainer.get();
       
   642         while (partialStart->parentNode() != cmnRoot)
       
   643             partialStart = partialStart->parentNode();
       
   644     }
       
   645 
       
   646     // what is the highest node that partially selects the end of the range?
       
   647     Node *partialEnd = 0;
       
   648     if (m_endContainer != cmnRoot) {
       
   649         partialEnd = m_endContainer.get();
       
   650         while (partialEnd->parentNode() != cmnRoot)
       
   651             partialEnd = partialEnd->parentNode();
       
   652     }
       
   653 
       
   654     RefPtr<DocumentFragment> fragment;
       
   655     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
       
   656         fragment = new DocumentFragment(m_ownerDocument.get());
       
   657 
       
   658     // Simple case: the start and end containers are the same. We just grab
       
   659     // everything >= start offset and < end offset
       
   660     if (m_startContainer == m_endContainer) {
       
   661         if(m_startContainer->nodeType() == Node::TEXT_NODE ||
       
   662            m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
       
   663            m_startContainer->nodeType() == Node::COMMENT_NODE) {
       
   664 
       
   665             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
       
   666                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_startContainer->cloneNode(true));
       
   667                 c->deleteData(m_endOffset, c->length() - m_endOffset, ec);
       
   668                 c->deleteData(0, m_startOffset, ec);
       
   669                 fragment->appendChild(c.release(), ec);
       
   670             }
       
   671             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
       
   672                 static_cast<CharacterData*>(m_startContainer.get())->deleteData(m_startOffset,m_endOffset-m_startOffset,ec);
       
   673                 m_startContainer->document()->updateLayout();
       
   674             }
       
   675         }
       
   676         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
       
   677             // ### operate just on data ?
       
   678         }
       
   679         else {
       
   680             Node *n = m_startContainer->firstChild();
       
   681             unsigned i;
       
   682             for (i = 0; n && i < m_startOffset; i++) // skip until m_startOffset
       
   683                 n = n->nextSibling();
       
   684             while (n && i < m_endOffset) { // delete until m_endOffset
       
   685                 Node *next = n->nextSibling();
       
   686                 if (action == EXTRACT_CONTENTS)
       
   687                     fragment->appendChild(n,ec); // will remove n from it's parent
       
   688                 else if (action == CLONE_CONTENTS)
       
   689                     fragment->appendChild(n->cloneNode(true),ec);
       
   690                 else
       
   691                     m_startContainer->removeChild(n,ec);
       
   692                 n = next;
       
   693                 i++;
       
   694             }
       
   695         }
       
   696         if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
       
   697             collapse(true,ec);
       
   698         return fragment.release();
       
   699     }
       
   700 
       
   701     // Complex case: Start and end containers are different.
       
   702     // There are three possiblities here:
       
   703     // 1. Start container == cmnRoot (End container must be a descendant)
       
   704     // 2. End container == cmnRoot (Start container must be a descendant)
       
   705     // 3. Neither is cmnRoot, they are both descendants
       
   706     //
       
   707     // In case 3, we grab everything after the start (up until a direct child
       
   708     // of cmnRoot) into leftContents, and everything before the end (up until
       
   709     // a direct child of cmnRoot) into rightContents. Then we process all
       
   710     // cmnRoot children between leftContents and rightContents
       
   711     //
       
   712     // In case 1 or 2, we skip either processing of leftContents or rightContents,
       
   713     // in which case the last lot of nodes either goes from the first or last
       
   714     // child of cmnRoot.
       
   715     //
       
   716     // These are deleted, cloned, or extracted (i.e. both) depending on action.
       
   717 
       
   718     RefPtr<Node> leftContents;
       
   719     if (m_startContainer != cmnRoot) {
       
   720         // process the left-hand side of the range, up until the last ancestor of
       
   721         // m_startContainer before cmnRoot
       
   722         if(m_startContainer->nodeType() == Node::TEXT_NODE ||
       
   723            m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
       
   724            m_startContainer->nodeType() == Node::COMMENT_NODE) {
       
   725 
       
   726             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
       
   727                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_startContainer->cloneNode(true));
       
   728                 c->deleteData(0, m_startOffset, ec);
       
   729                 leftContents = c.release();
       
   730             }
       
   731             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
       
   732                 static_cast<CharacterData*>(m_startContainer.get())->deleteData(
       
   733                     m_startOffset, static_cast<CharacterData*>(m_startContainer.get())->length() - m_startOffset, ec);
       
   734                 m_startContainer->document()->updateLayout();
       
   735             }
       
   736         }
       
   737         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
       
   738             // ### operate just on data ?
       
   739             // leftContents = ...
       
   740         }
       
   741         else {
       
   742             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
       
   743                 leftContents = m_startContainer->cloneNode(false);
       
   744             Node *n = m_startContainer->firstChild();
       
   745             for (unsigned i = 0; n && i < m_startOffset; i++) // skip until m_startOffset
       
   746                 n = n->nextSibling();
       
   747             while (n) { // process until end
       
   748                 Node *next = n->nextSibling();
       
   749                 if (action == EXTRACT_CONTENTS)
       
   750                     leftContents->appendChild(n,ec); // will remove n from m_startContainer
       
   751                 else if (action == CLONE_CONTENTS)
       
   752                     leftContents->appendChild(n->cloneNode(true),ec);
       
   753                 else
       
   754                     m_startContainer->removeChild(n,ec);
       
   755                 n = next;
       
   756             }
       
   757         }
       
   758 
       
   759         Node *leftParent = m_startContainer->parentNode();
       
   760         Node *n = m_startContainer->nextSibling();
       
   761         for (; leftParent != cmnRoot; leftParent = leftParent->parentNode()) {
       
   762             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
       
   763                 RefPtr<Node> leftContentsParent = leftParent->cloneNode(false);
       
   764                 leftContentsParent->appendChild(leftContents,ec);
       
   765                 leftContents = leftContentsParent;
       
   766             }
       
   767 
       
   768             Node *next;
       
   769             for (; n; n = next) {
       
   770                 next = n->nextSibling();
       
   771                 if (action == EXTRACT_CONTENTS)
       
   772                     leftContents->appendChild(n,ec); // will remove n from leftParent
       
   773                 else if (action == CLONE_CONTENTS)
       
   774                     leftContents->appendChild(n->cloneNode(true),ec);
       
   775                 else
       
   776                     leftParent->removeChild(n,ec);
       
   777             }
       
   778             n = leftParent->nextSibling();
       
   779         }
       
   780     }
       
   781 
       
   782     RefPtr<Node> rightContents = 0;
       
   783     if (m_endContainer != cmnRoot) {
       
   784         // delete the right-hand side of the range, up until the last ancestor of
       
   785         // m_endContainer before cmnRoot
       
   786         if(m_endContainer->nodeType() == Node::TEXT_NODE ||
       
   787            m_endContainer->nodeType() == Node::CDATA_SECTION_NODE ||
       
   788            m_endContainer->nodeType() == Node::COMMENT_NODE) {
       
   789 
       
   790             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
       
   791                 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_endContainer->cloneNode(true));
       
   792                 c->deleteData(m_endOffset, static_cast<CharacterData*>(m_endContainer.get())->length() - m_endOffset, ec);
       
   793                 rightContents = c;
       
   794             }
       
   795             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
       
   796                 static_cast<CharacterData*>(m_endContainer.get())->deleteData(0, m_endOffset, ec);
       
   797                 m_startContainer->document()->updateLayout();
       
   798             }
       
   799         }
       
   800         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
       
   801             // ### operate just on data ?
       
   802             // rightContents = ...
       
   803         }
       
   804         else {
       
   805             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
       
   806                 rightContents = m_endContainer->cloneNode(false);
       
   807             Node *n = m_endContainer->firstChild();
       
   808             if (n && m_endOffset) {
       
   809                 for (unsigned i = 0; i+1 < m_endOffset; i++) { // skip to m_endOffset
       
   810                     Node *next = n->nextSibling();
       
   811                     if (!next)
       
   812                         break;
       
   813                     n = next;
       
   814                 }
       
   815                 Node *prev;
       
   816                 for (; n; n = prev) {
       
   817                     prev = n->previousSibling();
       
   818                     if (action == EXTRACT_CONTENTS)
       
   819                         rightContents->insertBefore(n,rightContents->firstChild(),ec); // will remove n from it's parent
       
   820                     else if (action == CLONE_CONTENTS)
       
   821                         rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),ec);
       
   822                     else
       
   823                         m_endContainer->removeChild(n,ec);
       
   824                 }
       
   825             }
       
   826         }
       
   827 
       
   828         Node *rightParent = m_endContainer->parentNode();
       
   829         Node *n = m_endContainer->previousSibling();
       
   830         for (; rightParent != cmnRoot; rightParent = rightParent->parentNode()) {
       
   831             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
       
   832                 RefPtr<Node> rightContentsParent = rightParent->cloneNode(false);
       
   833                 rightContentsParent->appendChild(rightContents,ec);
       
   834                 rightContents = rightContentsParent;
       
   835             }
       
   836 
       
   837             Node *prev;
       
   838             for (; n; n = prev) {
       
   839                 prev = n->previousSibling();
       
   840                 if (action == EXTRACT_CONTENTS)
       
   841                     rightContents->insertBefore(n,rightContents->firstChild(),ec); // will remove n from it's parent
       
   842                 else if (action == CLONE_CONTENTS)
       
   843                     rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),ec);
       
   844                 else
       
   845                     rightParent->removeChild(n,ec);
       
   846             }
       
   847             n = rightParent->previousSibling();
       
   848         }
       
   849     }
       
   850 
       
   851     // delete all children of cmnRoot between the start and end container
       
   852 
       
   853     Node *processStart; // child of cmnRooot
       
   854     if (m_startContainer == cmnRoot) {
       
   855         unsigned i;
       
   856         processStart = m_startContainer->firstChild();
       
   857         for (i = 0; i < m_startOffset; i++)
       
   858             processStart = processStart->nextSibling();
       
   859     }
       
   860     else {
       
   861         processStart = m_startContainer.get();
       
   862         while (processStart->parentNode() != cmnRoot)
       
   863             processStart = processStart->parentNode();
       
   864         processStart = processStart->nextSibling();
       
   865     }
       
   866     Node *processEnd; // child of cmnRooot
       
   867     if (m_endContainer == cmnRoot) {
       
   868         unsigned i;
       
   869         processEnd = m_endContainer->firstChild();
       
   870         for (i = 0; i < m_endOffset; i++)
       
   871             processEnd = processEnd->nextSibling();
       
   872     }
       
   873     else {
       
   874         processEnd = m_endContainer.get();
       
   875         while (processEnd->parentNode() != cmnRoot)
       
   876             processEnd = processEnd->parentNode();
       
   877     }
       
   878 
       
   879     // Now add leftContents, stuff in between, and rightContents to the fragment
       
   880     // (or just delete the stuff in between)
       
   881 
       
   882     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
       
   883       fragment->appendChild(leftContents,ec);
       
   884 
       
   885     Node *next;
       
   886     Node *n;
       
   887     if (processStart) {
       
   888         for (n = processStart; n && n != processEnd; n = next) {
       
   889             next = n->nextSibling();
       
   890 
       
   891             if (action == EXTRACT_CONTENTS)
       
   892                 fragment->appendChild(n,ec); // will remove from cmnRoot
       
   893             else if (action == CLONE_CONTENTS)
       
   894                 fragment->appendChild(n->cloneNode(true),ec);
       
   895             else
       
   896                 cmnRoot->removeChild(n,ec);
       
   897         }
       
   898     }
       
   899 
       
   900     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
       
   901       fragment->appendChild(rightContents,ec);
       
   902 
       
   903     // collapse to the proper position - see spec section 2.6
       
   904     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
       
   905         if (!partialStart && !partialEnd)
       
   906             collapse(true,ec);
       
   907         else if (partialStart) {
       
   908             m_startContainer = partialStart->parentNode();
       
   909             m_endContainer = partialStart->parentNode();
       
   910             m_startOffset = m_endOffset = partialStart->nodeIndex()+1;
       
   911         }
       
   912         else if (partialEnd) {
       
   913             m_startContainer = partialEnd->parentNode();
       
   914             m_endContainer = partialEnd->parentNode();
       
   915             m_startOffset = m_endOffset = partialEnd->nodeIndex();
       
   916         }
       
   917     }
       
   918     return fragment.release();
       
   919 }
       
   920 
       
   921 
       
   922 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
       
   923 {
       
   924     if (m_detached) {
       
   925         ec = INVALID_STATE_ERR;
       
   926         return 0;
       
   927     }
       
   928 
       
   929     checkDeleteExtract(ec);
       
   930     if (ec)
       
   931         return 0;
       
   932 
       
   933     return processContents(EXTRACT_CONTENTS,ec);
       
   934 }
       
   935 
       
   936 PassRefPtr<DocumentFragment> Range::cloneContents( int &ec  )
       
   937 {
       
   938     if (m_detached) {
       
   939         ec = INVALID_STATE_ERR;
       
   940         return 0;
       
   941     }
       
   942 
       
   943     return processContents(CLONE_CONTENTS,ec);
       
   944 }
       
   945 
       
   946 void Range::insertNode(PassRefPtr<Node> newNode, ExceptionCode& ec)
       
   947 {
       
   948     if (m_detached) {
       
   949         ec = INVALID_STATE_ERR;
       
   950         return;
       
   951     }
       
   952 
       
   953     if (!newNode) {
       
   954         ec = NOT_FOUND_ERR;
       
   955         return;
       
   956     }
       
   957 
       
   958     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
       
   959     // the Range is read-only.
       
   960     if (containedByReadOnly()) {
       
   961         ec = NO_MODIFICATION_ALLOWED_ERR;
       
   962         return;
       
   963     }
       
   964 
       
   965     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
       
   966     // not created from the same document.
       
   967     if (newNode->document() != m_startContainer->document()) {
       
   968         ec = WRONG_DOCUMENT_ERR;
       
   969         return;
       
   970     }
       
   971 
       
   972 
       
   973     // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
       
   974     // does not allow children of the type of newNode or if newNode is an ancestor of the container.
       
   975 
       
   976     // an extra one here - if a text node is going to split, it must have a parent to insert into
       
   977     if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
       
   978         ec = HIERARCHY_REQUEST_ERR;
       
   979         return;
       
   980     }
       
   981 
       
   982     // In the case where the container is a text node, we check against the container's parent, because
       
   983     // text nodes get split up upon insertion.
       
   984     Node *checkAgainst;
       
   985     if (m_startContainer->nodeType() == Node::TEXT_NODE)
       
   986         checkAgainst = m_startContainer->parentNode();
       
   987     else
       
   988         checkAgainst = m_startContainer.get();
       
   989 
       
   990     if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
       
   991         // check each child node, not the DocumentFragment itself
       
   992         Node *c;
       
   993         for (c = newNode->firstChild(); c; c = c->nextSibling()) {
       
   994             if (!checkAgainst->childTypeAllowed(c->nodeType())) {
       
   995                 ec = HIERARCHY_REQUEST_ERR;
       
   996                 return;
       
   997             }
       
   998         }
       
   999     }
       
  1000     else {
       
  1001         if (!checkAgainst->childTypeAllowed(newNode->nodeType())) {
       
  1002             ec = HIERARCHY_REQUEST_ERR;
       
  1003             return;
       
  1004         }
       
  1005     }
       
  1006 
       
  1007     for (Node *n = m_startContainer.get(); n; n = n->parentNode()) {
       
  1008         if (n == newNode) {
       
  1009             ec = HIERARCHY_REQUEST_ERR;
       
  1010             return;
       
  1011         }
       
  1012     }
       
  1013 
       
  1014     // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
       
  1015     if( newNode->nodeType() == Node::ATTRIBUTE_NODE ||
       
  1016         newNode->nodeType() == Node::ENTITY_NODE ||
       
  1017         newNode->nodeType() == Node::NOTATION_NODE ||
       
  1018         newNode->nodeType() == Node::DOCUMENT_NODE) {
       
  1019         ec = INVALID_NODE_TYPE_ERR;
       
  1020         return;
       
  1021     }
       
  1022 
       
  1023     if( m_startContainer->nodeType() == Node::TEXT_NODE ||
       
  1024         m_startContainer->nodeType() == Node::CDATA_SECTION_NODE )
       
  1025     {
       
  1026         Text *newText = static_cast<Text*>(m_startContainer.get())->splitText(m_startOffset,ec);
       
  1027         if (ec)
       
  1028             return;
       
  1029         m_startContainer->parentNode()->insertBefore( newNode, newText, ec );
       
  1030     }
       
  1031     else {
       
  1032         m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), ec );
       
  1033     }
       
  1034 }
       
  1035 
       
  1036 String Range::toString(ExceptionCode& ec) const
       
  1037 {
       
  1038     if (m_detached) {
       
  1039         ec = INVALID_STATE_ERR;
       
  1040         return String();
       
  1041     }
       
  1042 
       
  1043     Vector<UChar> result;
       
  1044 
       
  1045     Node* pastEnd = pastEndNode();
       
  1046     for (Node* n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
       
  1047         if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
       
  1048             String data = static_cast<CharacterData*>(n)->data();
       
  1049             unsigned length = data.length();
       
  1050             unsigned start = (n == m_startContainer) ? min(m_startOffset, length) : 0;
       
  1051             unsigned end = (n == m_endContainer) ? min(max(start, m_endOffset), length) : length;
       
  1052             result.append(data.characters() + start, end - start);
       
  1053         }
       
  1054     }
       
  1055 
       
  1056     return String::adopt(result);
       
  1057 }
       
  1058 
       
  1059 String Range::toHTML() const
       
  1060 {
       
  1061     return createMarkup(this);
       
  1062 }
       
  1063 
       
  1064 String Range::text() const
       
  1065 {
       
  1066     if (m_detached)
       
  1067         return String();
       
  1068 
       
  1069     // We need to update layout, since plainText uses line boxes in the render tree.
       
  1070     // FIXME: As with innerText, we'd like this to work even if there are no render objects.
       
  1071     m_startContainer->document()->updateLayout();
       
  1072 
       
  1073     // FIXME: Maybe DOMRange constructor should take const DOMRange*; if it did we would not need this const_cast.
       
  1074     return plainText(const_cast<Range *>(this));
       
  1075 }
       
  1076 
       
  1077 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String &html, ExceptionCode& ec) const
       
  1078 {
       
  1079     if (m_detached) {
       
  1080         ec = INVALID_STATE_ERR;
       
  1081         return 0;
       
  1082     }
       
  1083 
       
  1084     Node* htmlElement = m_startContainer->isHTMLElement() ? m_startContainer.get() : m_startContainer->parentNode();
       
  1085     
       
  1086     if (!htmlElement->isHTMLElement()) {
       
  1087         ec = NOT_SUPPORTED_ERR;
       
  1088         return 0;
       
  1089     }
       
  1090 
       
  1091     RefPtr<DocumentFragment> fragment = static_cast<HTMLElement*>(htmlElement)->createContextualFragment(html);
       
  1092     if (!fragment) {
       
  1093         ec = NOT_SUPPORTED_ERR;
       
  1094         return 0;
       
  1095     }
       
  1096 
       
  1097     return fragment.release();
       
  1098 }
       
  1099 
       
  1100 
       
  1101 void Range::detach(ExceptionCode& ec)
       
  1102 {
       
  1103     if (m_detached) {
       
  1104         ec = INVALID_STATE_ERR;
       
  1105         return;
       
  1106     }
       
  1107 
       
  1108     m_startContainer = 0;
       
  1109     m_endContainer = 0;
       
  1110     m_detached = true;
       
  1111 }
       
  1112 
       
  1113 bool Range::isDetached() const
       
  1114 {
       
  1115     return m_detached;
       
  1116 }
       
  1117 
       
  1118 void Range::checkNodeWOffset( Node *n, int offset, ExceptionCode& ec) const
       
  1119 {
       
  1120     if( offset < 0 ) {
       
  1121         ec = INDEX_SIZE_ERR;
       
  1122     }
       
  1123 
       
  1124     switch (n->nodeType()) {
       
  1125         case Node::ENTITY_NODE:
       
  1126         case Node::NOTATION_NODE:
       
  1127         case Node::DOCUMENT_TYPE_NODE:
       
  1128             ec = INVALID_NODE_TYPE_ERR;
       
  1129             break;
       
  1130         case Node::TEXT_NODE:
       
  1131         case Node::COMMENT_NODE:
       
  1132         case Node::CDATA_SECTION_NODE:
       
  1133             if ( (unsigned)offset > static_cast<CharacterData*>(n)->length() )
       
  1134                 ec = INDEX_SIZE_ERR;
       
  1135             break;
       
  1136         case Node::PROCESSING_INSTRUCTION_NODE:
       
  1137             // ### are we supposed to check with just data or the whole contents?
       
  1138             if ( (unsigned)offset > static_cast<ProcessingInstruction*>(n)->data().length() )
       
  1139                 ec = INDEX_SIZE_ERR;
       
  1140             break;
       
  1141         default:
       
  1142             if ( (unsigned)offset > n->childNodeCount() )
       
  1143                 ec = INDEX_SIZE_ERR;
       
  1144             break;
       
  1145     }
       
  1146 }
       
  1147 
       
  1148 void Range::checkNodeBA( Node *n, ExceptionCode& ec) const
       
  1149 {
       
  1150     // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
       
  1151     // Attr, Document or DocumentFragment node or part of a shadow DOM tree
       
  1152     // or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation node.
       
  1153     Node *root = n;
       
  1154     while (root->parentNode())
       
  1155         root = root->parentNode();
       
  1156     if (!(root->nodeType() == Node::ATTRIBUTE_NODE ||
       
  1157           root->nodeType() == Node::DOCUMENT_NODE ||
       
  1158           root->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
       
  1159           root->isShadowNode())) {
       
  1160         ec = INVALID_NODE_TYPE_ERR;
       
  1161         return;
       
  1162     }
       
  1163 
       
  1164     if( n->nodeType() == Node::DOCUMENT_NODE ||
       
  1165         n->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
       
  1166         n->nodeType() == Node::ATTRIBUTE_NODE ||
       
  1167         n->nodeType() == Node::ENTITY_NODE ||
       
  1168         n->nodeType() == Node::NOTATION_NODE )
       
  1169         ec = INVALID_NODE_TYPE_ERR;
       
  1170 
       
  1171 }
       
  1172 
       
  1173 PassRefPtr<Range> Range::cloneRange(ExceptionCode& ec) const
       
  1174 {
       
  1175     if (m_detached) {
       
  1176         ec = INVALID_STATE_ERR;
       
  1177         return 0;
       
  1178     }
       
  1179 
       
  1180     return new Range(m_ownerDocument.get(), m_startContainer.get(), m_startOffset, m_endContainer.get(), m_endOffset);
       
  1181 }
       
  1182 
       
  1183 void Range::setStartAfter( Node *refNode, ExceptionCode& ec)
       
  1184 {
       
  1185     if (m_detached) {
       
  1186         ec = INVALID_STATE_ERR;
       
  1187         return;
       
  1188     }
       
  1189 
       
  1190     if (!refNode) {
       
  1191         ec = NOT_FOUND_ERR;
       
  1192         return;
       
  1193     }
       
  1194 
       
  1195     if (refNode->document() != m_ownerDocument) {
       
  1196         ec = WRONG_DOCUMENT_ERR;
       
  1197         return;
       
  1198     }
       
  1199 
       
  1200     checkNodeBA( refNode, ec );
       
  1201     if (ec)
       
  1202         return;
       
  1203 
       
  1204     setStart( refNode->parentNode(), refNode->nodeIndex()+1, ec );
       
  1205 }
       
  1206 
       
  1207 void Range::setEndBefore( Node *refNode, ExceptionCode& ec)
       
  1208 {
       
  1209     if (m_detached) {
       
  1210         ec = INVALID_STATE_ERR;
       
  1211         return;
       
  1212     }
       
  1213 
       
  1214     if (!refNode) {
       
  1215         ec = NOT_FOUND_ERR;
       
  1216         return;
       
  1217     }
       
  1218 
       
  1219     if (refNode->document() != m_ownerDocument) {
       
  1220         ec = WRONG_DOCUMENT_ERR;
       
  1221         return;
       
  1222     }
       
  1223 
       
  1224     checkNodeBA( refNode, ec );
       
  1225     if (ec)
       
  1226         return;
       
  1227 
       
  1228     setEnd( refNode->parentNode(), refNode->nodeIndex(), ec );
       
  1229 }
       
  1230 
       
  1231 void Range::setEndAfter( Node *refNode, ExceptionCode& ec)
       
  1232 {
       
  1233     if (m_detached) {
       
  1234         ec = INVALID_STATE_ERR;
       
  1235         return;
       
  1236     }
       
  1237 
       
  1238     if (!refNode) {
       
  1239         ec = NOT_FOUND_ERR;
       
  1240         return;
       
  1241     }
       
  1242 
       
  1243     if (refNode->document() != m_ownerDocument) {
       
  1244         ec = WRONG_DOCUMENT_ERR;
       
  1245         return;
       
  1246     }
       
  1247 
       
  1248     checkNodeBA( refNode, ec );
       
  1249     if (ec)
       
  1250         return;
       
  1251 
       
  1252     setEnd( refNode->parentNode(), refNode->nodeIndex()+1, ec );
       
  1253 
       
  1254 }
       
  1255 
       
  1256 void Range::selectNode( Node *refNode, ExceptionCode& ec)
       
  1257 {
       
  1258     if (m_detached) {
       
  1259         ec = INVALID_STATE_ERR;
       
  1260         return;
       
  1261     }
       
  1262 
       
  1263     if (!refNode) {
       
  1264         ec = NOT_FOUND_ERR;
       
  1265         return;
       
  1266     }
       
  1267 
       
  1268     // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
       
  1269     // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
       
  1270     // node.
       
  1271     Node *anc;
       
  1272     for (anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
       
  1273         if (anc->nodeType() == Node::ENTITY_NODE ||
       
  1274             anc->nodeType() == Node::NOTATION_NODE ||
       
  1275             anc->nodeType() == Node::DOCUMENT_TYPE_NODE) {
       
  1276 
       
  1277             ec = INVALID_NODE_TYPE_ERR;
       
  1278             return;
       
  1279         }
       
  1280     }
       
  1281 
       
  1282     if (refNode->nodeType() == Node::DOCUMENT_NODE ||
       
  1283         refNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
       
  1284         refNode->nodeType() == Node::ATTRIBUTE_NODE ||
       
  1285         refNode->nodeType() == Node::ENTITY_NODE ||
       
  1286         refNode->nodeType() == Node::NOTATION_NODE) {
       
  1287 
       
  1288         ec = INVALID_NODE_TYPE_ERR;
       
  1289         return;
       
  1290     }
       
  1291 
       
  1292     setStartBefore( refNode, ec );
       
  1293     if (ec)
       
  1294         return;
       
  1295     setEndAfter( refNode, ec );
       
  1296 }
       
  1297 
       
  1298 void Range::selectNodeContents( Node *refNode, ExceptionCode& ec)
       
  1299 {
       
  1300     if (m_detached) {
       
  1301         ec = INVALID_STATE_ERR;
       
  1302         return;
       
  1303     }
       
  1304 
       
  1305     if (!refNode) {
       
  1306         ec = NOT_FOUND_ERR;
       
  1307         return;
       
  1308     }
       
  1309 
       
  1310     // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
       
  1311     // or DocumentType node.
       
  1312     Node *n;
       
  1313     for (n = refNode; n; n = n->parentNode()) {
       
  1314         if (n->nodeType() == Node::ENTITY_NODE ||
       
  1315             n->nodeType() == Node::NOTATION_NODE ||
       
  1316             n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
       
  1317 
       
  1318             ec = INVALID_NODE_TYPE_ERR;
       
  1319             return;
       
  1320         }
       
  1321     }
       
  1322 
       
  1323     m_startContainer = refNode;
       
  1324     m_startOffset = 0;
       
  1325     m_endContainer = refNode;
       
  1326     m_endOffset = refNode->offsetInCharacters() ? refNode->maxOffset() : refNode->childNodeCount();
       
  1327 }
       
  1328 
       
  1329 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionCode& ec)
       
  1330 {
       
  1331     RefPtr<Node> newParent = passNewParent;
       
  1332 
       
  1333     if (m_detached) {
       
  1334         ec = INVALID_STATE_ERR;
       
  1335         return;
       
  1336     }
       
  1337 
       
  1338     if (!newParent) {
       
  1339         ec = NOT_FOUND_ERR;
       
  1340         return;
       
  1341     }
       
  1342 
       
  1343     // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
       
  1344     // Document, or DocumentFragment node.
       
  1345     if( newParent->nodeType() == Node::ATTRIBUTE_NODE ||
       
  1346         newParent->nodeType() == Node::ENTITY_NODE ||
       
  1347         newParent->nodeType() == Node::NOTATION_NODE ||
       
  1348         newParent->nodeType() == Node::DOCUMENT_TYPE_NODE ||
       
  1349         newParent->nodeType() == Node::DOCUMENT_NODE ||
       
  1350         newParent->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
       
  1351         ec = INVALID_NODE_TYPE_ERR;
       
  1352         return;
       
  1353     }
       
  1354 
       
  1355     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
       
  1356     // the Range is read-only.
       
  1357     if (containedByReadOnly()) {
       
  1358         ec = NO_MODIFICATION_ALLOWED_ERR;
       
  1359         return;
       
  1360     }
       
  1361 
       
  1362     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
       
  1363     // not created from the same document.
       
  1364     if (newParent->document() != m_startContainer->document()) {
       
  1365         ec = WRONG_DOCUMENT_ERR;
       
  1366         return;
       
  1367     }
       
  1368 
       
  1369     // Raise a HIERARCHY_REQUEST_ERR if m_startContainer doesn't accept children like newParent.
       
  1370     Node* parentOfNewParent = m_startContainer.get();
       
  1371     // If m_startContainer is a textNode, it will be split and it will be its parent that will 
       
  1372     // need to accept newParent.
       
  1373     if (parentOfNewParent->isTextNode())
       
  1374         parentOfNewParent = parentOfNewParent->parentNode();
       
  1375     if (!parentOfNewParent->childTypeAllowed(newParent->nodeType())) {
       
  1376         ec = HIERARCHY_REQUEST_ERR;
       
  1377         return;
       
  1378     }
       
  1379     
       
  1380     if (m_startContainer == newParent || m_startContainer->isDescendantOf(newParent.get())) {
       
  1381         ec = HIERARCHY_REQUEST_ERR;
       
  1382         return;
       
  1383     }
       
  1384 
       
  1385     // ### check if node would end up with a child node of a type not allowed by the type of node
       
  1386 
       
  1387     // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text node.
       
  1388     if (!m_startContainer->offsetInCharacters()) {
       
  1389         if (m_startOffset > 0 && m_startOffset < m_startContainer->childNodeCount()) {
       
  1390             ec = BAD_BOUNDARYPOINTS_ERR;
       
  1391             return;
       
  1392         }
       
  1393     }
       
  1394     if (!m_endContainer->offsetInCharacters()) {
       
  1395         if (m_endOffset > 0 && m_endOffset < m_endContainer->childNodeCount()) {
       
  1396             ec = BAD_BOUNDARYPOINTS_ERR;
       
  1397             return;
       
  1398         }
       
  1399     }
       
  1400 
       
  1401     while (Node* n = newParent->firstChild()) {
       
  1402         newParent->removeChild(n, ec);
       
  1403         if (ec)
       
  1404             return;
       
  1405     }
       
  1406     RefPtr<DocumentFragment> fragment = extractContents(ec);
       
  1407     if (ec)
       
  1408         return;
       
  1409     insertNode(newParent, ec);
       
  1410     if (ec)
       
  1411         return;
       
  1412     newParent->appendChild(fragment.release(), ec);
       
  1413     if (ec)
       
  1414         return;
       
  1415     selectNode(newParent.get(), ec);
       
  1416 }
       
  1417 
       
  1418 void Range::setStartBefore( Node *refNode, ExceptionCode& ec)
       
  1419 {
       
  1420     if (m_detached) {
       
  1421         ec = INVALID_STATE_ERR;
       
  1422         return;
       
  1423     }
       
  1424 
       
  1425     if (!refNode) {
       
  1426         ec = NOT_FOUND_ERR;
       
  1427         return;
       
  1428     }
       
  1429 
       
  1430     if (refNode->document() != m_ownerDocument) {
       
  1431         ec = WRONG_DOCUMENT_ERR;
       
  1432         return;
       
  1433     }
       
  1434 
       
  1435     checkNodeBA( refNode, ec );
       
  1436     if (ec)
       
  1437         return;
       
  1438 
       
  1439     setStart( refNode->parentNode(), refNode->nodeIndex(), ec );
       
  1440 }
       
  1441 
       
  1442 void Range::checkDeleteExtract(ExceptionCode& ec)
       
  1443 {
       
  1444     if (!commonAncestorContainer(ec) || ec)
       
  1445         return;
       
  1446         
       
  1447     Node *pastEnd = pastEndNode();
       
  1448     for (Node *n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
       
  1449         if (n->isReadOnlyNode()) {
       
  1450             ec = NO_MODIFICATION_ALLOWED_ERR;
       
  1451             return;
       
  1452         }
       
  1453         if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { // ### is this for only directly under the DF, or anywhere?
       
  1454             ec = HIERARCHY_REQUEST_ERR;
       
  1455             return;
       
  1456         }
       
  1457     }
       
  1458 
       
  1459     if (containedByReadOnly()) {
       
  1460         ec = NO_MODIFICATION_ALLOWED_ERR;
       
  1461         return;
       
  1462     }
       
  1463 }
       
  1464 
       
  1465 bool Range::containedByReadOnly() const
       
  1466 {
       
  1467     Node *n;
       
  1468     for (n = m_startContainer.get(); n; n = n->parentNode()) {
       
  1469         if (n->isReadOnlyNode())
       
  1470             return true;
       
  1471     }
       
  1472     for (n = m_endContainer.get(); n; n = n->parentNode()) {
       
  1473         if (n->isReadOnlyNode())
       
  1474             return true;
       
  1475     }
       
  1476     return false;
       
  1477 }
       
  1478 
       
  1479 Position Range::startPosition() const
       
  1480 {
       
  1481     return Position(m_startContainer.get(), m_startOffset);
       
  1482 }
       
  1483 
       
  1484 Position Range::endPosition() const
       
  1485 {
       
  1486     return Position(m_endContainer.get(), m_endOffset);
       
  1487 }
       
  1488 
       
  1489 Node *Range::startNode() const
       
  1490 {
       
  1491     if (!m_startContainer)
       
  1492         return 0;
       
  1493     if (m_startContainer->offsetInCharacters())
       
  1494         return m_startContainer.get();
       
  1495     Node *child = m_startContainer->childNode(m_startOffset);
       
  1496     if (child)
       
  1497         return child;
       
  1498     if (m_startOffset == 0)
       
  1499         return m_startContainer.get();
       
  1500     return m_startContainer->traverseNextSibling();
       
  1501 }
       
  1502 
       
  1503 Position Range::editingStartPosition() const
       
  1504 {
       
  1505     // This function is used by range style computations to avoid bugs like:
       
  1506     // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
       
  1507     // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up 
       
  1508     // with a spurious "mixed" style.
       
  1509     
       
  1510     VisiblePosition visiblePosition(m_startContainer.get(), m_startOffset, VP_DEFAULT_AFFINITY);
       
  1511     if (visiblePosition.isNull())
       
  1512         return Position();
       
  1513 
       
  1514     ExceptionCode ec = 0;
       
  1515     // if the selection is a caret, just return the position, since the style
       
  1516     // behind us is relevant
       
  1517     if (collapsed(ec))
       
  1518         return visiblePosition.deepEquivalent();
       
  1519 
       
  1520     // if the selection starts just before a paragraph break, skip over it
       
  1521     if (isEndOfParagraph(visiblePosition))
       
  1522         return visiblePosition.next().deepEquivalent().downstream();
       
  1523 
       
  1524     // otherwise, make sure to be at the start of the first selected node,
       
  1525     // instead of possibly at the end of the last node before the selection
       
  1526     return visiblePosition.deepEquivalent().downstream();
       
  1527 }
       
  1528 
       
  1529 Node *Range::pastEndNode() const
       
  1530 {
       
  1531     if (!m_startContainer || !m_endContainer)
       
  1532         return 0;
       
  1533     if (m_endContainer->offsetInCharacters())
       
  1534         return m_endContainer->traverseNextSibling();
       
  1535     Node *child = m_endContainer->childNode(m_endOffset);
       
  1536     if (child)
       
  1537         return child;
       
  1538     return m_endContainer->traverseNextSibling();
       
  1539 }
       
  1540 
       
  1541 IntRect Range::boundingBox()
       
  1542 {
       
  1543     IntRect result;
       
  1544     Vector<IntRect> rects;
       
  1545     addLineBoxRects(rects);
       
  1546     const size_t n = rects.size();
       
  1547     for (size_t i = 0; i < n; ++i)
       
  1548         result.unite(rects[i]);
       
  1549     return result;
       
  1550 }
       
  1551 
       
  1552 void Range::addLineBoxRects(Vector<IntRect>& rects, bool useSelectionHeight)
       
  1553 {
       
  1554     if (!m_startContainer || !m_endContainer)
       
  1555         return;
       
  1556 
       
  1557     RenderObject* start = m_startContainer->renderer();
       
  1558     RenderObject* end = m_endContainer->renderer();
       
  1559     if (!start || !end)
       
  1560         return;
       
  1561 
       
  1562     RenderObject* stop = end->nextInPreOrderAfterChildren();
       
  1563     for (RenderObject* r = start; r && r != stop; r = r->nextInPreOrder()) {
       
  1564         // only ask leaf render objects for their line box rects
       
  1565         if (!r->firstChild()) {
       
  1566             int startOffset = r == start ? m_startOffset : 0;
       
  1567             int endOffset = r == end ? m_endOffset : UINT_MAX;
       
  1568             r->addLineBoxRects(rects, startOffset, endOffset, useSelectionHeight);
       
  1569         }
       
  1570     }
       
  1571 }
       
  1572 
       
  1573 #ifndef NDEBUG
       
  1574 #define FormatBufferSize 1024
       
  1575 void Range::formatForDebugger(char *buffer, unsigned length) const
       
  1576 {
       
  1577     String result;
       
  1578     String s;
       
  1579     
       
  1580     if (!m_startContainer || !m_endContainer)
       
  1581         result = "<empty>";
       
  1582     else {
       
  1583         char s[FormatBufferSize];
       
  1584         result += "from offset ";
       
  1585         result += String::number(m_startOffset);
       
  1586         result += " of ";
       
  1587         m_startContainer->formatForDebugger(s, FormatBufferSize);
       
  1588         result += s;
       
  1589         result += " to offset ";
       
  1590         result += String::number(m_endOffset);
       
  1591         result += " of ";
       
  1592         m_endContainer->formatForDebugger(s, FormatBufferSize);
       
  1593         result += s;
       
  1594     }
       
  1595           
       
  1596     strncpy(buffer, result.deprecatedString().latin1(), length - 1);
       
  1597 }
       
  1598 #undef FormatBufferSize
       
  1599 #endif
       
  1600 
       
  1601 bool operator==(const Range &a, const Range &b)
       
  1602 {
       
  1603     if (&a == &b)
       
  1604         return true;
       
  1605     // Not strictly legal C++, but in practice this can happen, and works fine with GCC.
       
  1606     if (!&a || !&b)
       
  1607         return false;
       
  1608     bool ad = a.isDetached();
       
  1609     bool bd = b.isDetached();
       
  1610     if (ad && bd)
       
  1611         return true;
       
  1612     if (ad || bd)
       
  1613         return false;
       
  1614     int exception = 0;
       
  1615     return a.startContainer(exception) == b.startContainer(exception)
       
  1616         && a.endContainer(exception) == b.endContainer(exception)
       
  1617         && a.startOffset(exception) == b.startOffset(exception)
       
  1618         && a.endOffset(exception) == b.endOffset(exception);
       
  1619 }
       
  1620 
       
  1621 PassRefPtr<Range> rangeOfContents(Node* node)
       
  1622 {
       
  1623     ASSERT(node);
       
  1624     RefPtr<Range> range = new Range(node->document());
       
  1625     int exception = 0;
       
  1626     range->selectNodeContents(node, exception);
       
  1627     return range.release();
       
  1628 }
       
  1629 
       
  1630 }