OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 #include "core/editing/htmlediting.h" | 62 #include "core/editing/htmlediting.h" |
63 #include "core/editing/markup.h" | 63 #include "core/editing/markup.h" |
64 #include "core/events/ScopedEventQueue.h" | 64 #include "core/events/ScopedEventQueue.h" |
65 #include "core/frame/LocalFrame.h" | 65 #include "core/frame/LocalFrame.h" |
66 #include "core/html/HTMLElement.h" | 66 #include "core/html/HTMLElement.h" |
67 #include "core/rendering/InlineTextBox.h" | 67 #include "core/rendering/InlineTextBox.h" |
68 #include "core/rendering/RenderBlock.h" | 68 #include "core/rendering/RenderBlock.h" |
69 #include "core/rendering/RenderListItem.h" | 69 #include "core/rendering/RenderListItem.h" |
70 #include "core/rendering/RenderText.h" | 70 #include "core/rendering/RenderText.h" |
71 | 71 |
72 using namespace std; | |
73 | |
74 namespace WebCore { | 72 namespace WebCore { |
75 | 73 |
76 using namespace HTMLNames; | 74 using namespace HTMLNames; |
77 | 75 |
78 PassRefPtrWillBeRawPtr<EditCommandComposition> EditCommandComposition::create(Do
cument* document, | 76 PassRefPtrWillBeRawPtr<EditCommandComposition> EditCommandComposition::create(Do
cument* document, |
79 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) | 77 const VisibleSelection& startingSelection, const VisibleSelection& endingSel
ection, EditAction editAction) |
80 { | 78 { |
81 return adoptRefWillBeNoop(new EditCommandComposition(document, startingSelec
tion, endingSelection, editAction)); | 79 return adoptRefWillBeNoop(new EditCommandComposition(document, startingSelec
tion, endingSelection, editAction)); |
82 } | 80 } |
83 | 81 |
(...skipping 18 matching lines...) Expand all Loading... |
102 ASSERT(m_document); | 100 ASSERT(m_document); |
103 RefPtr<LocalFrame> frame = m_document->frame(); | 101 RefPtr<LocalFrame> frame = m_document->frame(); |
104 ASSERT(frame); | 102 ASSERT(frame); |
105 | 103 |
106 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. | 104 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. |
107 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one | 105 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one |
108 // if one is necessary (like for the creation of VisiblePositions). | 106 // if one is necessary (like for the creation of VisiblePositions). |
109 m_document->updateLayoutIgnorePendingStylesheets(); | 107 m_document->updateLayoutIgnorePendingStylesheets(); |
110 | 108 |
111 { | 109 { |
112 size_t size = m_commands.size(); | 110 std::size_t size = m_commands.size(); |
113 for (size_t i = size; i; --i) | 111 for (std::size_t i = size; i; --i) |
114 m_commands[i - 1]->doUnapply(); | 112 m_commands[i - 1]->doUnapply(); |
115 } | 113 } |
116 | 114 |
117 frame->editor().unappliedEditing(this); | 115 frame->editor().unappliedEditing(this); |
118 } | 116 } |
119 | 117 |
120 void EditCommandComposition::reapply() | 118 void EditCommandComposition::reapply() |
121 { | 119 { |
122 ASSERT(m_document); | 120 ASSERT(m_document); |
123 RefPtr<LocalFrame> frame = m_document->frame(); | 121 RefPtr<LocalFrame> frame = m_document->frame(); |
124 ASSERT(frame); | 122 ASSERT(frame); |
125 | 123 |
126 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. | 124 // Changes to the document may have been made since the last editing operati
on that require a layout, as in <rdar://problem/5658603>. |
127 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one | 125 // Low level operations, like RemoveNodeCommand, don't require a layout beca
use the high level operations that use them perform one |
128 // if one is necessary (like for the creation of VisiblePositions). | 126 // if one is necessary (like for the creation of VisiblePositions). |
129 m_document->updateLayoutIgnorePendingStylesheets(); | 127 m_document->updateLayoutIgnorePendingStylesheets(); |
130 | 128 |
131 { | 129 { |
132 size_t size = m_commands.size(); | 130 std::size_t size = m_commands.size(); |
133 for (size_t i = 0; i != size; ++i) | 131 for (std::size_t i = 0; i != size; ++i) |
134 m_commands[i]->doReapply(); | 132 m_commands[i]->doReapply(); |
135 } | 133 } |
136 | 134 |
137 frame->editor().reappliedEditing(this); | 135 frame->editor().reappliedEditing(this); |
138 } | 136 } |
139 | 137 |
140 void EditCommandComposition::append(SimpleEditCommand* command) | 138 void EditCommandComposition::append(SimpleEditCommand* command) |
141 { | 139 { |
142 m_commands.append(command); | 140 m_commands.append(command); |
143 } | 141 } |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 applyCommandToComposite(AppendNodeCommand::create(parent, node)); | 359 applyCommandToComposite(AppendNodeCommand::create(parent, node)); |
362 } | 360 } |
363 | 361 |
364 void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no
de, unsigned from, unsigned to) | 362 void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> no
de, unsigned from, unsigned to) |
365 { | 363 { |
366 WillBeHeapVector<RefPtrWillBeMember<Node> > children; | 364 WillBeHeapVector<RefPtrWillBeMember<Node> > children; |
367 Node* child = node->traverseToChildAt(from); | 365 Node* child = node->traverseToChildAt(from); |
368 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) | 366 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) |
369 children.append(child); | 367 children.append(child); |
370 | 368 |
371 size_t size = children.size(); | 369 std::size_t size = children.size(); |
372 for (size_t i = 0; i < size; ++i) | 370 for (std::size_t i = 0; i < size; ++i) |
373 removeNode(children[i].release()); | 371 removeNode(children[i].release()); |
374 } | 372 } |
375 | 373 |
376 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldA
ssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 374 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, ShouldA
ssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
377 { | 375 { |
378 if (!node || !node->nonShadowBoundaryParentNode()) | 376 if (!node || !node->nonShadowBoundaryParentNode()) |
379 return; | 377 return; |
380 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); | 378 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); |
381 } | 379 } |
382 | 380 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 return Position(); | 492 return Position(); |
495 | 493 |
496 RefPtrWillBeRawPtr<Text> textNode = start.containerText(); | 494 RefPtrWillBeRawPtr<Text> textNode = start.containerText(); |
497 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); | 495 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta
inerNode() - start.offsetInContainerNode(), text); |
498 | 496 |
499 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); | 497 return Position(textNode.release(), start.offsetInContainerNode() + text.len
gth()); |
500 } | 498 } |
501 | 499 |
502 static void copyMarkers(const WillBeHeapVector<DocumentMarker*>& markerPointers,
Vector<DocumentMarker>& markers) | 500 static void copyMarkers(const WillBeHeapVector<DocumentMarker*>& markerPointers,
Vector<DocumentMarker>& markers) |
503 { | 501 { |
504 size_t arraySize = markerPointers.size(); | 502 std::size_t arraySize = markerPointers.size(); |
505 markers.reserveCapacity(arraySize); | 503 markers.reserveCapacity(arraySize); |
506 for (size_t i = 0; i < arraySize; ++i) | 504 for (std::size_t i = 0; i < arraySize; ++i) |
507 markers.append(*markerPointers[i]); | 505 markers.append(*markerPointers[i]); |
508 } | 506 } |
509 | 507 |
510 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtrWillBeRa
wPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementTe
xt) | 508 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtrWillBeRa
wPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementTe
xt) |
511 { | 509 { |
512 RefPtrWillBeRawPtr<Text> node(prpNode); | 510 RefPtrWillBeRawPtr<Text> node(prpNode); |
513 DocumentMarkerController& markerController = document().markers(); | 511 DocumentMarkerController& markerController = document().markers(); |
514 Vector<DocumentMarker> markers; | 512 Vector<DocumentMarker> markers; |
515 copyMarkers(markerController.markersInRange(Range::create(document(), node.g
et(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()),
markers); | 513 copyMarkers(markerController.markersInRange(Range::create(document(), node.g
et(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()),
markers); |
516 replaceTextInNode(node, offset, count, replacementText); | 514 replaceTextInNode(node, offset, count, replacementText); |
517 RefPtrWillBeRawPtr<Range> newRange = Range::create(document(), node.get(), o
ffset, node.get(), offset + replacementText.length()); | 515 RefPtrWillBeRawPtr<Range> newRange = Range::create(document(), node.get(), o
ffset, node.get(), offset + replacementText.length()); |
518 for (size_t i = 0; i < markers.size(); ++i) | 516 for (std::size_t i = 0; i < markers.size(); ++i) |
519 markerController.addMarker(newRange.get(), markers[i].type(), markers[i]
.description()); | 517 markerController.addMarker(newRange.get(), markers[i].type(), markers[i]
.description()); |
520 } | 518 } |
521 | 519 |
522 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) | 520 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) |
523 { | 521 { |
524 if (!isTabSpanTextNode(pos.anchorNode())) | 522 if (!isTabSpanTextNode(pos.anchorNode())) |
525 return pos; | 523 return pos; |
526 | 524 |
527 switch (pos.anchorType()) { | 525 switch (pos.anchorType()) { |
528 case Position::PositionIsBeforeChildren: | 526 case Position::PositionIsBeforeChildren: |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 if (!textNode || start >= end) | 716 if (!textNode || start >= end) |
719 return; | 717 return; |
720 | 718 |
721 document().updateLayout(); | 719 document().updateLayout(); |
722 | 720 |
723 RenderText* textRenderer = toRenderText(textNode->renderer()); | 721 RenderText* textRenderer = toRenderText(textNode->renderer()); |
724 if (!textRenderer) | 722 if (!textRenderer) |
725 return; | 723 return; |
726 | 724 |
727 Vector<InlineTextBox*> sortedTextBoxes; | 725 Vector<InlineTextBox*> sortedTextBoxes; |
728 size_t sortedTextBoxesPosition = 0; | 726 std::size_t sortedTextBoxesPosition = 0; |
729 | 727 |
730 for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox
= textBox->nextTextBox()) | 728 for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox
= textBox->nextTextBox()) |
731 sortedTextBoxes.append(textBox); | 729 sortedTextBoxes.append(textBox); |
732 | 730 |
733 // If there is mixed directionality text, the boxes can be out of order, | 731 // If there is mixed directionality text, the boxes can be out of order, |
734 // (like Arabic with embedded LTR), so sort them first. | 732 // (like Arabic with embedded LTR), so sort them first. |
735 if (textRenderer->containsReversedText()) | 733 if (textRenderer->containsReversedText()) |
736 std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox:
:compareByStart); | 734 std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox:
:compareByStart); |
737 InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedT
extBoxesPosition]; | 735 InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedT
extBoxesPosition]; |
738 | 736 |
(...skipping 16 matching lines...) Expand all Loading... |
755 while (prevBox || box) { | 753 while (prevBox || box) { |
756 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; | 754 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; |
757 if (end < gapStart) | 755 if (end < gapStart) |
758 // No more chance for any intersections | 756 // No more chance for any intersections |
759 break; | 757 break; |
760 | 758 |
761 unsigned gapEnd = box ? box->start() : length; | 759 unsigned gapEnd = box ? box->start() : length; |
762 bool indicesIntersect = start <= gapEnd && end >= gapStart; | 760 bool indicesIntersect = start <= gapEnd && end >= gapStart; |
763 int gapLen = gapEnd - gapStart; | 761 int gapLen = gapEnd - gapStart; |
764 if (indicesIntersect && gapLen > 0) { | 762 if (indicesIntersect && gapLen > 0) { |
765 gapStart = max(gapStart, start); | 763 gapStart = std::max(gapStart, start); |
766 if (str.isNull()) | 764 if (str.isNull()) |
767 str = textNode->data().substring(start, end - start); | 765 str = textNode->data().substring(start, end - start); |
768 // remove text in the gap | 766 // remove text in the gap |
769 str.remove(gapStart - start - removed, gapLen); | 767 str.remove(gapStart - start - removed, gapLen); |
770 removed += gapLen; | 768 removed += gapLen; |
771 } | 769 } |
772 | 770 |
773 prevBox = box; | 771 prevBox = box; |
774 if (box) { | 772 if (box) { |
775 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) | 773 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) |
(...skipping 26 matching lines...) Expand all Loading... |
802 return; | 800 return; |
803 | 801 |
804 WillBeHeapVector<RefPtrWillBeMember<Text> > nodes; | 802 WillBeHeapVector<RefPtrWillBeMember<Text> > nodes; |
805 for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(*
node)) { | 803 for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(*
node)) { |
806 if (node->isTextNode()) | 804 if (node->isTextNode()) |
807 nodes.append(toText(node)); | 805 nodes.append(toText(node)); |
808 if (node == end.deprecatedNode()) | 806 if (node == end.deprecatedNode()) |
809 break; | 807 break; |
810 } | 808 } |
811 | 809 |
812 for (size_t i = 0; i < nodes.size(); ++i) { | 810 for (std::size_t i = 0; i < nodes.size(); ++i) { |
813 Text* textNode = nodes[i].get(); | 811 Text* textNode = nodes[i].get(); |
814 int startOffset = textNode == start.deprecatedNode() ? start.deprecatedE
ditingOffset() : 0; | 812 int startOffset = textNode == start.deprecatedNode() ? start.deprecatedE
ditingOffset() : 0; |
815 int endOffset = textNode == end.deprecatedNode() ? end.deprecatedEditing
Offset() : static_cast<int>(textNode->length()); | 813 int endOffset = textNode == end.deprecatedNode() ? end.deprecatedEditing
Offset() : static_cast<int>(textNode->length()); |
816 deleteInsignificantText(textNode, startOffset, endOffset); | 814 deleteInsignificantText(textNode, startOffset, endOffset); |
817 } | 815 } |
818 } | 816 } |
819 | 817 |
820 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 818 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
821 { | 819 { |
822 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); | 820 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 | 997 |
1000 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { | 998 if (start.anchorNode() != outerNode && lastNode->isElementNode() && start.an
chorNode()->isDescendantOf(outerNode.get())) { |
1001 WillBeHeapVector<RefPtrWillBeMember<Node> > ancestors; | 999 WillBeHeapVector<RefPtrWillBeMember<Node> > ancestors; |
1002 | 1000 |
1003 // Insert each node from innerNode to outerNode (excluded) in a list. | 1001 // Insert each node from innerNode to outerNode (excluded) in a list. |
1004 for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->paren
tNode()) | 1002 for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->paren
tNode()) |
1005 ancestors.append(n); | 1003 ancestors.append(n); |
1006 | 1004 |
1007 // Clone every node between start.deprecatedNode() and outerBlock. | 1005 // Clone every node between start.deprecatedNode() and outerBlock. |
1008 | 1006 |
1009 for (size_t i = ancestors.size(); i != 0; --i) { | 1007 for (std::size_t i = ancestors.size(); i != 0; --i) { |
1010 Node* item = ancestors[i - 1].get(); | 1008 Node* item = ancestors[i - 1].get(); |
1011 RefPtrWillBeRawPtr<Node> child = item->cloneNode(isRenderedTableElem
ent(item)); | 1009 RefPtrWillBeRawPtr<Node> child = item->cloneNode(isRenderedTableElem
ent(item)); |
1012 appendNode(child, toElement(lastNode)); | 1010 appendNode(child, toElement(lastNode)); |
1013 lastNode = child.release(); | 1011 lastNode = child.release(); |
1014 } | 1012 } |
1015 } | 1013 } |
1016 | 1014 |
1017 // Scripts specified in javascript protocol may remove |outerNode| | 1015 // Scripts specified in javascript protocol may remove |outerNode| |
1018 // during insertion, e.g. <iframe src="javascript:..."> | 1016 // during insertion, e.g. <iframe src="javascript:..."> |
1019 if (!outerNode->inDocument()) | 1017 if (!outerNode->inDocument()) |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1497 } | 1495 } |
1498 | 1496 |
1499 void CompositeEditCommand::trace(Visitor* visitor) | 1497 void CompositeEditCommand::trace(Visitor* visitor) |
1500 { | 1498 { |
1501 visitor->trace(m_commands); | 1499 visitor->trace(m_commands); |
1502 visitor->trace(m_composition); | 1500 visitor->trace(m_composition); |
1503 EditCommand::trace(visitor); | 1501 EditCommand::trace(visitor); |
1504 } | 1502 } |
1505 | 1503 |
1506 } // namespace WebCore | 1504 } // namespace WebCore |
OLD | NEW |