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