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 |