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 23 matching lines...) Expand all Loading... |
34 #include "ProcessingInstruction.h" | 34 #include "ProcessingInstruction.h" |
35 #include "Text.h" | 35 #include "Text.h" |
36 #include "TextIterator.h" | 36 #include "TextIterator.h" |
37 #include "VisiblePosition.h" | 37 #include "VisiblePosition.h" |
38 #include "htmlediting.h" | 38 #include "htmlediting.h" |
39 #include "markup.h" | 39 #include "markup.h" |
40 #include "visible_units.h" | 40 #include "visible_units.h" |
41 #include <stdio.h> | 41 #include <stdio.h> |
42 #include <wtf/text/CString.h> | 42 #include <wtf/text/CString.h> |
43 #include <wtf/RefCountedLeakCounter.h> | 43 #include <wtf/RefCountedLeakCounter.h> |
| 44 #include <wtf/Vector.h> |
44 | 45 |
45 namespace WebCore { | 46 namespace WebCore { |
46 | 47 |
| 48 typedef Vector<RefPtr<Node> > NodeVector; |
| 49 |
47 using namespace std; | 50 using namespace std; |
48 | 51 |
49 #ifndef NDEBUG | 52 #ifndef NDEBUG |
50 static WTF::RefCountedLeakCounter rangeCounter("Range"); | 53 static WTF::RefCountedLeakCounter rangeCounter("Range"); |
51 #endif | 54 #endif |
52 | 55 |
53 inline Range::Range(PassRefPtr<Document> ownerDocument) | 56 inline Range::Range(PassRefPtr<Document> ownerDocument) |
54 : m_ownerDocument(ownerDocument) | 57 : m_ownerDocument(ownerDocument) |
55 , m_start(m_ownerDocument) | 58 , m_start(m_ownerDocument) |
56 , m_end(m_ownerDocument) | 59 , m_end(m_ownerDocument) |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after en
d | 591 } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after en
d |
589 comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after
end | 592 comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after
end |
590 return false; | 593 return false; |
591 } | 594 } |
592 | 595 |
593 return true; // all other cases | 596 return true; // all other cases |
594 } | 597 } |
595 | 598 |
596 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
Code& ec) | 599 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
Code& ec) |
597 { | 600 { |
598 // FIXME: To work properly with mutation events, we will have to take into a
ccount | |
599 // situations where the tree is being transformed while we work on it - ugh! | |
600 | |
601 RefPtr<DocumentFragment> fragment; | 601 RefPtr<DocumentFragment> fragment; |
602 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 602 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
603 fragment = DocumentFragment::create(m_ownerDocument.get()); | 603 fragment = DocumentFragment::create(m_ownerDocument.get()); |
604 | 604 |
605 ec = 0; | 605 ec = 0; |
606 if (collapsed(ec)) | 606 if (collapsed(ec)) |
607 return fragment.release(); | 607 return fragment.release(); |
608 if (ec) | 608 if (ec) |
609 return 0; | 609 return 0; |
610 | 610 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 c->setData(c->data().substring(m_start.offset(), m_end.offset()
- m_start.offset()), ec); | 648 c->setData(c->data().substring(m_start.offset(), m_end.offset()
- m_start.offset()), ec); |
649 fragment->appendChild(c.release(), ec); | 649 fragment->appendChild(c.release(), ec); |
650 } | 650 } |
651 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 651 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
652 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_start.container()); | 652 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_start.container()); |
653 String data(pi->data()); | 653 String data(pi->data()); |
654 data.remove(m_start.offset(), m_end.offset() - m_start.offset())
; | 654 data.remove(m_start.offset(), m_end.offset() - m_start.offset())
; |
655 pi->setData(data, ec); | 655 pi->setData(data, ec); |
656 } | 656 } |
657 } else { | 657 } else { |
658 Node* n = m_start.container()->firstChild(); | 658 RefPtr<Node> n = m_start.container()->firstChild(); |
659 int i; | 659 int i; |
660 for (i = 0; n && i < m_start.offset(); i++) // skip until start offs
et | 660 for (i = 0; n && i < m_start.offset(); i++) // skip until start offs
et |
661 n = n->nextSibling(); | 661 n = n->nextSibling(); |
662 int endOffset = m_end.offset(); | 662 int endOffset = m_end.offset(); |
663 while (n && i < endOffset) { // delete until end offset | 663 RefPtr<Node> next; |
664 Node* next = n->nextSibling(); | 664 for (; n && i < endOffset; n = next, i++) { // delete until end offs
et |
| 665 next = n->nextSibling(); |
665 if (action == EXTRACT_CONTENTS) | 666 if (action == EXTRACT_CONTENTS) |
666 fragment->appendChild(n, ec); // will remove n from its pare
nt | 667 fragment->appendChild(n, ec); // will remove n from its pare
nt |
667 else if (action == CLONE_CONTENTS) | 668 else if (action == CLONE_CONTENTS) |
668 fragment->appendChild(n->cloneNode(true), ec); | 669 fragment->appendChild(n->cloneNode(true), ec); |
669 else | 670 else |
670 toContainerNode(m_start.container())->removeChild(n, ec); | 671 toContainerNode(m_start.container())->removeChild(n.get(), e
c); |
671 n = next; | |
672 i++; | |
673 } | 672 } |
674 } | 673 } |
675 return fragment.release(); | 674 return fragment.release(); |
676 } | 675 } |
677 | 676 |
678 // Complex case: Start and end containers are different. | 677 // Complex case: Start and end containers are different. |
679 // There are three possibilities here: | 678 // There are three possibilities here: |
680 // 1. Start container == commonRoot (End container must be a descendant) | 679 // 1. Start container == commonRoot (End container must be a descendant) |
681 // 2. End container == commonRoot (Start container must be a descendant) | 680 // 2. End container == commonRoot (Start container must be a descendant) |
682 // 3. Neither is commonRoot, they are both descendants | 681 // 3. Neither is commonRoot, they are both descendants |
(...skipping 30 matching lines...) Expand all Loading... |
713 leftContents = c.release(); | 712 leftContents = c.release(); |
714 } | 713 } |
715 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 714 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
716 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_start.container()); | 715 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_start.container()); |
717 String data(pi->data()); | 716 String data(pi->data()); |
718 pi->setData(data.left(m_start.offset()), ec); | 717 pi->setData(data.left(m_start.offset()), ec); |
719 } | 718 } |
720 } else { | 719 } else { |
721 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 720 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
722 leftContents = m_start.container()->cloneNode(false); | 721 leftContents = m_start.container()->cloneNode(false); |
| 722 NodeVector nodes; |
723 Node* n = m_start.container()->firstChild(); | 723 Node* n = m_start.container()->firstChild(); |
724 for (int i = 0; n && i < m_start.offset(); i++) // skip until start
offset | 724 for (int i = 0; n; n = n->nextSibling(), i++) { |
725 n = n->nextSibling(); | 725 if (i < m_start.offset()) |
726 while (n) { // process until end | 726 continue; // Skip until start offset. |
727 Node* next = n->nextSibling(); | 727 nodes.append(n); |
| 728 } |
| 729 for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(
); it++) { |
| 730 Node* n = it->get(); |
728 if (action == EXTRACT_CONTENTS) | 731 if (action == EXTRACT_CONTENTS) |
729 leftContents->appendChild(n, ec); // will remove n from star
t container | 732 leftContents->appendChild(n, ec); // Will remove n from star
t container. |
730 else if (action == CLONE_CONTENTS) | 733 else if (action == CLONE_CONTENTS) |
731 leftContents->appendChild(n->cloneNode(true), ec); | 734 leftContents->appendChild(n->cloneNode(true), ec); |
732 else | 735 else |
733 toContainerNode(m_start.container())->removeChild(n, ec); | 736 toContainerNode(m_start.container())->removeChild(n, ec); |
734 n = next; | |
735 } | 737 } |
736 } | 738 } |
737 | 739 |
738 ContainerNode* leftParent = m_start.container()->parentNode(); | 740 NodeVector ancestorNodes; |
739 Node* n = m_start.container()->nextSibling(); | 741 for (ContainerNode* n = m_start.container()->parentNode(); n && n != com
monRoot; n = n->parentNode()) |
740 for (; leftParent != commonRoot; leftParent = leftParent->parentNode())
{ | 742 ancestorNodes.append(n); |
| 743 RefPtr<Node> n = m_start.container()->nextSibling(); |
| 744 for (NodeVector::const_iterator it = ancestorNodes.begin(); it != ancest
orNodes.end(); it++) { |
| 745 Node* leftParent = it->get(); |
741 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 746 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
742 RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); | 747 RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); |
743 leftContentsParent->appendChild(leftContents, ec); | 748 if (leftContentsParent) { // Might have been removed already dur
ing mutation event. |
744 leftContents = leftContentsParent; | 749 leftContentsParent->appendChild(leftContents, ec); |
| 750 leftContents = leftContentsParent; |
| 751 } |
745 } | 752 } |
746 | 753 |
747 Node* next; | 754 RefPtr<Node> next; |
748 for (; n; n = next) { | 755 for (; n; n = next) { |
749 next = n->nextSibling(); | 756 next = n->nextSibling(); |
750 if (action == EXTRACT_CONTENTS) | 757 if (action == EXTRACT_CONTENTS) |
751 leftContents->appendChild(n, ec); // will remove n from left
Parent | 758 leftContents->appendChild(n.get(), ec); // will remove n fro
m leftParent |
752 else if (action == CLONE_CONTENTS) | 759 else if (action == CLONE_CONTENTS) |
753 leftContents->appendChild(n->cloneNode(true), ec); | 760 leftContents->appendChild(n->cloneNode(true), ec); |
754 else | 761 else |
755 leftParent->removeChild(n, ec); | 762 leftParent->removeChild(n.get(), ec); |
756 } | 763 } |
757 n = leftParent->nextSibling(); | 764 n = leftParent->nextSibling(); |
758 } | 765 } |
759 } | 766 } |
760 | 767 |
761 RefPtr<Node> rightContents; | 768 RefPtr<Node> rightContents; |
762 if (m_end.container() != commonRoot) { | 769 if (m_end.container() != commonRoot) { |
763 // delete the right-hand side of the range, up until the last ancestor o
f | 770 // delete the right-hand side of the range, up until the last ancestor o
f |
764 // end container before commonRoot | 771 // end container before commonRoot |
765 Node::NodeType endNodeType = m_end.container()->nodeType(); | 772 Node::NodeType endNodeType = m_end.container()->nodeType(); |
(...skipping 13 matching lines...) Expand all Loading... |
779 } | 786 } |
780 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 787 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
781 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_end.container()); | 788 ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(
m_end.container()); |
782 pi->setData(pi->data().substring(m_end.offset()), ec); | 789 pi->setData(pi->data().substring(m_end.offset()), ec); |
783 } | 790 } |
784 } else { | 791 } else { |
785 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 792 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
786 rightContents = m_end.container()->cloneNode(false); | 793 rightContents = m_end.container()->cloneNode(false); |
787 Node* n = m_end.container()->firstChild(); | 794 Node* n = m_end.container()->firstChild(); |
788 if (n && m_end.offset()) { | 795 if (n && m_end.offset()) { |
789 for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.of
fset() | 796 NodeVector nodes; |
790 Node* next = n->nextSibling(); | 797 for (int i = 0; i + 1 < m_end.offset() && n; i++, n = n->nextSib
ling()) { |
791 if (!next) | 798 nodes.append(n); |
792 break; | |
793 n = next; | |
794 } | 799 } |
795 Node* prev; | 800 for (int i = nodes.size() - 1; i >= 0; i--) { |
796 for (; n; n = prev) { | 801 Node* n = nodes[i].get(); |
797 prev = n->previousSibling(); | |
798 if (action == EXTRACT_CONTENTS) | 802 if (action == EXTRACT_CONTENTS) |
799 rightContents->insertBefore(n, rightContents->firstChild
(), ec); // will remove n from its parent | 803 rightContents->insertBefore(n, rightContents->firstChild
(), ec); // will remove n from its parent |
800 else if (action == CLONE_CONTENTS) | 804 else if (action == CLONE_CONTENTS) |
801 rightContents->insertBefore(n->cloneNode(true), rightCon
tents->firstChild(), ec); | 805 rightContents->insertBefore(n->cloneNode(true), rightCon
tents->firstChild(), ec); |
802 else | 806 else |
803 toContainerNode(m_end.container())->removeChild(n, ec); | 807 toContainerNode(m_end.container())->removeChild(n, ec); |
804 } | 808 } |
805 } | 809 } |
806 } | 810 } |
807 | 811 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 return 0; | 865 return 0; |
862 m_end = m_start; | 866 m_end = m_start; |
863 } | 867 } |
864 | 868 |
865 // Now add leftContents, stuff in between, and rightContents to the fragment | 869 // Now add leftContents, stuff in between, and rightContents to the fragment |
866 // (or just delete the stuff in between) | 870 // (or just delete the stuff in between) |
867 | 871 |
868 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) | 872 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) |
869 fragment->appendChild(leftContents, ec); | 873 fragment->appendChild(leftContents, ec); |
870 | 874 |
871 Node* next; | |
872 Node* n; | |
873 if (processStart) { | 875 if (processStart) { |
874 for (n = processStart; n && n != processEnd; n = next) { | 876 NodeVector nodes; |
875 next = n->nextSibling(); | 877 for (Node* n = processStart; n && n != processEnd; n = n->nextSibling()) |
| 878 nodes.append(n); |
| 879 for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); i
t++) { |
| 880 Node* n = it->get(); |
876 if (action == EXTRACT_CONTENTS) | 881 if (action == EXTRACT_CONTENTS) |
877 fragment->appendChild(n, ec); // will remove from commonRoot | 882 fragment->appendChild(n, ec); // will remove from commonRoot |
878 else if (action == CLONE_CONTENTS) | 883 else if (action == CLONE_CONTENTS) |
879 fragment->appendChild(n->cloneNode(true), ec); | 884 fragment->appendChild(n->cloneNode(true), ec); |
880 else | 885 else |
881 commonRoot->removeChild(n, ec); | 886 commonRoot->removeChild(n, ec); |
882 } | 887 } |
883 } | 888 } |
884 | 889 |
885 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) | 890 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) |
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1979 { | 1984 { |
1980 if (range && range->boundaryPointsValid()) { | 1985 if (range && range->boundaryPointsValid()) { |
1981 WebCore::Position start = range->startPosition(); | 1986 WebCore::Position start = range->startPosition(); |
1982 WebCore::Position end = range->endPosition(); | 1987 WebCore::Position end = range->endPosition(); |
1983 start.node()->showTreeAndMark(start.node(), "S", end.node(), "E"); | 1988 start.node()->showTreeAndMark(start.node(), "S", end.node(), "E"); |
1984 fprintf(stderr, "start offset: %d, end offset: %d\n", start.deprecatedEd
itingOffset(), end.deprecatedEditingOffset()); | 1989 fprintf(stderr, "start offset: %d, end offset: %d\n", start.deprecatedEd
itingOffset(), end.deprecatedEditingOffset()); |
1985 } | 1990 } |
1986 } | 1991 } |
1987 | 1992 |
1988 #endif | 1993 #endif |
OLD | NEW |