| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# dom2_rangeimpl.cpp

    00001
    00025 #include "dom/dom_exception.h"
    00026 #include "dom_docimpl.h"
    00027 #include "dom2_rangeimpl.h"
    00028 #include "dom_textimpl.h"
    00029 #include "dom_xmlimpl.h"
    00030
    00031 using namespace DOM;
    00032
    00033
    00034 RangeImpl::RangeImpl(DocumentPtr *_ownerDocument)
    00035 {
    00036     m_ownerDocument = _ownerDocument;
    00037     m_ownerDocument->ref();
    00038     m_startContainer = _ownerDocument->document();
    00039     m_startContainer->ref();
    00040     m_endContainer = _ownerDocument->document();
    00041     m_endContainer->ref();
    00042     m_startOffset = 0;
    00043     m_endOffset = 0;
    00044     m_detached = false;
    00045 }
    00046
    00047 RangeImpl::RangeImpl(DocumentPtr *_ownerDocument,
    00048               NodeImpl *_startContainer, long _startOffset,
    00049               NodeImpl *_endContainer, long _endOffset)
    00050 {
    00051     m_ownerDocument = _ownerDocument;
    00052     m_ownerDocument->ref();
    00053     m_startContainer = _startContainer;
    00054     m_startContainer->ref();
    00055     m_startOffset = _startOffset;
    00056     m_endContainer = _endContainer;
    00057     m_endContainer->ref();
    00058     m_endOffset = _endOffset;
    00059     m_detached = false;
    00060 }
    00061
    00062 RangeImpl::~RangeImpl()
    00063 {
    00064     m_ownerDocument->deref();
    00065     int exceptioncode = 0;
    00066     if (!m_detached)
    00067         detach(exceptioncode);
    00068 }
    00069
    00070 NodeImpl *RangeImpl::startContainer(int &exceptioncode) const
    00071 {
    00072     if (m_detached) {
    00073         exceptioncode = DOMException::INVALID_STATE_ERR;
    00074         return 0;
    00075     }
    00076
    00077     return m_startContainer;
    00078 }
    00079
    00080 long RangeImpl::startOffset(int &exceptioncode) const
    00081 {
    00082     if (m_detached) {
    00083         exceptioncode = DOMException::INVALID_STATE_ERR;
    00084         return 0;
    00085     }
    00086
    00087     return m_startOffset;
    00088 }
    00089
    00090 NodeImpl *RangeImpl::endContainer(int &exceptioncode) const
    00091 {
    00092     if (m_detached) {
    00093         exceptioncode = DOMException::INVALID_STATE_ERR;
    00094         return 0;
    00095     }
    00096
    00097     return m_endContainer;
    00098 }
    00099
    00100 long RangeImpl::endOffset(int &exceptioncode) const
    00101 {
    00102     if (m_detached) {
    00103         exceptioncode = DOMException::INVALID_STATE_ERR;
    00104         return 0;
    00105     }
    00106
    00107     return m_endOffset;
    00108 }
    00109
    00110 NodeImpl *RangeImpl::commonAncestorContainer(int &exceptioncode)
    00111 {
    00112     if (m_detached) {
    00113         exceptioncode = DOMException::INVALID_STATE_ERR;
    00114         return 0;
    00115     }
    00116
    00117     NodeImpl *com = commonAncestorContainer(m_startContainer,m_endContainer);
    00118     if (!com) //  should never happen
    00119         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00120     return com;
    00121 }
    00122
    00123 NodeImpl *RangeImpl::commonAncestorContainer(NodeImpl *containerA, NodeImpl *containerB)
    00124 {
    00125     NodeImpl *parentStart;
    00126
    00127     for (parentStart = containerA; parentStart; parentStart = parentStart->parentNode()) {
    00128         NodeImpl *parentEnd = containerB;
    00129         while( parentEnd && (parentStart != parentEnd) )
    00130             parentEnd = parentEnd->parentNode();
    00131
    00132         if(parentStart == parentEnd)  break;
    00133     }
    00134
    00135     return parentStart;
    00136 }
    00137
    00138 bool RangeImpl::collapsed(int &exceptioncode) const
    00139 {
    00140     if (m_detached) {
    00141         exceptioncode = DOMException::INVALID_STATE_ERR;
    00142         return 0;
    00143     }
    00144
    00145     return (m_startContainer == m_endContainer && m_startOffset == m_endOffset);
    00146 }
    00147
    00148 void RangeImpl::setStart( NodeImpl *refNode, long offset, int &exceptioncode )
    00149 {
    00150     if (m_detached) {
    00151         exceptioncode = DOMException::INVALID_STATE_ERR;
    00152         return;
    00153     }
    00154
    00155     if (!refNode) {
    00156         exceptioncode = DOMException::NOT_FOUND_ERR;
    00157         return;
    00158     }
    00159
    00160     if (refNode->getDocument() != m_ownerDocument->document()) {
    00161         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00162         return;
    00163     }
    00164
    00165     checkNodeWOffset( refNode, offset, exceptioncode );
    00166     if (exceptioncode)
    00167         return;
    00168
    00169     setStartContainer(refNode);
    00170     m_startOffset = offset;
    00171
    00172     // check if different root container
    00173     NodeImpl *endRootContainer = m_endContainer;
    00174     while (endRootContainer->parentNode())
    00175         endRootContainer = endRootContainer->parentNode();
    00176     NodeImpl *startRootContainer = m_startContainer;
    00177     while (startRootContainer->parentNode())
    00178         startRootContainer = startRootContainer->parentNode();
    00179     if (startRootContainer != endRootContainer)
    00180         collapse(true,exceptioncode);
    00181     // check if new start after end
    00182     else if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)
    00183         collapse(true,exceptioncode);
    00184 }
    00185
    00186 void RangeImpl::setEnd( NodeImpl *refNode, long offset, int &exceptioncode )
    00187 {
    00188     if (m_detached) {
    00189         exceptioncode = DOMException::INVALID_STATE_ERR;
    00190         return;
    00191     }
    00192
    00193     if (!refNode) {
    00194         exceptioncode = DOMException::NOT_FOUND_ERR;
    00195         return;
    00196     }
    00197
    00198     if (refNode->getDocument() != m_ownerDocument->document()) {
    00199         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00200         return;
    00201     }
    00202
    00203     checkNodeWOffset( refNode, offset, exceptioncode );
    00204     if (exceptioncode)
    00205         return;
    00206
    00207     setEndContainer(refNode);
    00208     m_endOffset = offset;
    00209
    00210     // check if different root container
    00211     NodeImpl *endRootContainer = m_endContainer;
    00212     while (endRootContainer->parentNode())
    00213         endRootContainer = endRootContainer->parentNode();
    00214     NodeImpl *startRootContainer = m_startContainer;
    00215     while (startRootContainer->parentNode())
    00216         startRootContainer = startRootContainer->parentNode();
    00217     if (startRootContainer != endRootContainer)
    00218         collapse(false,exceptioncode);
    00219     // check if new end before start
    00220     if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)
    00221         collapse(false,exceptioncode);
    00222 }
    00223
    00224 void RangeImpl::collapse( bool toStart, int &exceptioncode )
    00225 {
    00226     if (m_detached) {
    00227         exceptioncode = DOMException::INVALID_STATE_ERR;
    00228         return;
    00229     }
    00230
    00231     if( toStart )   // collapse to start
    00232     {
    00233         setEndContainer(m_startContainer);
    00234         m_endOffset = m_startOffset;
    00235     }
    00236     else            // collapse to end
    00237     {
    00238         setStartContainer(m_endContainer);
    00239         m_startOffset = m_endOffset;
    00240     }
    00241 }
    00242
    00243 short RangeImpl::compareBoundaryPoints( Range::CompareHow how, RangeImpl *sourceRange, int &exceptioncode )
    00244 {
    00245     if (m_detached) {
    00246         exceptioncode = DOMException::INVALID_STATE_ERR;
    00247         return 0;
    00248     }
    00249
    00250     if (!sourceRange) {
    00251         exceptioncode = DOMException::NOT_FOUND_ERR;
    00252         return 0;
    00253     }
    00254
    00255     NodeImpl *thisCont = commonAncestorContainer(exceptioncode);
    00256     NodeImpl *sourceCont = sourceRange->commonAncestorContainer(exceptioncode);
    00257     if (exceptioncode)
    00258         return 0;
    00259
    00260     if (thisCont->getDocument() != sourceCont->getDocument()) {
    00261         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00262         return 0;
    00263     }
    00264
    00265     NodeImpl *thisTop = thisCont;
    00266     NodeImpl *sourceTop = sourceCont;
    00267     while (thisTop->parentNode())
    00268         thisTop = thisTop->parentNode();
    00269     while (sourceTop->parentNode())
    00270         sourceTop = sourceTop->parentNode();
    00271     if (thisTop != sourceTop) { // in different DocumentFragments
    00272         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00273         return 0;
    00274     }
    00275
    00276     switch(how)
    00277     {
    00278     case Range::START_TO_START:
    00279         return compareBoundaryPoints( m_startContainer, m_startOffset,
    00280                                       sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );
    00281         break;
    00282     case Range::START_TO_END:
    00283         return compareBoundaryPoints( m_startContainer, m_startOffset,
    00284                                       sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );
    00285         break;
    00286     case Range::END_TO_END:
    00287         return compareBoundaryPoints( m_endContainer, m_endOffset,
    00288                                       sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );
    00289         break;
    00290     case Range::END_TO_START:
    00291         return compareBoundaryPoints( m_endContainer, m_endOffset,
    00292                                       sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );
    00293         break;
    00294     default:
    00295         exceptioncode = DOMException::SYNTAX_ERR;
    00296         return 0;
    00297     }
    00298 }
    00299
    00300 short RangeImpl::compareBoundaryPoints( NodeImpl *containerA, long offsetA, NodeImpl *containerB, long offsetB )
    00301 {
    00302     // see DOM2 traversal & range section 2.5
    00303
    00304     // case 1: both points have the same container
    00305     if( containerA == containerB )
    00306     {
    00307         if( offsetA == offsetB )  return 0;    // A is equal to B
    00308         if( offsetA < offsetB )  return -1;    // A is before B
    00309         else  return 1;                        // A is after B
    00310     }
    00311
    00312     // case 2: node C (container B or an ancestor) is a child node of A
    00313     NodeImpl *c = containerB;
    00314     while (c && c->parentNode() != containerA)
    00315         c = c->parentNode();
    00316     if (c) {
    00317         int offsetC = 0;
    00318         NodeImpl *n = n = containerA->firstChild();
    00319         while (n != c) {
    00320             offsetC++;
    00321             n = n->nextSibling();
    00322         }
    00323
    00324         if( offsetA <= offsetC )  return -1;    // A is before B
    00325         else  return 1;                        // A is after B
    00326     }
    00327
    00328     // case 3: node C (container A or an ancestor) is a child node of B
    00329     c = containerA;
    00330     while (c && c->parentNode() != containerB)
    00331         c = c->parentNode();
    00332     if (c) {
    00333         int offsetC = 0;
    00334         NodeImpl *n = n = containerB->firstChild();
    00335         while (n != c) {
    00336             offsetC++;
    00337             n = n->nextSibling();
    00338         }
    00339
    00340         if( offsetC < offsetB )  return -1;    // A is before B
    00341         else  return 1;                        // A is after B
    00342     }
    00343
    00344     // case 4: containers A & B are siblings, or children of siblings
    00345     // ### we need to do a traversal here instead
    00346     NodeImpl *cmnRoot = commonAncestorContainer(containerA,containerB);
    00347     NodeImpl *childA = containerA;
    00348     while (childA->parentNode() != cmnRoot)
    00349         childA = childA->parentNode();
    00350     NodeImpl *childB = containerB;
    00351     while (childB->parentNode() != cmnRoot)
    00352         childB = childB->parentNode();
    00353
    00354     NodeImpl *n = cmnRoot->firstChild();
    00355     int i = 0;
    00356     int childAOffset = -1;
    00357     int childBOffset = -1;
    00358     while (childAOffset < 0 || childBOffset < 0) {
    00359         if (n == childA)
    00360             childAOffset = i;
    00361         if (n == childB)
    00362             childBOffset = i;
    00363         n = n->nextSibling();
    00364         i++;
    00365     }
    00366
    00367     if( childAOffset == childBOffset )  return 0;    // A is equal to B
    00368     if( childAOffset < childBOffset )   return -1;    // A is before B
    00369     else  return 1;                        // A is after B
    00370 }
    00371
    00372 bool RangeImpl::boundaryPointsValid(  )
    00373 {
    00374     short valid =  compareBoundaryPoints( m_startContainer, m_startOffset,
    00375                                           m_endContainer, m_endOffset );
    00376     if( valid == 1 )  return false;
    00377     else  return true;
    00378
    00379 }
    00380
    00381 void RangeImpl::deleteContents( int &exceptioncode ) {
    00382     if (m_detached) {
    00383         exceptioncode = DOMException::INVALID_STATE_ERR;
    00384         return;
    00385     }
    00386
    00387     checkDeleteExtract(exceptioncode);
    00388     if (exceptioncode)
    00389         return;
    00390
    00391     processContents(DELETE_CONTENTS,exceptioncode);
    00392 }
    00393
    00394 DocumentFragmentImpl *RangeImpl::processContents ( ActionType action, int &exceptioncode )
    00395 {
    00396     // ### when mutation events are implemented, we will have to take into account
    00397     // situations where the tree is being transformed while we delete - ugh!
    00398
    00399     // ### perhaps disable node deletion notification for this range while we do this?
    00400
    00401     if (collapsed(exceptioncode))
    00402         return 0;
    00403     if (exceptioncode)
    00404         return 0;
    00405
    00406     NodeImpl *cmnRoot = commonAncestorContainer(exceptioncode);
    00407     if (exceptioncode)
    00408         return 0;
    00409
    00410     // what is the highest node that partially selects the start of the range?
    00411     NodeImpl *partialStart = 0;
    00412     if (m_startContainer != cmnRoot) {
    00413         partialStart = m_startContainer;
    00414         while (partialStart->parentNode() != cmnRoot)
    00415             partialStart = partialStart->parentNode();
    00416     }
    00417
    00418     // what is the highest node that partially selects the end of the range?
    00419     NodeImpl *partialEnd = 0;
    00420     if (m_endContainer != cmnRoot) {
    00421         partialEnd = m_endContainer;
    00422         while (partialEnd->parentNode() != cmnRoot)
    00423             partialEnd = partialEnd->parentNode();
    00424     }
    00425
    00426     DocumentFragmentImpl *fragment = 0;
    00427     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
    00428         fragment = new DocumentFragmentImpl(m_ownerDocument);
    00429
    00430     // Simple case: the start and end containers are the same. We just grab
    00431     // everything >= start offset and < end offset
    00432     if (m_startContainer == m_endContainer) {
    00433         if(m_startContainer->nodeType() == Node::TEXT_NODE ||
    00434            m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
    00435            m_startContainer->nodeType() == Node::COMMENT_NODE) {
    00436
    00437             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    00438                 CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
    00439                 c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_endOffset,exceptioncode);
    00440                 c->deleteData(0,m_startOffset,exceptioncode);
    00441                 fragment->appendChild(c,exceptioncode);
    00442             }
    00443             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
    00444                 static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(m_startOffset,m_endOffset-m_startOffset,exceptioncode);
    00445         }
    00446         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
    00447             // ### operate just on data ?
    00448         }
    00449         else {
    00450             NodeImpl *n = m_startContainer->firstChild();
    00451             unsigned long i;
    00452             for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
    00453                 n = n->nextSibling();
    00454             while (n && i < m_endOffset) { // delete until m_endOffset
    00455                 NodeImpl *next = n->nextSibling();
    00456                 if (action == EXTRACT_CONTENTS)
    00457                     fragment->appendChild(n,exceptioncode); // will remove n from its parent
    00458                 else if (action == CLONE_CONTENTS)
    00459                     fragment->appendChild(n->cloneNode(true),exceptioncode);
    00460                 else
    00461                     m_startContainer->removeChild(n,exceptioncode);
    00462                 n = next;
    00463                 i++;
    00464             }
    00465         }
    00466         collapse(true,exceptioncode);
    00467         return fragment;
    00468     }
    00469
    00470     // Complex case: Start and end containers are different.
    00471     // There are three possiblities here:
    00472     // 1. Start container == cmnRoot (End container must be a descendant)
    00473     // 2. End container == cmnRoot (Start container must be a descendant)
    00474     // 3. Neither is cmnRoot, they are both descendants
    00475     //
    00476     // In case 3, we grab everything after the start (up until a direct child
    00477     // of cmnRoot) into leftContents, and everything before the end (up until
    00478     // a direct child of cmnRoot) into rightContents. Then we process all
    00479     // cmnRoot children between leftContents and rightContents
    00480     //
    00481     // In case 1 or 2, we skip either processing of leftContents or rightContents,
    00482     // in which case the last lot of nodes either goes from the first or last
    00483     // child of cmnRoot.
    00484     //
    00485     // These are deleted, cloned, or extracted (i.e. both) depending on action.
    00486
    00487     NodeImpl *leftContents = 0;
    00488     if (m_startContainer != cmnRoot) {
    00489         // process the left-hand side of the range, up until the last ancestor of
    00490         // m_startContainer before cmnRoot
    00491         if(m_startContainer->nodeType() == Node::TEXT_NODE ||
    00492            m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
    00493            m_startContainer->nodeType() == Node::COMMENT_NODE) {
    00494
    00495             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    00496                 CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
    00497                 c->deleteData(0,m_startOffset,exceptioncode);
    00498                 leftContents = c;
    00499             }
    00500             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
    00501                 static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(
    00502                     m_startOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_startOffset,exceptioncode);
    00503         }
    00504         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
    00505             // ### operate just on data ?
    00506             // leftContents = ...
    00507         }
    00508         else {
    00509             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
    00510                 leftContents = m_startContainer->cloneNode(false);
    00511             NodeImpl *n = m_startContainer->firstChild();
    00512             unsigned long i;
    00513             for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
    00514                 n = n->nextSibling();
    00515             while (n) { // process until end
    00516                 NodeImpl *next = n->nextSibling();
    00517                 if (action == EXTRACT_CONTENTS)
    00518                     leftContents->appendChild(n,exceptioncode); // will remove n from m_startContainer
    00519                 else if (action == CLONE_CONTENTS)
    00520                     leftContents->appendChild(n->cloneNode(true),exceptioncode);
    00521                 else
    00522                     m_startContainer->removeChild(n,exceptioncode);
    00523                 n = next;
    00524             }
    00525         }
    00526
    00527         NodeImpl *leftParent = m_startContainer->parentNode();
    00528         NodeImpl *n = m_startContainer->nextSibling();
    00529         for (; leftParent != cmnRoot; leftParent = leftParent->parentNode()) {
    00530             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    00531                 NodeImpl *leftContentsParent = leftParent->cloneNode(false);
    00532                 leftContentsParent->appendChild(leftContents,exceptioncode);
    00533                 leftContents = leftContentsParent;
    00534             }
    00535
    00536             NodeImpl *next;
    00537             for (; n; n = next ) {
    00538                 next = n->nextSibling();
    00539                 if (action == EXTRACT_CONTENTS)
    00540                     leftContents->appendChild(n,exceptioncode); // will remove n from leftParent
    00541                 else if (action == CLONE_CONTENTS)
    00542                     leftContents->appendChild(n->cloneNode(true),exceptioncode);
    00543                 else
    00544                     leftParent->removeChild(n,exceptioncode);
    00545             }
    00546             n = leftParent->nextSibling();
    00547         }
    00548     }
    00549
    00550     NodeImpl *rightContents = 0;
    00551     if (m_endContainer != cmnRoot) {
    00552         // delete the right-hand side of the range, up until the last ancestor of
    00553         // m_endContainer before cmnRoot
    00554         if(m_endContainer->nodeType() == Node::TEXT_NODE ||
    00555            m_endContainer->nodeType() == Node::CDATA_SECTION_NODE ||
    00556            m_endContainer->nodeType() == Node::COMMENT_NODE) {
    00557
    00558             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    00559                 CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_endContainer->cloneNode(true));
    00560                 c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_endContainer)->length()-m_endOffset,exceptioncode);
    00561                 rightContents = c;
    00562             }
    00563             if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
    00564                 static_cast<CharacterDataImpl*>(m_endContainer)->deleteData(0,m_endOffset,exceptioncode);
    00565         }
    00566         else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
    00567             // ### operate just on data ?
    00568             // rightContents = ...
    00569         }
    00570         else {
    00571             if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
    00572                 rightContents = m_endContainer->cloneNode(false);
    00573             NodeImpl *n = m_endContainer->firstChild();
    00574             unsigned long i;
    00575             for(i = 0; i+1 < m_endOffset; i++) // skip to m_endOffset
    00576                 n = n->nextSibling();
    00577             NodeImpl *prev;
    00578             for (; n; n = prev ) {
    00579                 prev = n->previousSibling();
    00580                 if (action == EXTRACT_CONTENTS)
    00581                     rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
    00582                 else if (action == CLONE_CONTENTS)
    00583                     rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
    00584                 else
    00585                     m_endContainer->removeChild(n,exceptioncode);
    00586             }
    00587         }
    00588
    00589         NodeImpl *rightParent = m_endContainer->parentNode();
    00590         NodeImpl *n = m_endContainer->previousSibling();
    00591         for (; rightParent != cmnRoot; rightParent = rightParent->parentNode()) {
    00592                 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    00593                     NodeImpl *rightContentsParent = rightParent->cloneNode(false);
    00594                     rightContentsParent->appendChild(rightContents,exceptioncode);
    00595                     rightContents = rightContentsParent;
    00596             }
    00597
    00598             NodeImpl *prev;
    00599             for (; n; n = prev ) {
    00600                 prev = n->previousSibling();
    00601                 if (action == EXTRACT_CONTENTS)
    00602                     rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
    00603                 else if (action == CLONE_CONTENTS)
    00604                     rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
    00605                 else
    00606                     rightParent->removeChild(n,exceptioncode);
    00607
    00608             }
    00609             n = rightParent->previousSibling();
    00610         }
    00611     }
    00612
    00613     // delete all children of cmnRoot between the start and end container
    00614
    00615     NodeImpl *processStart; // child of cmnRooot
    00616     if (m_startContainer == cmnRoot) {
    00617         unsigned long i;
    00618         processStart = m_startContainer->firstChild();
    00619         for (i = 0; i < m_startOffset; i++)
    00620             processStart = processStart->nextSibling();
    00621     }
    00622     else {
    00623         processStart = m_startContainer;
    00624         while (processStart->parentNode() != cmnRoot)
    00625             processStart = processStart->parentNode();
    00626         processStart = processStart->nextSibling();
    00627     }
    00628     NodeImpl *processEnd; // child of cmnRooot
    00629     if (m_endContainer == cmnRoot) {
    00630         unsigned long i;
    00631         processEnd = m_endContainer->firstChild();
    00632         for (i = 0; i < m_endOffset; i++)
    00633             processEnd = processEnd->nextSibling();
    00634     }
    00635     else {
    00636         processEnd = m_endContainer;
    00637         while (processEnd->parentNode() != cmnRoot)
    00638             processEnd = processEnd->parentNode();
    00639     }
    00640
    00641     // Now add leftContents, stuff in between, and rightContents to the fragment
    00642     // (or just delete the stuff in between)
    00643
    00644     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
    00645       fragment->appendChild(leftContents,exceptioncode);
    00646
    00647     NodeImpl *next;
    00648     NodeImpl *n;
    00649     if (processStart) {
    00650         for (n = processStart; n && n != processEnd; n = next) {
    00651             next = n->nextSibling();
    00652
    00653             if (action == EXTRACT_CONTENTS)
    00654                 fragment->appendChild(n,exceptioncode); // will remove from cmnRoot
    00655             else if (action == CLONE_CONTENTS)
    00656                 fragment->appendChild(n->cloneNode(true),exceptioncode);
    00657             else
    00658                 cmnRoot->removeChild(n,exceptioncode);
    00659         }
    00660     }
    00661
    00662     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
    00663       fragment->appendChild(rightContents,exceptioncode);
    00664
    00665     // collapse to the proper position - see spec section 2.6
    00666     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
    00667         if (!partialStart && !partialEnd)
    00668             collapse(true,exceptioncode);
    00669         else if (partialStart) {
    00670             setStartContainer(partialStart->parentNode());
    00671             setEndContainer(partialStart->parentNode());
    00672             m_startOffset = m_endOffset = partialStart->nodeIndex()+1;
    00673         }
    00674         else if (partialEnd) {
    00675             setStartContainer(partialEnd->parentNode());
    00676             setEndContainer(partialEnd->parentNode());
    00677             m_startOffset = m_endOffset = partialEnd->nodeIndex();
    00678         }
    00679     }
    00680     return fragment;
    00681 }
    00682
    00683
    00684 DocumentFragmentImpl *RangeImpl::extractContents( int &exceptioncode )
    00685 {
    00686     if (m_detached) {
    00687         exceptioncode = DOMException::INVALID_STATE_ERR;
    00688         return 0;
    00689     }
    00690
    00691     checkDeleteExtract(exceptioncode);
    00692     if (exceptioncode)
    00693         return 0;
    00694
    00695     return processContents(EXTRACT_CONTENTS,exceptioncode);
    00696 }
    00697
    00698 DocumentFragmentImpl *RangeImpl::cloneContents( int &exceptioncode  )
    00699 {
    00700     if (m_detached) {
    00701         exceptioncode = DOMException::INVALID_STATE_ERR;
    00702         return 0;
    00703     }
    00704
    00705     return processContents(CLONE_CONTENTS,exceptioncode);
    00706 }
    00707
    00708 void RangeImpl::insertNode( NodeImpl *newNode, int &exceptioncode )
    00709 {
    00710     if (m_detached) {
    00711         exceptioncode = DOMException::INVALID_STATE_ERR;
    00712         return;
    00713     }
    00714
    00715     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
    00716     // the Range is read-only.
    00717     NodeImpl *n = m_startContainer;
    00718     while (n && !n->isReadOnly())
    00719         n = n->parentNode();
    00720     if (n) {
    00721         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00722         return;
    00723     }
    00724
    00725     n = m_endContainer;
    00726     while (n && !n->isReadOnly())
    00727         n = n->parentNode();
    00728     if (n) {
    00729         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00730         return;
    00731     }
    00732
    00733     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
    00734     // not created from the same document.
    00735     if (newNode->getDocument() != m_startContainer->getDocument()) {
    00736         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00737         return;
    00738     }
    00739
    00740
    00741     // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
    00742     // does not allow children of the type of newNode or if newNode is an ancestor of the container.
    00743
    00744     // an extra one here - if a text node is going to split, it must have a parent to insert into
    00745     if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
    00746         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    00747         return;
    00748     }
    00749
    00750     // In the case where the container is a text node, we check against the container's parent, because
    00751     // text nodes get split up upon insertion.
    00752     NodeImpl *checkAgainst;
    00753     if (m_startContainer->nodeType() == Node::TEXT_NODE)
    00754         checkAgainst = m_startContainer->parentNode();
    00755     else
    00756         checkAgainst = m_startContainer;
    00757
    00758     if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
    00759         // check each child node, not the DocumentFragment itself
    00760         NodeImpl *c;
    00761         for (c = newNode->firstChild(); c; c = c->nextSibling()) {
    00762             if (!checkAgainst->childTypeAllowed(c->nodeType())) {
    00763                 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    00764                 return;
    00765             }
    00766         }
    00767     }
    00768     else {
    00769         if (!checkAgainst->childTypeAllowed(newNode->nodeType())) {
    00770             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    00771             return;
    00772         }
    00773     }
    00774
    00775     for (n = m_startContainer; n; n = n->parentNode()) {
    00776         if (n == newNode) {
    00777             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    00778             return;
    00779         }
    00780     }
    00781
    00782     // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
    00783     if( newNode->nodeType() == Node::ATTRIBUTE_NODE ||
    00784         newNode->nodeType() == Node::ENTITY_NODE ||
    00785         newNode->nodeType() == Node::NOTATION_NODE ||
    00786         newNode->nodeType() == Node::DOCUMENT_NODE) {
    00787         exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    00788         return;
    00789     }
    00790
    00791     if( m_startContainer->nodeType() == Node::TEXT_NODE ||
    00792         m_startContainer->nodeType() == Node::CDATA_SECTION_NODE )
    00793     {
    00794         TextImpl *newText = static_cast<TextImpl*>(m_startContainer)->splitText(m_startOffset,exceptioncode);
    00795         if (exceptioncode)
    00796             return;
    00797         m_startContainer->parentNode()->insertBefore( newNode, newText, exceptioncode );
    00798     }
    00799     else {
    00800         m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), exceptioncode );
    00801     }
    00802 }
    00803
    00804 DOMString RangeImpl::toString( int &exceptioncode )
    00805 {
    00806     if (m_detached) {
    00807         exceptioncode = DOMException::INVALID_STATE_ERR;
    00808         return DOMString();
    00809     }
    00810
    00811     DOMString text = "";
    00812     NodeImpl *n = m_startContainer;
    00813     while(n) {
    00814         if(n->nodeType() == DOM::Node::TEXT_NODE ||
    00815            n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
    00816
    00817             DOMString str;
    00818             if (static_cast<TextImpl *>(n)->string())
    00819                str = static_cast<TextImpl *>(n)->string()->copy();
    00820             if (n == m_endContainer)
    00821                 str.truncate(m_endOffset);
    00822             if (n == m_startContainer)
    00823                 str.remove(0,m_startOffset);
    00824             text += str;
    00825             if (n == m_endContainer)
    00826                 break;
    00827         }
    00828         else if (n->parentNode() == m_endContainer && !n->nextSibling()) {
    00829             break;
    00830         }
    00831         //if (n == m_endContainer) break;
    00832         NodeImpl *next = n->firstChild();
    00833         if (!next) next = n->nextSibling();
    00834
    00835         while( !next && n->parentNode() ) {
    00836             n = n->parentNode();
    00837             next = n->nextSibling();
    00838         }
    00839         n = next;
    00840     }
    00841     return text;
    00842 }
    00843
    00844 DOMString RangeImpl::toHTML(  )
    00845 {
    00846     // ### implement me!!!!
    00847     return DOMString();
    00848 }
    00849
    00850 void RangeImpl::detach( int &exceptioncode )
    00851 {
    00852     if (m_detached) {
    00853         exceptioncode = DOMException::INVALID_STATE_ERR;
    00854         return;
    00855     }
    00856
    00857     if (m_startContainer)
    00858         m_startContainer->deref();
    00859     m_startContainer = 0;
    00860     if (m_endContainer)
    00861         m_endContainer->deref();
    00862     m_endContainer = 0;
    00863     m_detached = true;
    00864 }
    00865
    00866 bool RangeImpl::isDetached() const
    00867 {
    00868     return m_detached;
    00869 }
    00870
    00871 void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const
    00872 {
    00873     if( offset < 0 ) {
    00874         exceptioncode = DOMException::INDEX_SIZE_ERR;
    00875     }
    00876
    00877     switch (n->nodeType()) {
    00878         case Node::ENTITY_NODE:
    00879         case Node::NOTATION_NODE:
    00880         case Node::DOCUMENT_TYPE_NODE:
    00881             exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    00882             break;
    00883         case Node::TEXT_NODE:
    00884         case Node::COMMENT_NODE:
    00885         case Node::CDATA_SECTION_NODE:
    00886             if ( (unsigned long)offset > static_cast<CharacterDataImpl*>(n)->length() )
    00887                 exceptioncode = DOMException::INDEX_SIZE_ERR;
    00888             break;
    00889         case Node::PROCESSING_INSTRUCTION_NODE:
    00890             // ### are we supposed to check with just data or the whole contents?
    00891             if ( (unsigned long)offset > static_cast<ProcessingInstructionImpl*>(n)->data().length() )
    00892                 exceptioncode = DOMException::INDEX_SIZE_ERR;
    00893             break;
    00894         default:
    00895             if ( (unsigned long)offset > n->childNodeCount() )
    00896                 exceptioncode = DOMException::INDEX_SIZE_ERR;
    00897             break;
    00898     }
    00899 }
    00900
    00901 void RangeImpl::checkNodeBA( NodeImpl *n, int &exceptioncode ) const
    00902 {
    00903     // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
    00904     // Attr, Document or DocumentFragment node or if refNode is a Document,
    00905     // DocumentFragment, Attr, Entity, or Notation node.
    00906     NodeImpl *root = n;
    00907     while (root->parentNode())
    00908         root = root->parentNode();
    00909     if (!(root->nodeType() == Node::ATTRIBUTE_NODE ||
    00910           root->nodeType() == Node::DOCUMENT_NODE ||
    00911           root->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)) {
    00912         exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    00913         return;
    00914     }
    00915
    00916     if( n->nodeType() == Node::DOCUMENT_NODE ||
    00917         n->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
    00918         n->nodeType() == Node::ATTRIBUTE_NODE ||
    00919         n->nodeType() == Node::ENTITY_NODE ||
    00920         n->nodeType() == Node::NOTATION_NODE )
    00921         exceptioncode = RangeException::INVALID_NODE_TYPE_ERR  + RangeException::_EXCEPTION_OFFSET;
    00922
    00923 }
    00924
    00925 RangeImpl *RangeImpl::cloneRange(int &exceptioncode)
    00926 {
    00927     if (m_detached) {
    00928         exceptioncode = DOMException::INVALID_STATE_ERR;
    00929         return 0;
    00930     }
    00931
    00932     return new RangeImpl(m_ownerDocument,m_startContainer,m_startOffset,m_endContainer,m_endOffset);
    00933 }
    00934
    00935 void RangeImpl::setStartAfter( NodeImpl *refNode, int &exceptioncode )
    00936 {
    00937     if (m_detached) {
    00938         exceptioncode = DOMException::INVALID_STATE_ERR;
    00939         return;
    00940     }
    00941
    00942     if (!refNode) {
    00943         exceptioncode = DOMException::NOT_FOUND_ERR;
    00944         return;
    00945     }
    00946
    00947     if (refNode->getDocument() != m_ownerDocument->document()) {
    00948         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00949         return;
    00950     }
    00951
    00952     checkNodeBA( refNode, exceptioncode );
    00953     if (exceptioncode)
    00954         return;
    00955
    00956     setStart( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
    00957 }
    00958
    00959 void RangeImpl::setEndBefore( NodeImpl *refNode, int &exceptioncode )
    00960 {
    00961     if (m_detached) {
    00962         exceptioncode = DOMException::INVALID_STATE_ERR;
    00963         return;
    00964     }
    00965
    00966     if (!refNode) {
    00967         exceptioncode = DOMException::NOT_FOUND_ERR;
    00968         return;
    00969     }
    00970
    00971     if (refNode->getDocument() != m_ownerDocument->document()) {
    00972         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00973         return;
    00974     }
    00975
    00976     checkNodeBA( refNode, exceptioncode );
    00977     if (exceptioncode)
    00978         return;
    00979
    00980     setEnd( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
    00981 }
    00982
    00983 void RangeImpl::setEndAfter( NodeImpl *refNode, int &exceptioncode )
    00984 {
    00985     if (m_detached) {
    00986         exceptioncode = DOMException::INVALID_STATE_ERR;
    00987         return;
    00988     }
    00989
    00990     if (!refNode) {
    00991         exceptioncode = DOMException::NOT_FOUND_ERR;
    00992         return;
    00993     }
    00994
    00995     if (refNode->getDocument() != m_ownerDocument->document()) {
    00996         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00997         return;
    00998     }
    00999
    01000     checkNodeBA( refNode, exceptioncode );
    01001     if (exceptioncode)
    01002         return;
    01003
    01004     setEnd( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
    01005
    01006 }
    01007
    01008 void RangeImpl::selectNode( NodeImpl *refNode, int &exceptioncode )
    01009 {
    01010     if (m_detached) {
    01011         exceptioncode = DOMException::INVALID_STATE_ERR;
    01012         return;
    01013     }
    01014
    01015     if (!refNode) {
    01016         exceptioncode = DOMException::NOT_FOUND_ERR;
    01017         return;
    01018     }
    01019
    01020     // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
    01021     // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
    01022     // node.
    01023     NodeImpl *anc;
    01024     for (anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
    01025         if (anc->nodeType() == Node::ENTITY_NODE ||
    01026             anc->nodeType() == Node::NOTATION_NODE ||
    01027             anc->nodeType() == Node::DOCUMENT_TYPE_NODE) {
    01028
    01029             exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    01030             return;
    01031         }
    01032     }
    01033
    01034     if (refNode->nodeType() == Node::DOCUMENT_NODE ||
    01035         refNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
    01036         refNode->nodeType() == Node::ATTRIBUTE_NODE ||
    01037         refNode->nodeType() == Node::ENTITY_NODE ||
    01038         refNode->nodeType() == Node::NOTATION_NODE) {
    01039
    01040         exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    01041         return;
    01042     }
    01043
    01044     setStartBefore( refNode, exceptioncode );
    01045     if (exceptioncode)
    01046         return;
    01047     setEndAfter( refNode, exceptioncode );
    01048 }
    01049
    01050 void RangeImpl::selectNodeContents( NodeImpl *refNode, int &exceptioncode )
    01051 {
    01052     if (m_detached) {
    01053         exceptioncode = DOMException::INVALID_STATE_ERR;
    01054         return;
    01055     }
    01056
    01057     if (!refNode) {
    01058         exceptioncode = DOMException::NOT_FOUND_ERR;
    01059         return;
    01060     }
    01061
    01062     // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
    01063     // or DocumentType node.
    01064     NodeImpl *n;
    01065     for (n = refNode; n; n = n->parentNode()) {
    01066         if (n->nodeType() == Node::ENTITY_NODE ||
    01067             n->nodeType() == Node::NOTATION_NODE ||
    01068             n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
    01069
    01070             exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    01071             return;
    01072         }
    01073     }
    01074
    01075     setStartContainer(refNode);
    01076     m_startOffset = 0;
    01077     setEndContainer(refNode);
    01078     m_endOffset = refNode->childNodeCount();
    01079 }
    01080
    01081 void RangeImpl::surroundContents( NodeImpl *newParent, int &exceptioncode )
    01082 {
    01083     if (m_detached) {
    01084         exceptioncode = DOMException::INVALID_STATE_ERR;
    01085         return;
    01086     }
    01087
    01088     if( !newParent ) {
    01089         exceptioncode = DOMException::NOT_FOUND_ERR;
    01090         return;
    01091     }
    01092
    01093     // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
    01094     // Document, or DocumentFragment node.
    01095     if( newParent->nodeType() == Node::ATTRIBUTE_NODE ||
    01096         newParent->nodeType() == Node::ENTITY_NODE ||
    01097         newParent->nodeType() == Node::NOTATION_NODE ||
    01098         newParent->nodeType() == Node::DOCUMENT_TYPE_NODE ||
    01099         newParent->nodeType() == Node::DOCUMENT_NODE ||
    01100         newParent->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
    01101         exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
    01102         return;
    01103     }
    01104
    01105     // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
    01106     // the Range is read-only.
    01107     if (readOnly()) {
    01108         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    01109         return;
    01110     }
    01111
    01112     NodeImpl *n = m_startContainer;
    01113     while (n && !n->isReadOnly())
    01114         n = n->parentNode();
    01115     if (n) {
    01116         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    01117         return;
    01118     }
    01119
    01120     n = m_endContainer;
    01121     while (n && !n->isReadOnly())
    01122         n = n->parentNode();
    01123     if (n) {
    01124         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    01125         return;
    01126     }
    01127
    01128     // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
    01129     // not created from the same document.
    01130     if (newParent->getDocument() != m_startContainer->getDocument()) {
    01131         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    01132         return;
    01133     }
    01134
    01135     // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
    01136     // does not allow children of the type of newParent or if newParent is an ancestor of the container
    01137     // or if node would end up with a child node of a type not allowed by the type of node.
    01138     if (!m_startContainer->childTypeAllowed(newParent->nodeType())) {
    01139         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    01140         return;
    01141     }
    01142
    01143     for (n = m_startContainer; n; n = n->parentNode()) {
    01144         if (n == newParent) {
    01145             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    01146             return;
    01147         }
    01148     }
    01149
    01150     // ### check if node would end up with a child node of a type not allowed by the type of node
    01151
    01152     // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text node.
    01153     if (m_startContainer->nodeType() != Node::TEXT_NODE &&
    01154         m_startContainer->nodeType() != Node::COMMENT_NODE &&
    01155         m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
    01156         m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
    01157
    01158         if (m_startOffset > 0 && m_startOffset < m_startContainer->childNodeCount()) {
    01159             exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
    01160             return;
    01161         }
    01162     }
    01163
    01164     if (m_endContainer->nodeType() != Node::TEXT_NODE &&
    01165         m_endContainer->nodeType() != Node::COMMENT_NODE &&
    01166         m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
    01167         m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
    01168
    01169         if (m_endOffset > 0 && m_endOffset < m_endContainer->childNodeCount()) {
    01170             exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
    01171             return;
    01172         }
    01173     }
    01174
    01175     while (newParent->firstChild()) {
    01176         newParent->removeChild(newParent->firstChild(),exceptioncode);
    01177         if (exceptioncode)
    01178             return;
    01179     }
    01180     DocumentFragmentImpl *fragment = extractContents(exceptioncode);
    01181     if (exceptioncode)
    01182         return;
    01183     insertNode( newParent, exceptioncode );
    01184     if (exceptioncode)
    01185         return;
    01186     newParent->appendChild( fragment, exceptioncode );
    01187     if (exceptioncode)
    01188         return;
    01189     selectNode( newParent, exceptioncode );
    01190 }
    01191
    01192 void RangeImpl::setStartBefore( NodeImpl *refNode, int &exceptioncode )
    01193 {
    01194     if (m_detached) {
    01195         exceptioncode = DOMException::INVALID_STATE_ERR;
    01196         return;
    01197     }
    01198
    01199     if (!refNode) {
    01200         exceptioncode = DOMException::NOT_FOUND_ERR;
    01201         return;
    01202     }
    01203
    01204     if (refNode->getDocument() != m_ownerDocument->document()) {
    01205         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    01206         return;
    01207     }
    01208
    01209     checkNodeBA( refNode, exceptioncode );
    01210     if (exceptioncode)
    01211         return;
    01212
    01213     setStart( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
    01214 }
    01215
    01216 void RangeImpl::setStartContainer(NodeImpl *_startContainer)
    01217 {
    01218     if (m_startContainer == _startContainer)
    01219         return;
    01220
    01221     if (m_startContainer)
    01222         m_startContainer->deref();
    01223     m_startContainer = _startContainer;
    01224     if (m_startContainer)
    01225         m_startContainer->ref();
    01226 }
    01227
    01228 void RangeImpl::setEndContainer(NodeImpl *_endContainer)
    01229 {
    01230     if (m_endContainer == _endContainer)
    01231         return;
    01232
    01233     if (m_endContainer)
    01234         m_endContainer->deref();
    01235     m_endContainer = _endContainer;
    01236     if (m_endContainer)
    01237         m_endContainer->ref();
    01238 }
    01239
    01240 void RangeImpl::checkDeleteExtract(int &exceptioncode) {
    01241
    01242     NodeImpl *start;
    01243     if (m_startContainer->nodeType() != Node::TEXT_NODE &&
    01244         m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
    01245         m_startContainer->nodeType() != Node::COMMENT_NODE &&
    01246         m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
    01247
    01248         start = m_startContainer->childNode(m_startOffset);
    01249         if (!start) {
    01250             if (m_startContainer->lastChild())
    01251                 start = m_startContainer->lastChild()->traverseNextNode();
    01252             else
    01253                 start = m_startContainer->traverseNextNode();
    01254         }
    01255     }
    01256     else
    01257         start = m_startContainer;
    01258
    01259     NodeImpl *end;
    01260     if (m_endContainer->nodeType() != Node::TEXT_NODE &&
    01261         m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
    01262         m_endContainer->nodeType() != Node::COMMENT_NODE &&
    01263         m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
    01264
    01265         end = m_endContainer->childNode(m_endOffset);
    01266         if (!end) {
    01267             if (m_endContainer->lastChild())
    01268                 end = m_endContainer->lastChild()->traverseNextNode();
    01269             else
    01270                 end = m_endContainer->traverseNextNode();
    01271         }
    01272     }
    01273     else
    01274         end = m_endContainer;
    01275
    01276     NodeImpl *n;
    01277     for (n = start; n != end; n = n->traverseNextNode()) {
    01278         if (n->isReadOnly()) {
    01279             exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    01280             return;
    01281         }
    01282         if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { // ### is this for only directly under the DF, or anywhere?
    01283             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    01284             return;
    01285         }
    01286     }
    01287
    01288     if (containedByReadOnly()) {
    01289         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    01290         return;
    01291     }
    01292 }
    01293
    01294
    01295 bool RangeImpl::containedByReadOnly() {
    01296     NodeImpl *n;
    01297     for (n = m_startContainer; n; n = n->parentNode()) {
    01298         if (n->isReadOnly())
    01299             return true;
    01300     }
    01301     for (n = m_endContainer; n; n = n->parentNode()) {
    01302         if (n->isReadOnly())
    01303             return true;
    01304     }
    01305     return false;
    01306 }
    01307
    01308
    01309
    01310
    01311
    01312
    01313
    01314

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:38 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001