Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: Source/WebCore/dom/Range.cpp

Issue 7344019: Merge 90130 (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/782/
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « LayoutTests/fast/dom/Range/range-extractContents.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « LayoutTests/fast/dom/Range/range-extractContents.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698