1 16 17 package org.apache.xerces.dom; 18 19 import java.util.Vector ; 20 21 import org.w3c.dom.CharacterData ; 22 import org.w3c.dom.DOMException ; 23 import org.w3c.dom.DocumentFragment ; 24 import org.w3c.dom.Node ; 25 import org.w3c.dom.ranges.Range; 26 import org.w3c.dom.ranges.RangeException; 27 28 29 37 public class RangeImpl implements Range { 38 39 43 44 48 DocumentImpl fDocument; 49 Node fStartContainer; 50 Node fEndContainer; 51 int fStartOffset; 52 int fEndOffset; 53 boolean fIsCollapsed; 54 boolean fDetach = false; 55 Node fInsertNode = null; 56 Node fDeleteNode = null; 57 Node fSplitNode = null; 58 boolean fInsertedFromRange = false; 60 61 65 public RangeImpl(DocumentImpl document) { 66 fDocument = document; 67 fStartContainer = document; 68 fEndContainer = document; 69 fStartOffset = 0; 70 fEndOffset = 0; 71 fDetach = false; 72 } 73 74 public Node getStartContainer() { 75 if ( fDetach ) { 76 throw new DOMException ( 77 DOMException.INVALID_STATE_ERR, 78 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 79 } 80 return fStartContainer; 81 } 82 83 public int getStartOffset() { 84 if ( fDetach ) { 85 throw new DOMException ( 86 DOMException.INVALID_STATE_ERR, 87 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 88 } 89 return fStartOffset; 90 } 91 92 public Node getEndContainer() { 93 if ( fDetach ) { 94 throw new DOMException ( 95 DOMException.INVALID_STATE_ERR, 96 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 97 } 98 return fEndContainer; 99 } 100 101 public int getEndOffset() { 102 if ( fDetach ) { 103 throw new DOMException ( 104 DOMException.INVALID_STATE_ERR, 105 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 106 } 107 return fEndOffset; 108 } 109 110 public boolean getCollapsed() { 111 if ( fDetach ) { 112 throw new DOMException ( 113 DOMException.INVALID_STATE_ERR, 114 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 115 } 116 return (fStartContainer == fEndContainer 117 && fStartOffset == fEndOffset); 118 } 119 120 public Node getCommonAncestorContainer() { 121 if ( fDetach ) { 122 throw new DOMException ( 123 DOMException.INVALID_STATE_ERR, 124 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 125 } 126 Vector startV = new Vector (); 127 Node node; 128 for (node=fStartContainer; node != null; 129 node=node.getParentNode()) 130 { 131 startV.addElement(node); 132 } 133 Vector endV = new Vector (); 134 for (node=fEndContainer; node != null; 135 node=node.getParentNode()) 136 { 137 endV.addElement(node); 138 } 139 int s = startV.size()-1; 140 int e = endV.size()-1; 141 Object result = null; 142 while (s>=0 && e>=0) { 143 if (startV.elementAt(s) == endV.elementAt(e)) { 144 result = startV.elementAt(s); 145 } else { 146 break; 147 } 148 --s; 149 --e; 150 } 151 return (Node )result; 152 } 153 154 155 public void setStart(Node refNode, int offset) 156 throws RangeException, DOMException 157 { 158 if (fDocument.errorChecking) { 159 if ( fDetach) { 160 throw new DOMException ( 161 DOMException.INVALID_STATE_ERR, 162 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 163 } 164 if ( !isLegalContainer(refNode)) { 165 throw new RangeExceptionImpl( 166 RangeException.INVALID_NODE_TYPE_ERR, 167 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 168 } 169 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 170 throw new DOMException ( 171 DOMException.WRONG_DOCUMENT_ERR, 172 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 173 } 174 } 175 176 checkIndex(refNode, offset); 177 178 fStartContainer = refNode; 179 fStartOffset = offset; 180 181 if (getCommonAncestorContainer() == null 187 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 188 collapse(true); 189 } 190 } 191 192 public void setEnd(Node refNode, int offset) 193 throws RangeException, DOMException 194 { 195 if (fDocument.errorChecking) { 196 if (fDetach) { 197 throw new DOMException ( 198 DOMException.INVALID_STATE_ERR, 199 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 200 } 201 if ( !isLegalContainer(refNode)) { 202 throw new RangeExceptionImpl( 203 RangeException.INVALID_NODE_TYPE_ERR, 204 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 205 } 206 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 207 throw new DOMException ( 208 DOMException.WRONG_DOCUMENT_ERR, 209 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 210 } 211 } 212 213 checkIndex(refNode, offset); 214 215 fEndContainer = refNode; 216 fEndOffset = offset; 217 218 if (getCommonAncestorContainer() == null 224 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 225 collapse(false); 226 } 227 } 228 229 public void setStartBefore(Node refNode) 230 throws RangeException 231 { 232 if (fDocument.errorChecking) { 233 if (fDetach) { 234 throw new DOMException ( 235 DOMException.INVALID_STATE_ERR, 236 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 237 } 238 if ( !hasLegalRootContainer(refNode) || 239 !isLegalContainedNode(refNode) ) 240 { 241 throw new RangeExceptionImpl( 242 RangeException.INVALID_NODE_TYPE_ERR, 243 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 244 } 245 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 246 throw new DOMException ( 247 DOMException.WRONG_DOCUMENT_ERR, 248 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 249 } 250 } 251 252 fStartContainer = refNode.getParentNode(); 253 int i = 0; 254 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 255 i++; 256 } 257 fStartOffset = i-1; 258 259 if (getCommonAncestorContainer() == null 265 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 266 collapse(true); 267 } 268 } 269 270 public void setStartAfter(Node refNode) 271 throws RangeException 272 { 273 if (fDocument.errorChecking) { 274 if (fDetach) { 275 throw new DOMException ( 276 DOMException.INVALID_STATE_ERR, 277 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 278 } 279 if ( !hasLegalRootContainer(refNode) || 280 !isLegalContainedNode(refNode)) { 281 throw new RangeExceptionImpl( 282 RangeException.INVALID_NODE_TYPE_ERR, 283 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 284 } 285 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 286 throw new DOMException ( 287 DOMException.WRONG_DOCUMENT_ERR, 288 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 289 } 290 } 291 fStartContainer = refNode.getParentNode(); 292 int i = 0; 293 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 294 i++; 295 } 296 fStartOffset = i; 297 298 if (getCommonAncestorContainer() == null 304 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 305 collapse(true); 306 } 307 } 308 309 public void setEndBefore(Node refNode) 310 throws RangeException 311 { 312 if (fDocument.errorChecking) { 313 if (fDetach) { 314 throw new DOMException ( 315 DOMException.INVALID_STATE_ERR, 316 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 317 } 318 if ( !hasLegalRootContainer(refNode) || 319 !isLegalContainedNode(refNode)) { 320 throw new RangeExceptionImpl( 321 RangeException.INVALID_NODE_TYPE_ERR, 322 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 323 } 324 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 325 throw new DOMException ( 326 DOMException.WRONG_DOCUMENT_ERR, 327 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 328 } 329 } 330 fEndContainer = refNode.getParentNode(); 331 int i = 0; 332 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 333 i++; 334 } 335 fEndOffset = i-1; 336 337 if (getCommonAncestorContainer() == null 343 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 344 collapse(false); 345 } 346 } 347 348 public void setEndAfter(Node refNode) 349 throws RangeException 350 { 351 if (fDocument.errorChecking) { 352 if( fDetach) { 353 throw new DOMException ( 354 DOMException.INVALID_STATE_ERR, 355 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 356 } 357 if ( !hasLegalRootContainer(refNode) || 358 !isLegalContainedNode(refNode)) { 359 throw new RangeExceptionImpl( 360 RangeException.INVALID_NODE_TYPE_ERR, 361 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 362 } 363 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 364 throw new DOMException ( 365 DOMException.WRONG_DOCUMENT_ERR, 366 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 367 } 368 } 369 fEndContainer = refNode.getParentNode(); 370 int i = 0; 371 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 372 i++; 373 } 374 fEndOffset = i; 375 376 if (getCommonAncestorContainer() == null 382 || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) { 383 collapse(false); 384 } 385 } 386 387 public void collapse(boolean toStart) { 388 389 if( fDetach) { 390 throw new DOMException ( 391 DOMException.INVALID_STATE_ERR, 392 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 393 } 394 395 if (toStart) { 396 fEndContainer = fStartContainer; 397 fEndOffset = fStartOffset; 398 } else { 399 fStartContainer = fEndContainer; 400 fStartOffset = fEndOffset; 401 } 402 } 403 404 public void selectNode(Node refNode) 405 throws RangeException 406 { 407 if (fDocument.errorChecking) { 408 if (fDetach) { 409 throw new DOMException ( 410 DOMException.INVALID_STATE_ERR, 411 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 412 } 413 if ( !isLegalContainer( refNode.getParentNode() ) || 414 !isLegalContainedNode( refNode ) ) { 415 throw new RangeExceptionImpl( 416 RangeException.INVALID_NODE_TYPE_ERR, 417 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 418 } 419 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 420 throw new DOMException ( 421 DOMException.WRONG_DOCUMENT_ERR, 422 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 423 } 424 } 425 Node parent = refNode.getParentNode(); 426 if (parent != null ) { 428 fStartContainer = parent; 429 fEndContainer = parent; 430 int i = 0; 431 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 432 i++; 433 } 434 fStartOffset = i-1; 435 fEndOffset = fStartOffset+1; 436 } 437 } 438 439 public void selectNodeContents(Node refNode) 440 throws RangeException 441 { 442 if (fDocument.errorChecking) { 443 if( fDetach) { 444 throw new DOMException ( 445 DOMException.INVALID_STATE_ERR, 446 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 447 } 448 if ( !isLegalContainer(refNode)) { 449 throw new RangeExceptionImpl( 450 RangeException.INVALID_NODE_TYPE_ERR, 451 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 452 } 453 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 454 throw new DOMException ( 455 DOMException.WRONG_DOCUMENT_ERR, 456 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 457 } 458 } 459 fStartContainer = refNode; 460 fEndContainer = refNode; 461 Node first = refNode.getFirstChild(); 462 fStartOffset = 0; 463 if (first == null) { 464 fEndOffset = 0; 465 } else { 466 int i = 0; 467 for (Node n = first; n!=null; n = n.getNextSibling()) { 468 i++; 469 } 470 fEndOffset = i; 471 } 472 473 } 474 475 public short compareBoundaryPoints(short how, Range sourceRange) 476 throws DOMException 477 { 478 if (fDocument.errorChecking) { 479 if( fDetach) { 480 throw new DOMException ( 481 DOMException.INVALID_STATE_ERR, 482 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 483 } 484 if ((fDocument != sourceRange.getStartContainer().getOwnerDocument() 486 && fDocument != sourceRange.getStartContainer() 487 && sourceRange.getStartContainer() != null) 488 || (fDocument != sourceRange.getEndContainer().getOwnerDocument() 489 && fDocument != sourceRange.getEndContainer() 490 && sourceRange.getStartContainer() != null)) { 491 throw new DOMException (DOMException.WRONG_DOCUMENT_ERR, 492 DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 493 } 494 } 495 496 Node endPointA; 497 Node endPointB; 498 int offsetA; 499 int offsetB; 500 501 if (how == START_TO_START) { 502 endPointA = sourceRange.getStartContainer(); 503 endPointB = fStartContainer; 504 offsetA = sourceRange.getStartOffset(); 505 offsetB = fStartOffset; 506 } else 507 if (how == START_TO_END) { 508 endPointA = sourceRange.getStartContainer(); 509 endPointB = fEndContainer; 510 offsetA = sourceRange.getStartOffset(); 511 offsetB = fEndOffset; 512 } else 513 if (how == END_TO_START) { 514 endPointA = sourceRange.getEndContainer(); 515 endPointB = fStartContainer; 516 offsetA = sourceRange.getEndOffset(); 517 offsetB = fStartOffset; 518 } else { 519 endPointA = sourceRange.getEndContainer(); 520 endPointB = fEndContainer; 521 offsetA = sourceRange.getEndOffset(); 522 offsetB = fEndOffset; 523 } 524 525 532 if (endPointA == endPointB) { 534 if (offsetA < offsetB) return 1; 535 if (offsetA == offsetB) return 0; 536 return -1; 537 } 538 for ( Node c = endPointB, p = c.getParentNode(); 541 p != null; 542 c = p, p = p.getParentNode()) 543 { 544 if (p == endPointA) { 545 int index = indexOf(c, endPointA); 546 if (offsetA <= index) return 1; 547 return -1; 548 } 549 } 550 551 for ( Node c = endPointA, p = c.getParentNode(); 554 p != null; 555 c = p, p = p.getParentNode()) 556 { 557 if (p == endPointB) { 558 int index = indexOf(c, endPointB); 559 if (index < offsetB) return 1; 560 return -1; 561 } 562 } 563 564 568 int depthDiff = 0; 569 for ( Node n = endPointA; n != null; n = n.getParentNode() ) 570 depthDiff++; 571 for ( Node n = endPointB; n != null; n = n.getParentNode() ) 572 depthDiff--; 573 while (depthDiff > 0) { 574 endPointA = endPointA.getParentNode(); 575 depthDiff--; 576 } 577 while (depthDiff < 0) { 578 endPointB = endPointB.getParentNode(); 579 depthDiff++; 580 } 581 for (Node pA = endPointA.getParentNode(), 582 pB = endPointB.getParentNode(); 583 pA != pB; 584 pA = pA.getParentNode(), pB = pB.getParentNode() ) 585 { 586 endPointA = pA; 587 endPointB = pB; 588 } 589 for ( Node n = endPointA.getNextSibling(); 590 n != null; 591 n = n.getNextSibling() ) 592 { 593 if (n == endPointB) { 594 return 1; 595 } 596 } 597 return -1; 598 } 599 600 public void deleteContents() 601 throws DOMException 602 { 603 traverseContents(DELETE_CONTENTS); 604 } 605 606 public DocumentFragment extractContents() 607 throws DOMException 608 { 609 return traverseContents(EXTRACT_CONTENTS); 610 } 611 612 public DocumentFragment cloneContents() 613 throws DOMException 614 { 615 return traverseContents(CLONE_CONTENTS); 616 } 617 618 public void insertNode(Node newNode) 619 throws DOMException , RangeException 620 { 621 if ( newNode == null ) return; 623 int type = newNode.getNodeType(); 624 625 if (fDocument.errorChecking) { 626 if (fDetach) { 627 throw new DOMException ( 628 DOMException.INVALID_STATE_ERR, 629 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 630 } 631 if ( fDocument != newNode.getOwnerDocument() ) { 632 throw new DOMException (DOMException.WRONG_DOCUMENT_ERR, 633 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 634 } 635 636 if (type == Node.ATTRIBUTE_NODE 637 || type == Node.ENTITY_NODE 638 || type == Node.NOTATION_NODE 639 || type == Node.DOCUMENT_NODE) 640 { 641 throw new RangeExceptionImpl( 642 RangeException.INVALID_NODE_TYPE_ERR, 643 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 644 } 645 } 646 Node cloneCurrent; 647 Node current; 648 int currentChildren = 0; 649 fInsertedFromRange = true; 650 651 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 653 654 Node parent = fStartContainer.getParentNode(); 655 currentChildren = parent.getChildNodes().getLength(); cloneCurrent = fStartContainer.cloneNode(false); 658 ((TextImpl)cloneCurrent).setNodeValueInternal( 659 (cloneCurrent.getNodeValue()).substring(fStartOffset)); 660 ((TextImpl)fStartContainer).setNodeValueInternal( 661 (fStartContainer.getNodeValue()).substring(0,fStartOffset)); 662 Node next = fStartContainer.getNextSibling(); 663 if (next != null) { 664 if (parent != null) { 665 parent.insertBefore(newNode, next); 666 parent.insertBefore(cloneCurrent, next); 667 } 668 } else { 669 if (parent != null) { 670 parent.appendChild(newNode); 671 parent.appendChild(cloneCurrent); 672 } 673 } 674 if ( fEndContainer == fStartContainer) { 676 fEndContainer = cloneCurrent; fEndOffset -= fStartOffset; 678 } 679 else if ( fEndContainer == parent ) { fEndOffset += (parent.getChildNodes().getLength() - currentChildren); 682 } 683 684 signalSplitData(fStartContainer, cloneCurrent, fStartOffset); 686 687 688 } else { if ( fEndContainer == fStartContainer ) currentChildren= fEndContainer.getChildNodes().getLength(); 691 692 current = fStartContainer.getFirstChild(); 693 int i = 0; 694 for(i = 0; i < fStartOffset && current != null; i++) { 695 current=current.getNextSibling(); 696 } 697 if (current != null) { 698 fStartContainer.insertBefore(newNode, current); 699 } else { 700 fStartContainer.appendChild(newNode); 701 } 702 if ( fEndContainer == fStartContainer && fEndOffset != 0 ) { fEndOffset += (fEndContainer.getChildNodes().getLength() - currentChildren); 706 } 707 } 708 fInsertedFromRange = false; 709 } 710 711 public void surroundContents(Node newParent) 712 throws DOMException , RangeException 713 { 714 if (newParent==null) return; 715 int type = newParent.getNodeType(); 716 717 if (fDocument.errorChecking) { 718 if (fDetach) { 719 throw new DOMException ( 720 DOMException.INVALID_STATE_ERR, 721 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 722 } 723 if (type == Node.ATTRIBUTE_NODE 724 || type == Node.ENTITY_NODE 725 || type == Node.NOTATION_NODE 726 || type == Node.DOCUMENT_TYPE_NODE 727 || type == Node.DOCUMENT_NODE 728 || type == Node.DOCUMENT_FRAGMENT_NODE) 729 { 730 throw new RangeExceptionImpl( 731 RangeException.INVALID_NODE_TYPE_ERR, 732 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 733 } 734 } 735 736 Node realStart = fStartContainer; 737 Node realEnd = fEndContainer; 738 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 739 realStart = fStartContainer.getParentNode(); 740 } 741 if (fEndContainer.getNodeType() == Node.TEXT_NODE) { 742 realEnd = fEndContainer.getParentNode(); 743 } 744 745 if (realStart != realEnd) { 746 throw new RangeExceptionImpl( 747 RangeException.BAD_BOUNDARYPOINTS_ERR, 748 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "BAD_BOUNDARYPOINTS_ERR", null)); 749 } 750 751 DocumentFragment frag = extractContents(); 752 insertNode(newParent); 753 newParent.appendChild(frag); 754 selectNode(newParent); 755 } 756 757 public Range cloneRange(){ 758 if( fDetach) { 759 throw new DOMException ( 760 DOMException.INVALID_STATE_ERR, 761 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 762 } 763 764 Range range = fDocument.createRange(); 765 range.setStart(fStartContainer, fStartOffset); 766 range.setEnd(fEndContainer, fEndOffset); 767 return range; 768 } 769 770 public String toString(){ 771 if( fDetach) { 772 throw new DOMException ( 773 DOMException.INVALID_STATE_ERR, 774 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 775 } 776 777 Node node = fStartContainer; 778 Node stopNode = fEndContainer; 779 StringBuffer sb = new StringBuffer (); 780 if (fStartContainer.getNodeType() == Node.TEXT_NODE 781 || fStartContainer.getNodeType() == Node.CDATA_SECTION_NODE 782 ) { 783 if (fStartContainer == fEndContainer) { 784 sb.append(fStartContainer.getNodeValue().substring(fStartOffset, fEndOffset)); 785 return sb.toString(); 786 } 787 sb.append(fStartContainer.getNodeValue().substring(fStartOffset)); 788 node=nextNode (node,true); 790 } 791 else { node=node.getFirstChild(); 793 if (fStartOffset>0) { int counter=0; 795 while (counter<fStartOffset && node!=null) { 796 node=node.getNextSibling(); 797 counter++; 798 } 799 } 800 if (node == null) { 801 node = nextNode(fStartContainer,false); 802 } 803 } 804 if ( fEndContainer.getNodeType()!= Node.TEXT_NODE && 805 fEndContainer.getNodeType()!= Node.CDATA_SECTION_NODE ){ 806 int i=fEndOffset; 807 stopNode = fEndContainer.getFirstChild(); 808 while( i>0 && stopNode!=null ){ 809 --i; 810 stopNode = stopNode.getNextSibling(); 811 } 812 if ( stopNode == null ) 813 stopNode = nextNode( fEndContainer, false ); 814 } 815 while (node != stopNode) { if (node == null) break; 817 if (node.getNodeType() == Node.TEXT_NODE 818 || node.getNodeType() == Node.CDATA_SECTION_NODE) { 819 sb.append(node.getNodeValue()); 820 } 821 822 node = nextNode(node, true); 823 } 824 825 if (fEndContainer.getNodeType() == Node.TEXT_NODE 826 || fEndContainer.getNodeType() == Node.CDATA_SECTION_NODE) { 827 sb.append(fEndContainer.getNodeValue().substring(0,fEndOffset)); 828 } 829 return sb.toString(); 830 } 831 832 public void detach() { 833 if( fDetach) { 834 throw new DOMException ( 835 DOMException.INVALID_STATE_ERR, 836 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 837 } 838 fDetach = true; 839 fDocument.removeRange(this); 840 } 841 842 846 850 void signalSplitData(Node node, Node newNode, int offset) { 851 fSplitNode = node; 852 fDocument.splitData(node, newNode, offset); 854 fSplitNode = null; 855 } 856 857 860 void receiveSplitData(Node node, Node newNode, int offset) { 861 if (node == null || newNode == null) return; 862 if (fSplitNode == node) return; 863 864 if (node == fStartContainer 865 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 866 if (fStartOffset > offset) { 867 fStartOffset = fStartOffset - offset; 868 fStartContainer = newNode; 869 } 870 } 871 if (node == fEndContainer 872 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 873 if (fEndOffset > offset) { 874 fEndOffset = fEndOffset-offset; 875 fEndContainer = newNode; 876 } 877 } 878 879 } 880 881 884 void deleteData(CharacterData node, int offset, int count) { 885 fDeleteNode = node; 886 node.deleteData( offset, count); 887 fDeleteNode = null; 888 } 889 890 891 895 void receiveDeletedText(Node node, int offset, int count) { 896 if (node == null) return; 897 if (fDeleteNode == node) return; 898 if (node == fStartContainer 899 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 900 if (fStartOffset > offset+count) { 901 fStartOffset = offset+(fStartOffset-(offset+count)); 902 } else 903 if (fStartOffset > offset) { 904 fStartOffset = offset; 905 } 906 } 907 if (node == fEndContainer 908 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 909 if (fEndOffset > offset+count) { 910 fEndOffset = offset+(fEndOffset-(offset+count)); 911 } else 912 if (fEndOffset > offset) { 913 fEndOffset = offset; 914 } 915 } 916 917 } 918 919 922 void insertData(CharacterData node, int index, String insert) { 923 fInsertNode = node; 924 node.insertData( index, insert); 925 fInsertNode = null; 926 } 927 928 929 933 void receiveInsertedText(Node node, int index, int len) { 934 if (node == null) return; 935 if (fInsertNode == node) return; 936 if (node == fStartContainer 937 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 938 if (index < fStartOffset) { 939 fStartOffset = fStartOffset+len; 940 } 941 } 942 if (node == fEndContainer 943 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 944 if (index < fEndOffset) { 945 fEndOffset = fEndOffset+len; 946 } 947 } 948 949 } 950 951 955 void receiveReplacedText(Node node) { 956 if (node == null) return; 957 if (node == fStartContainer 958 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 959 fStartOffset = 0; 960 } 961 if (node == fEndContainer 962 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 963 fEndOffset = 0; 964 } 965 966 } 967 968 972 public void insertedNodeFromDOM(Node node) { 973 if (node == null) return; 974 if (fInsertNode == node) return; 975 if (fInsertedFromRange) return; 977 Node parent = node.getParentNode(); 978 979 if (parent == fStartContainer) { 980 int index = indexOf(node, fStartContainer); 981 if (index < fStartOffset) { 982 fStartOffset++; 983 } 984 } 985 986 if (parent == fEndContainer) { 987 int index = indexOf(node, fEndContainer); 988 if (index < fEndOffset) { 989 fEndOffset++; 990 } 991 } 992 993 } 994 995 1000 1001 Node fRemoveChild = null; 1002 Node removeChild(Node parent, Node child) { 1003 fRemoveChild = child; 1004 Node n = parent.removeChild(child); 1005 fRemoveChild = null; 1006 return n; 1007 } 1008 1009 1013 void removeNode(Node node) { 1014 if (node == null) return; 1015 if (fRemoveChild == node) return; 1016 1017 Node parent = node.getParentNode(); 1018 1019 if (parent == fStartContainer) { 1020 int index = indexOf(node, fStartContainer); 1021 if (index < fStartOffset) { 1022 fStartOffset--; 1023 } 1024 } 1025 1026 if (parent == fEndContainer) { 1027 int index = indexOf(node, fEndContainer); 1028 if (index < fEndOffset) { 1029 fEndOffset--; 1030 } 1031 } 1032 if (parent != fStartContainer 1034 || parent != fEndContainer) { 1035 if (isAncestorOf(node, fStartContainer)) { 1036 fStartContainer = parent; 1037 fStartOffset = indexOf( node, parent); 1038 } 1039 if (isAncestorOf(node, fEndContainer)) { 1040 fEndContainer = parent; 1041 fEndOffset = indexOf( node, parent); 1042 } 1043 } 1044 1045 } 1046 1047 1051 static final int EXTRACT_CONTENTS = 1; 1054 static final int CLONE_CONTENTS = 2; 1055 static final int DELETE_CONTENTS = 3; 1056 1057 1087 private DocumentFragment traverseContents( int how ) 1088 throws DOMException 1089 { 1090 if (fStartContainer == null || fEndContainer == null) { 1091 return null; } 1093 1094 if( fDetach) { 1096 throw new DOMException ( 1097 DOMException.INVALID_STATE_ERR, 1098 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 1099 } 1100 1101 1108 1109 if ( fStartContainer == fEndContainer ) 1111 return traverseSameContainer( how ); 1112 1113 1114 int endContainerDepth = 0; 1118 for ( Node c = fEndContainer, p = c.getParentNode(); 1119 p != null; 1120 c = p, p = p.getParentNode()) 1121 { 1122 if (p == fStartContainer) 1123 return traverseCommonStartContainer( c, how ); 1124 ++endContainerDepth; 1125 } 1126 1127 int startContainerDepth = 0; 1130 for ( Node c = fStartContainer, p = c.getParentNode(); 1131 p != null; 1132 c = p, p = p.getParentNode()) 1133 { 1134 if (p == fEndContainer) 1135 return traverseCommonEndContainer( c, how ); 1136 ++startContainerDepth; 1137 } 1138 1139 int depthDiff = startContainerDepth - endContainerDepth; 1142 1143 Node startNode = fStartContainer; 1144 while (depthDiff > 0) { 1145 startNode = startNode.getParentNode(); 1146 depthDiff--; 1147 } 1148 1149 Node endNode = fEndContainer; 1150 while (depthDiff < 0) { 1151 endNode = endNode.getParentNode(); 1152 depthDiff++; 1153 } 1154 1155 for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode(); 1157 sp!=ep; 1158 sp = sp.getParentNode(), ep = ep.getParentNode() ) 1159 { 1160 startNode = sp; 1161 endNode = ep; 1162 } 1163 return traverseCommonAncestors( startNode, endNode, how ); 1164 } 1165 1166 1196 private DocumentFragment traverseSameContainer( int how ) 1197 { 1198 DocumentFragment frag = null; 1199 if ( how!=DELETE_CONTENTS) 1200 frag = fDocument.createDocumentFragment(); 1201 1202 if ( fStartOffset==fEndOffset ) 1204 return frag; 1205 1206 if ( fStartContainer.getNodeType()==Node.TEXT_NODE ) 1208 { 1209 String s = fStartContainer.getNodeValue(); 1211 String sub = s.substring( fStartOffset, fEndOffset ); 1212 1213 if ( how != CLONE_CONTENTS ) 1215 { 1216 ((TextImpl)fStartContainer).deleteData(fStartOffset, 1217 fEndOffset-fStartOffset) ; 1218 collapse( true ); 1220 } 1221 if ( how==DELETE_CONTENTS) 1222 return null; 1223 frag.appendChild( fDocument.createTextNode(sub) ); 1224 return frag; 1225 } 1226 1227 Node n = getSelectedNode( fStartContainer, fStartOffset ); 1229 int cnt = fEndOffset - fStartOffset; 1230 while( cnt > 0 ) 1231 { 1232 Node sibling = n.getNextSibling(); 1233 Node xferNode = traverseFullySelected( n, how ); 1234 if ( frag!=null ) 1235 frag.appendChild( xferNode ); 1236 --cnt; 1237 n = sibling; 1238 } 1239 1240 if ( how != CLONE_CONTENTS ) 1242 collapse( true ); 1243 return frag; 1244 } 1245 1246 1281 private DocumentFragment 1282 traverseCommonStartContainer( Node endAncestor, int how ) 1283 { 1284 DocumentFragment frag = null; 1285 if ( how!=DELETE_CONTENTS) 1286 frag = fDocument.createDocumentFragment(); 1287 Node n = traverseRightBoundary( endAncestor, how ); 1288 if ( frag!=null ) 1289 frag.appendChild( n ); 1290 1291 int endIdx = indexOf( endAncestor, fStartContainer ); 1292 int cnt = endIdx - fStartOffset; 1293 if ( cnt <=0 ) 1294 { 1295 if ( how != CLONE_CONTENTS ) 1298 { 1299 setEndBefore( endAncestor ); 1300 collapse( false ); 1301 } 1302 return frag; 1303 } 1304 1305 n = endAncestor.getPreviousSibling(); 1306 while( cnt > 0 ) 1307 { 1308 Node sibling = n.getPreviousSibling(); 1309 Node xferNode = traverseFullySelected( n, how ); 1310 if ( frag!=null ) 1311 frag.insertBefore( xferNode, frag.getFirstChild() ); 1312 --cnt; 1313 n = sibling; 1314 } 1315 if ( how != CLONE_CONTENTS ) 1318 { 1319 setEndBefore( endAncestor ); 1320 collapse( false ); 1321 } 1322 return frag; 1323 } 1324 1325 1360 private DocumentFragment 1361 traverseCommonEndContainer( Node startAncestor, int how ) 1362 { 1363 DocumentFragment frag = null; 1364 if ( how!=DELETE_CONTENTS) 1365 frag = fDocument.createDocumentFragment(); 1366 Node n = traverseLeftBoundary( startAncestor, how ); 1367 if ( frag!=null ) 1368 frag.appendChild( n ); 1369 int startIdx = indexOf( startAncestor, fEndContainer ); 1370 ++startIdx; 1372 int cnt = fEndOffset - startIdx; 1373 n = startAncestor.getNextSibling(); 1374 while( cnt > 0 ) 1375 { 1376 Node sibling = n.getNextSibling(); 1377 Node xferNode = traverseFullySelected( n, how ); 1378 if ( frag!=null ) 1379 frag.appendChild( xferNode ); 1380 --cnt; 1381 n = sibling; 1382 } 1383 1384 if ( how != CLONE_CONTENTS ) 1385 { 1386 setStartAfter( startAncestor ); 1387 collapse( true ); 1388 } 1389 1390 return frag; 1391 } 1392 1393 1435 private DocumentFragment 1436 traverseCommonAncestors( Node startAncestor, Node endAncestor, int how ) 1437 { 1438 DocumentFragment frag = null; 1439 if ( how!=DELETE_CONTENTS) 1440 frag = fDocument.createDocumentFragment(); 1441 1442 Node n = traverseLeftBoundary( startAncestor, how ); 1443 if ( frag!=null ) 1444 frag.appendChild( n ); 1445 1446 Node commonParent = startAncestor.getParentNode(); 1447 int startOffset = indexOf( startAncestor, commonParent ); 1448 int endOffset = indexOf( endAncestor, commonParent ); 1449 ++startOffset; 1450 1451 int cnt = endOffset - startOffset; 1452 Node sibling = startAncestor.getNextSibling(); 1453 1454 while( cnt > 0 ) 1455 { 1456 Node nextSibling = sibling.getNextSibling(); 1457 n = traverseFullySelected( sibling, how ); 1458 if ( frag!=null ) 1459 frag.appendChild( n ); 1460 sibling = nextSibling; 1461 --cnt; 1462 } 1463 1464 n = traverseRightBoundary( endAncestor, how ); 1465 if ( frag!=null ) 1466 frag.appendChild( n ); 1467 1468 if ( how != CLONE_CONTENTS ) 1469 { 1470 setStartAfter( startAncestor ); 1471 collapse( true ); 1472 } 1473 return frag; 1474 } 1475 1476 1534 private Node traverseRightBoundary( Node root, int how ) 1535 { 1536 Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); 1537 boolean isFullySelected = ( next!=fEndContainer ); 1538 1539 if ( next==root ) 1540 return traverseNode( next, isFullySelected, false, how ); 1541 1542 Node parent = next.getParentNode(); 1543 Node clonedParent = traverseNode( parent, false, false, how ); 1544 1545 while( parent!=null ) 1546 { 1547 while( next!=null ) 1548 { 1549 Node prevSibling = next.getPreviousSibling(); 1550 Node clonedChild = 1551 traverseNode( next, isFullySelected, false, how ); 1552 if ( how!=DELETE_CONTENTS ) 1553 { 1554 clonedParent.insertBefore( 1555 clonedChild, 1556 clonedParent.getFirstChild() 1557 ); 1558 } 1559 isFullySelected = true; 1560 next = prevSibling; 1561 } 1562 if ( parent==root ) 1563 return clonedParent; 1564 1565 next = parent.getPreviousSibling(); 1566 parent = parent.getParentNode(); 1567 Node clonedGrandParent = traverseNode( parent, false, false, how ); 1568 if ( how!=DELETE_CONTENTS ) 1569 clonedGrandParent.appendChild( clonedParent ); 1570 clonedParent = clonedGrandParent; 1571 1572 } 1573 1574 return null; 1576 } 1577 1578 1637 private Node traverseLeftBoundary( Node root, int how ) 1638 { 1639 Node next = getSelectedNode( getStartContainer(), getStartOffset() ); 1640 boolean isFullySelected = ( next!=getStartContainer() ); 1641 1642 if ( next==root ) 1643 return traverseNode( next, isFullySelected, true, how ); 1644 1645 Node parent = next.getParentNode(); 1646 Node clonedParent = traverseNode( parent, false, true, how ); 1647 1648 while( parent!=null ) 1649 { 1650 while( next!=null ) 1651 { 1652 Node nextSibling = next.getNextSibling(); 1653 Node clonedChild = 1654 traverseNode( next, isFullySelected, true, how ); 1655 if ( how!=DELETE_CONTENTS ) 1656 clonedParent.appendChild(clonedChild); 1657 isFullySelected = true; 1658 next = nextSibling; 1659 } 1660 if ( parent==root ) 1661 return clonedParent; 1662 1663 next = parent.getNextSibling(); 1664 parent = parent.getParentNode(); 1665 Node clonedGrandParent = traverseNode( parent, false, true, how ); 1666 if ( how!=DELETE_CONTENTS ) 1667 clonedGrandParent.appendChild( clonedParent ); 1668 clonedParent = clonedGrandParent; 1669 1670 } 1671 1672 return null; 1674 1675 } 1676 1677 1718 private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how ) 1719 { 1720 if ( isFullySelected ) 1721 return traverseFullySelected( n, how ); 1722 if ( n.getNodeType()==Node.TEXT_NODE ) 1723 return traverseTextNode( n, isLeft, how ); 1724 return traversePartiallySelected( n, how ); 1725 } 1726 1727 1754 private Node traverseFullySelected( Node n, int how ) 1755 { 1756 switch( how ) 1757 { 1758 case CLONE_CONTENTS: 1759 return n.cloneNode( true ); 1760 case EXTRACT_CONTENTS: 1761 if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE ) 1762 { 1763 throw new DOMException ( 1765 DOMException.HIERARCHY_REQUEST_ERR, 1766 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null)); 1767 } 1768 return n; 1769 case DELETE_CONTENTS: 1770 n.getParentNode().removeChild(n); 1771 return null; 1772 } 1773 return null; 1774 } 1775 1776 1803 private Node traversePartiallySelected( Node n, int how ) 1804 { 1805 switch( how ) 1806 { 1807 case DELETE_CONTENTS: 1808 return null; 1809 case CLONE_CONTENTS: 1810 case EXTRACT_CONTENTS: 1811 return n.cloneNode( false ); 1812 } 1813 return null; 1814 } 1815 1816 1849 private Node traverseTextNode( Node n, boolean isLeft, int how ) 1850 { 1851 String txtValue = n.getNodeValue(); 1852 String newNodeValue; 1853 String oldNodeValue; 1854 1855 if ( isLeft ) 1856 { 1857 int offset = getStartOffset(); 1858 newNodeValue = txtValue.substring( offset ); 1859 oldNodeValue = txtValue.substring( 0, offset ); 1860 } 1861 else 1862 { 1863 int offset = getEndOffset(); 1864 newNodeValue = txtValue.substring( 0, offset ); 1865 oldNodeValue = txtValue.substring( offset ); 1866 } 1867 1868 if ( how != CLONE_CONTENTS ) 1869 n.setNodeValue( oldNodeValue ); 1870 if ( how==DELETE_CONTENTS ) 1871 return null; 1872 Node newNode = n.cloneNode( false ); 1873 newNode.setNodeValue( newNodeValue ); 1874 return newNode; 1875 } 1876 1877 void checkIndex(Node refNode, int offset) throws DOMException 1878 { 1879 if (offset < 0) { 1880 throw new DOMException ( 1881 DOMException.INDEX_SIZE_ERR, 1882 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1883 } 1884 1885 int type = refNode.getNodeType(); 1886 1887 if (type == Node.TEXT_NODE 1890 || type == Node.CDATA_SECTION_NODE 1891 || type == Node.COMMENT_NODE 1892 || type == Node.PROCESSING_INSTRUCTION_NODE) { 1893 if (offset > refNode.getNodeValue().length()) { 1894 throw new DOMException (DOMException.INDEX_SIZE_ERR, 1895 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1896 } 1897 } 1898 else { 1899 if (offset > refNode.getChildNodes().getLength()) { 1902 throw new DOMException (DOMException.INDEX_SIZE_ERR, 1903 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1904 } 1905 } 1906 } 1907 1908 1912 private Node getRootContainer( Node node ) 1913 { 1914 if ( node==null ) 1915 return null; 1916 1917 while( node.getParentNode()!=null ) 1918 node = node.getParentNode(); 1919 return node; 1920 } 1921 1922 1926 private boolean isLegalContainer( Node node ) 1927 { 1928 if ( node==null ) 1929 return false; 1930 1931 while( node!=null ) 1932 { 1933 switch( node.getNodeType() ) 1934 { 1935 case Node.ENTITY_NODE: 1936 case Node.NOTATION_NODE: 1937 case Node.DOCUMENT_TYPE_NODE: 1938 return false; 1939 } 1940 node = node.getParentNode(); 1941 } 1942 1943 return true; 1944 } 1945 1946 1947 1954 private boolean hasLegalRootContainer( Node node ) 1955 { 1956 if ( node==null ) 1957 return false; 1958 1959 Node rootContainer = getRootContainer( node ); 1960 switch( rootContainer.getNodeType() ) 1961 { 1962 case Node.ATTRIBUTE_NODE: 1963 case Node.DOCUMENT_NODE: 1964 case Node.DOCUMENT_FRAGMENT_NODE: 1965 return true; 1966 } 1967 return false; 1968 } 1969 1970 1974 private boolean isLegalContainedNode( Node node ) 1975 { 1976 if ( node==null ) 1977 return false; 1978 switch( node.getNodeType() ) 1979 { 1980 case Node.DOCUMENT_NODE: 1981 case Node.DOCUMENT_FRAGMENT_NODE: 1982 case Node.ATTRIBUTE_NODE: 1983 case Node.ENTITY_NODE: 1984 case Node.NOTATION_NODE: 1985 return false; 1986 } 1987 return true; 1988 } 1989 1990 Node nextNode(Node node, boolean visitChildren) { 1991 1992 if (node == null) return null; 1993 1994 Node result; 1995 if (visitChildren) { 1996 result = node.getFirstChild(); 1997 if (result != null) { 1998 return result; 1999 } 2000 } 2001 2002 result = node.getNextSibling(); 2004 if (result != null) { 2005 return result; 2006 } 2007 2008 2009 Node parent = node.getParentNode(); 2011 while (parent != null 2012 && parent != fDocument 2013 ) { 2014 result = parent.getNextSibling(); 2015 if (result != null) { 2016 return result; 2017 } else { 2018 parent = parent.getParentNode(); 2019 } 2020 2021 } 2023 return null; 2025 } 2026 2027 2028 boolean isAncestorOf(Node a, Node b) { 2029 for (Node node=b; node != null; node=node.getParentNode()) { 2030 if (node == a) return true; 2031 } 2032 return false; 2033 } 2034 2035 2036 int indexOf(Node child, Node parent) { 2037 if (child.getParentNode() != parent) return -1; 2038 int i = 0; 2039 for(Node node = parent.getFirstChild(); node!= child; node=node.getNextSibling()) { 2040 i++; 2041 } 2042 return i; 2043 } 2044 2045 2061 private Node getSelectedNode( Node container, int offset ) 2062 { 2063 if ( container.getNodeType() == Node.TEXT_NODE ) 2064 return container; 2065 2066 if ( offset<0 ) 2069 return container; 2070 2071 Node child = container.getFirstChild(); 2072 while( child!=null && offset > 0 ) 2073 { 2074 --offset; 2075 child = child.getNextSibling(); 2076 } 2077 if ( child!=null ) 2078 return child; 2079 return container; 2080 } 2081 2082} 2083 | Popular Tags |