| 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 |