| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) |
| 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) |
| 5 * (C) 2001 Peter Kelly (pmk@post.com) | 5 * (C) 2001 Peter Kelly (pmk@post.com) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 while (node->parentNode() != commonRoot) | 621 while (node->parentNode() != commonRoot) |
| 622 node = node->parentNode(); | 622 node = node->parentNode(); |
| 623 | 623 |
| 624 return node; | 624 return node; |
| 625 } | 625 } |
| 626 | 626 |
| 627 static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offs
et, Node* commonRoot) | 627 static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offs
et, Node* commonRoot) |
| 628 { | 628 { |
| 629 ASSERT(container); | 629 ASSERT(container); |
| 630 ASSERT(commonRoot); | 630 ASSERT(commonRoot); |
| 631 ASSERT(commonRoot->contains(container)); | 631 |
| 632 if (!commonRoot->contains(container)) |
| 633 return 0; |
| 632 | 634 |
| 633 if (container == commonRoot) { | 635 if (container == commonRoot) { |
| 634 container = container->firstChild(); | 636 container = container->firstChild(); |
| 635 for (unsigned i = 0; container && i < offset; i++) | 637 for (unsigned i = 0; container && i < offset; i++) |
| 636 container = container->nextSibling(); | 638 container = container->nextSibling(); |
| 637 } else { | 639 } else { |
| 638 while (container->parentNode() != commonRoot) | 640 while (container->parentNode() != commonRoot) |
| 639 container = container->parentNode(); | 641 container = container->parentNode(); |
| 640 } | 642 } |
| 641 | 643 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 RefPtr<DocumentFragment> fragment; | 677 RefPtr<DocumentFragment> fragment; |
| 676 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 678 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
| 677 fragment = DocumentFragment::create(m_ownerDocument.get()); | 679 fragment = DocumentFragment::create(m_ownerDocument.get()); |
| 678 | 680 |
| 679 ec = 0; | 681 ec = 0; |
| 680 if (collapsed(ec)) | 682 if (collapsed(ec)) |
| 681 return fragment.release(); | 683 return fragment.release(); |
| 682 if (ec) | 684 if (ec) |
| 683 return 0; | 685 return 0; |
| 684 | 686 |
| 685 Node* commonRoot = commonAncestorContainer(ec); | 687 RefPtr<Node> commonRoot = commonAncestorContainer(ec); |
| 686 if (ec) | 688 if (ec) |
| 687 return 0; | 689 return 0; |
| 688 ASSERT(commonRoot); | 690 ASSERT(commonRoot); |
| 689 | 691 |
| 690 if (m_start.container() == m_end.container()) { | 692 if (m_start.container() == m_end.container()) { |
| 691 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s
tart.offset(), m_end.offset(), ec); | 693 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s
tart.offset(), m_end.offset(), ec); |
| 692 return fragment; | 694 return fragment; |
| 693 } | 695 } |
| 694 | 696 |
| 695 // what is the highest node that partially selects the start / end of the ra
nge? | 697 // what is the highest node that partially selects the start / end of the ra
nge? |
| 696 Node* partialStart = highestAncestorUnderCommonRoot(m_start.container(), com
monRoot); | 698 RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(m_start.container
(), commonRoot.get()); |
| 697 Node* partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonR
oot); | 699 RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(m_end.container(),
commonRoot.get()); |
| 698 | 700 |
| 699 // Start and end containers are different. | 701 // Start and end containers are different. |
| 700 // There are three possibilities here: | 702 // There are three possibilities here: |
| 701 // 1. Start container == commonRoot (End container must be a descendant) | 703 // 1. Start container == commonRoot (End container must be a descendant) |
| 702 // 2. End container == commonRoot (Start container must be a descendant) | 704 // 2. End container == commonRoot (Start container must be a descendant) |
| 703 // 3. Neither is commonRoot, they are both descendants | 705 // 3. Neither is commonRoot, they are both descendants |
| 704 // | 706 // |
| 705 // In case 3, we grab everything after the start (up until a direct child | 707 // In case 3, we grab everything after the start (up until a direct child |
| 706 // of commonRoot) into leftContents, and everything before the end (up until | 708 // of commonRoot) into leftContents, and everything before the end (up until |
| 707 // a direct child of commonRoot) into rightContents. Then we process all | 709 // a direct child of commonRoot) into rightContents. Then we process all |
| 708 // commonRoot children between leftContents and rightContents | 710 // commonRoot children between leftContents and rightContents |
| 709 // | 711 // |
| 710 // In case 1 or 2, we skip either processing of leftContents or rightContent
s, | 712 // In case 1 or 2, we skip either processing of leftContents or rightContent
s, |
| 711 // in which case the last lot of nodes either goes from the first or last | 713 // in which case the last lot of nodes either goes from the first or last |
| 712 // child of commonRoot. | 714 // child of commonRoot. |
| 713 // | 715 // |
| 714 // These are deleted, cloned, or extracted (i.e. both) depending on action. | 716 // These are deleted, cloned, or extracted (i.e. both) depending on action. |
| 715 | 717 |
| 718 // Note that we are verifying that our common root hierarchy is still intact |
| 719 // after any DOM mutation event, at various stages below. See webkit bug 603
50. |
| 720 |
| 716 RefPtr<Node> leftContents; | 721 RefPtr<Node> leftContents; |
| 717 if (m_start.container() != commonRoot) { | 722 if (m_start.container() != commonRoot && commonRoot->contains(m_start.contai
ner())) { |
| 718 leftContents = processContentsBetweenOffsets(action, 0, m_start.containe
r(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec); | 723 leftContents = processContentsBetweenOffsets(action, 0, m_start.containe
r(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec); |
| 719 leftContents = processAncestorsAndTheirSiblings(action, m_start.containe
r(), ProcessContentsForward, leftContents, commonRoot, ec); | 724 leftContents = processAncestorsAndTheirSiblings(action, m_start.containe
r(), ProcessContentsForward, leftContents, commonRoot.get(), ec); |
| 720 } | 725 } |
| 721 | 726 |
| 722 RefPtr<Node> rightContents; | 727 RefPtr<Node> rightContents; |
| 723 if (m_end.container() != commonRoot) { | 728 if (m_end.container() != commonRoot && commonRoot->contains(m_end.container(
))) { |
| 724 rightContents = processContentsBetweenOffsets(action, 0, m_end.container
(), 0, m_end.offset(), ec); | 729 rightContents = processContentsBetweenOffsets(action, 0, m_end.container
(), 0, m_end.offset(), ec); |
| 725 rightContents = processAncestorsAndTheirSiblings(action, m_end.container
(), ProcessContentsBackward, rightContents, commonRoot, ec); | 730 rightContents = processAncestorsAndTheirSiblings(action, m_end.container
(), ProcessContentsBackward, rightContents, commonRoot.get(), ec); |
| 726 } | 731 } |
| 727 | 732 |
| 728 // delete all children of commonRoot between the start and end container | 733 // delete all children of commonRoot between the start and end container |
| 729 Node* processStart = childOfCommonRootBeforeOffset(m_start.container(), m_st
art.offset(), commonRoot); | 734 RefPtr<Node> processStart = childOfCommonRootBeforeOffset(m_start.container(
), m_start.offset(), commonRoot.get()); |
| 730 if (m_start.container() != commonRoot) // processStart contains nodes before
m_start. | 735 if (processStart && m_start.container() != commonRoot) // processStart conta
ins nodes before m_start. |
| 731 processStart = processStart->nextSibling(); | 736 processStart = processStart->nextSibling(); |
| 732 Node* processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.of
fset(), commonRoot); | 737 RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(m_end.container(), m
_end.offset(), commonRoot.get()); |
| 733 | 738 |
| 734 // Collapse the range, making sure that the result is not within a node that
was partially selected. | 739 // Collapse the range, making sure that the result is not within a node that
was partially selected. |
| 735 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 740 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
| 736 if (partialStart) | 741 if (partialStart && commonRoot->contains(partialStart.get())) |
| 737 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
ec); | 742 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
ec); |
| 738 else if (partialEnd) | 743 else if (partialEnd && commonRoot->contains(partialEnd.get())) |
| 739 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec); | 744 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec); |
| 740 if (ec) | 745 if (ec) |
| 741 return 0; | 746 return 0; |
| 742 m_end = m_start; | 747 m_end = m_start; |
| 743 } | 748 } |
| 744 | 749 |
| 745 // Now add leftContents, stuff in between, and rightContents to the fragment | 750 // Now add leftContents, stuff in between, and rightContents to the fragment |
| 746 // (or just delete the stuff in between) | 751 // (or just delete the stuff in between) |
| 747 | 752 |
| 748 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) | 753 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) |
| 749 fragment->appendChild(leftContents, ec); | 754 fragment->appendChild(leftContents, ec); |
| 750 | 755 |
| 751 if (processStart) { | 756 if (processStart) { |
| 752 NodeVector nodes; | 757 NodeVector nodes; |
| 753 for (Node* n = processStart; n && n != processEnd; n = n->nextSibling()) | 758 for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibl
ing()) |
| 754 nodes.append(n); | 759 nodes.append(n); |
| 755 processNodes(action, nodes, commonRoot, fragment, ec); | 760 processNodes(action, nodes, commonRoot, fragment, ec); |
| 756 } | 761 } |
| 757 | 762 |
| 758 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) | 763 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) |
| 759 fragment->appendChild(rightContents, ec); | 764 fragment->appendChild(rightContents, ec); |
| 760 | 765 |
| 761 return fragment.release(); | 766 return fragment.release(); |
| 762 } | 767 } |
| 763 | 768 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 Vector<RefPtr<Node> > nodes; | 839 Vector<RefPtr<Node> > nodes; |
| 835 for (unsigned i = startOffset; n && i; i--) | 840 for (unsigned i = startOffset; n && i; i--) |
| 836 n = n->nextSibling(); | 841 n = n->nextSibling(); |
| 837 for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibli
ng()) | 842 for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibli
ng()) |
| 838 nodes.append(n); | 843 nodes.append(n); |
| 839 | 844 |
| 840 processNodes(action, nodes, container, result, ec); | 845 processNodes(action, nodes, container, result, ec); |
| 841 break; | 846 break; |
| 842 } | 847 } |
| 843 | 848 |
| 844 return result; | 849 return result.release(); |
| 845 } | 850 } |
| 846 | 851 |
| 847 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRe
fPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec) | 852 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRe
fPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec) |
| 848 { | 853 { |
| 849 for (unsigned i = 0; i < nodes.size(); i++) { | 854 for (unsigned i = 0; i < nodes.size(); i++) { |
| 850 switch (action) { | 855 switch (action) { |
| 851 case DELETE_CONTENTS: | 856 case DELETE_CONTENTS: |
| 852 oldContainer->removeChild(nodes[i].get(), ec); | 857 oldContainer->removeChild(nodes[i].get(), ec); |
| 853 break; | 858 break; |
| 854 case EXTRACT_CONTENTS: | 859 case EXTRACT_CONTENTS: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 if (direction == ProcessContentsForward) | 904 if (direction == ProcessContentsForward) |
| 900 clonedContainer->appendChild(child->cloneNode(true), ec); | 905 clonedContainer->appendChild(child->cloneNode(true), ec); |
| 901 else | 906 else |
| 902 clonedContainer->insertBefore(child->cloneNode(true), cloned
Container->firstChild(), ec); | 907 clonedContainer->insertBefore(child->cloneNode(true), cloned
Container->firstChild(), ec); |
| 903 break; | 908 break; |
| 904 } | 909 } |
| 905 } | 910 } |
| 906 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); | 911 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); |
| 907 } | 912 } |
| 908 | 913 |
| 909 return clonedContainer; | 914 return clonedContainer.release(); |
| 910 } | 915 } |
| 911 | 916 |
| 912 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec) | 917 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec) |
| 913 { | 918 { |
| 914 checkDeleteExtract(ec); | 919 checkDeleteExtract(ec); |
| 915 if (ec) | 920 if (ec) |
| 916 return 0; | 921 return 0; |
| 917 | 922 |
| 918 return processContents(EXTRACT_CONTENTS, ec); | 923 return processContents(EXTRACT_CONTENTS, ec); |
| 919 } | 924 } |
| (...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 | 2016 |
| 2012 void showTree(const WebCore::Range* range) | 2017 void showTree(const WebCore::Range* range) |
| 2013 { | 2018 { |
| 2014 if (range && range->boundaryPointsValid()) { | 2019 if (range && range->boundaryPointsValid()) { |
| 2015 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); | 2020 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); |
| 2016 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); | 2021 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); |
| 2017 } | 2022 } |
| 2018 } | 2023 } |
| 2019 | 2024 |
| 2020 #endif | 2025 #endif |
| OLD | NEW |