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)
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
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
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
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
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 )
00232 {
00233 setEndContainer(m_startContainer);
00234 m_endOffset = m_startOffset;
00235 }
00236 else
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) {
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
00303
00304
00305 if( containerA == containerB )
00306 {
00307 if( offsetA == offsetB ) return 0;
00308 if( offsetA < offsetB ) return -1;
00309 else return 1;
00310 }
00311
00312
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;
00325 else return 1;
00326 }
00327
00328
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;
00341 else return 1;
00342 }
00343
00344
00345
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;
00368 if( childAOffset < childBOffset ) return -1;
00369 else return 1;
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
00397
00398
00399
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
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
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
00431
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
00448 }
00449 else {
00450 NodeImpl *n = m_startContainer->firstChild();
00451 unsigned long i;
00452 for(i = 0; i < m_startOffset; i++)
00453 n = n->nextSibling();
00454 while (n && i < m_endOffset) {
00455 NodeImpl *next = n->nextSibling();
00456 if (action == EXTRACT_CONTENTS)
00457 fragment->appendChild(n,exceptioncode);
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
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 NodeImpl *leftContents = 0;
00488 if (m_startContainer != cmnRoot) {
00489
00490
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
00506
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++)
00514 n = n->nextSibling();
00515 while (n) {
00516 NodeImpl *next = n->nextSibling();
00517 if (action == EXTRACT_CONTENTS)
00518 leftContents->appendChild(n,exceptioncode);
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);
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
00553
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
00568
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++)
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);
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);
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
00614
00615 NodeImpl *processStart;
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;
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
00642
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);
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
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
00716
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
00734
00735 if (newNode->getDocument() != m_startContainer->getDocument()) {
00736 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00737 return;
00738 }
00739
00740
00741
00742
00743
00744
00745 if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
00746 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00747 return;
00748 }
00749
00750
00751
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
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
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
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
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
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
00904
00905
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
01021
01022
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
01063
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
01094
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
01106
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
01129
01130 if (newParent->getDocument() != m_startContainer->getDocument()) {
01131 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
01132 return;
01133 }
01134
01135
01136
01137
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
01151
01152
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) {
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