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