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

Side by Side Diff: Source/core/editing/CompositeEditCommand.cpp

Issue 23822003: Have EditCommand classes deal with Document references, not pointers (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/editing/CompositeEditCommand.h ('k') | Source/core/editing/CreateLinkCommand.h » ('j') | 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 * 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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 for (size_t i = 0; i < size; ++i) 151 for (size_t i = 0; i < size; ++i)
152 m_commands[i]->getNodesInCommand(nodes); 152 m_commands[i]->getNodesInCommand(nodes);
153 } 153 }
154 #endif 154 #endif
155 155
156 void applyCommand(PassRefPtr<CompositeEditCommand> command) 156 void applyCommand(PassRefPtr<CompositeEditCommand> command)
157 { 157 {
158 command->apply(); 158 command->apply();
159 } 159 }
160 160
161 CompositeEditCommand::CompositeEditCommand(Document *document) 161 CompositeEditCommand::CompositeEditCommand(Document& document)
162 : EditCommand(document) 162 : EditCommand(document)
163 { 163 {
164 } 164 }
165 165
166 CompositeEditCommand::~CompositeEditCommand() 166 CompositeEditCommand::~CompositeEditCommand()
167 { 167 {
168 ASSERT(isTopLevelCommand() || !m_composition); 168 ASSERT(isTopLevelCommand() || !m_composition);
169 } 169 }
170 170
171 void CompositeEditCommand::apply() 171 void CompositeEditCommand::apply()
(...skipping 10 matching lines...) Expand all
182 default: 182 default:
183 ASSERT_NOT_REACHED(); 183 ASSERT_NOT_REACHED();
184 return; 184 return;
185 } 185 }
186 } 186 }
187 ensureComposition(); 187 ensureComposition();
188 188
189 // Changes to the document may have been made since the last editing operati on that require a layout, as in <rdar://problem/5658603>. 189 // Changes to the document may have been made since the last editing operati on that require a layout, as in <rdar://problem/5658603>.
190 // Low level operations, like RemoveNodeCommand, don't require a layout beca use the high level operations that use them perform one 190 // Low level operations, like RemoveNodeCommand, don't require a layout beca use the high level operations that use them perform one
191 // if one is necessary (like for the creation of VisiblePositions). 191 // if one is necessary (like for the creation of VisiblePositions).
192 ASSERT(document()); 192 document().updateLayoutIgnorePendingStylesheets();
193 document()->updateLayoutIgnorePendingStylesheets();
194 193
195 Frame* frame = document()->frame(); 194 Frame* frame = document().frame();
196 ASSERT(frame); 195 ASSERT(frame);
197 { 196 {
198 EventQueueScope scope; 197 EventQueueScope scope;
199 doApply(); 198 doApply();
200 } 199 }
201 200
202 // Only need to call appliedEditing for top-level commands, 201 // Only need to call appliedEditing for top-level commands,
203 // and TypingCommands do it on their own (see TypingCommand::typingAddedToOp enCommand). 202 // and TypingCommands do it on their own (see TypingCommand::typingAddedToOp enCommand).
204 if (!isTypingCommand()) 203 if (!isTypingCommand())
205 frame->editor().appliedEditing(this); 204 frame->editor().appliedEditing(this);
206 setShouldRetainAutocorrectionIndicator(false); 205 setShouldRetainAutocorrectionIndicator(false);
207 } 206 }
208 207
209 EditCommandComposition* CompositeEditCommand::ensureComposition() 208 EditCommandComposition* CompositeEditCommand::ensureComposition()
210 { 209 {
211 CompositeEditCommand* command = this; 210 CompositeEditCommand* command = this;
212 while (command && command->parent()) 211 while (command && command->parent())
213 command = command->parent(); 212 command = command->parent();
214 if (!command->m_composition) 213 if (!command->m_composition)
215 command->m_composition = EditCommandComposition::create(document(), star tingSelection(), endingSelection(), editingAction()); 214 command->m_composition = EditCommandComposition::create(&document(), sta rtingSelection(), endingSelection(), editingAction());
216 return command->m_composition.get(); 215 return command->m_composition.get();
217 } 216 }
218 217
219 bool CompositeEditCommand::isCreateLinkCommand() const 218 bool CompositeEditCommand::isCreateLinkCommand() const
220 { 219 {
221 return false; 220 return false;
222 } 221 }
223 222
224 bool CompositeEditCommand::preservesTypingStyle() const 223 bool CompositeEditCommand::preservesTypingStyle() const
225 { 224 {
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 { 510 {
512 size_t arraySize = markerPointers.size(); 511 size_t arraySize = markerPointers.size();
513 markers.reserveCapacity(arraySize); 512 markers.reserveCapacity(arraySize);
514 for (size_t i = 0; i < arraySize; ++i) 513 for (size_t i = 0; i < arraySize; ++i)
515 markers.append(*markerPointers[i]); 514 markers.append(*markerPointers[i]);
516 } 515 }
517 516
518 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtr<Text> p rpNode, unsigned offset, unsigned count, const String& replacementText) 517 void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtr<Text> p rpNode, unsigned offset, unsigned count, const String& replacementText)
519 { 518 {
520 RefPtr<Text> node(prpNode); 519 RefPtr<Text> node(prpNode);
521 DocumentMarkerController* markerController = document()->markers(); 520 DocumentMarkerController* markerController = document().markers();
522 Vector<DocumentMarker> markers; 521 Vector<DocumentMarker> markers;
523 copyMarkers(markerController->markersInRange(Range::create(document(), node. get(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()), markers); 522 copyMarkers(markerController->markersInRange(Range::create(&document(), node .get(), offset, node.get(), offset + count).get(), DocumentMarker::AllMarkers()) , markers);
524 replaceTextInNode(node, offset, count, replacementText); 523 replaceTextInNode(node, offset, count, replacementText);
525 RefPtr<Range> newRange = Range::create(document(), node.get(), offset, node. get(), offset + replacementText.length()); 524 RefPtr<Range> newRange = Range::create(&document(), node.get(), offset, node .get(), offset + replacementText.length());
526 for (size_t i = 0; i < markers.size(); ++i) 525 for (size_t i = 0; i < markers.size(); ++i)
527 markerController->addMarker(newRange.get(), markers[i].type(), markers[i ].description()); 526 markerController->addMarker(newRange.get(), markers[i].type(), markers[i ].description());
528 } 527 }
529 528
530 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) 529 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos)
531 { 530 {
532 if (!isTabSpanTextNode(pos.anchorNode())) 531 if (!isTabSpanTextNode(pos.anchorNode()))
533 return pos; 532 return pos;
534 533
535 switch (pos.anchorType()) { 534 switch (pos.anchorType()) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 rebalanceWhitespaceAt(selection.start()); 711 rebalanceWhitespaceAt(selection.start());
713 if (selection.isRange()) 712 if (selection.isRange())
714 rebalanceWhitespaceAt(selection.end()); 713 rebalanceWhitespaceAt(selection.end());
715 } 714 }
716 715
717 void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, un signed start, unsigned end) 716 void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, un signed start, unsigned end)
718 { 717 {
719 if (!textNode || start >= end) 718 if (!textNode || start >= end)
720 return; 719 return;
721 720
722 document()->updateLayout(); 721 document().updateLayout();
723 722
724 RenderText* textRenderer = toRenderText(textNode->renderer()); 723 RenderText* textRenderer = toRenderText(textNode->renderer());
725 if (!textRenderer) 724 if (!textRenderer)
726 return; 725 return;
727 726
728 Vector<InlineTextBox*> sortedTextBoxes; 727 Vector<InlineTextBox*> sortedTextBoxes;
729 size_t sortedTextBoxesPosition = 0; 728 size_t sortedTextBoxesPosition = 0;
730 729
731 for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox()) 730 for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox())
732 sortedTextBoxes.append(textBox); 731 sortedTextBoxes.append(textBox);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 { 822 {
824 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale nt().downstream(); 823 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale nt().downstream();
825 deleteInsignificantText(pos, end); 824 deleteInsignificantText(pos, end);
826 } 825 }
827 826
828 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element > container) 827 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element > container)
829 { 828 {
830 if (!container) 829 if (!container)
831 return 0; 830 return 0;
832 831
833 document()->updateLayoutIgnorePendingStylesheets(); 832 document().updateLayoutIgnorePendingStylesheets();
834 833
835 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 424 4964. 834 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 424 4964.
836 ASSERT(container->renderer()); 835 ASSERT(container->renderer());
837 836
838 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); 837 RefPtr<Node> placeholder = createBlockPlaceholderElement(&document());
839 appendNode(placeholder, container); 838 appendNode(placeholder, container);
840 return placeholder.release(); 839 return placeholder.release();
841 } 840 }
842 841
843 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po s) 842 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po s)
844 { 843 {
845 if (pos.isNull()) 844 if (pos.isNull())
846 return 0; 845 return 0;
847 846
848 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 42 44964. 847 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 42 44964.
849 ASSERT(pos.deprecatedNode()->renderer()); 848 ASSERT(pos.deprecatedNode()->renderer());
850 849
851 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); 850 RefPtr<Node> placeholder = createBlockPlaceholderElement(&document());
852 insertNodeAt(placeholder, pos); 851 insertNodeAt(placeholder, pos);
853 return placeholder.release(); 852 return placeholder.release();
854 } 853 }
855 854
856 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont ainer) 855 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont ainer)
857 { 856 {
858 if (!container) 857 if (!container)
859 return 0; 858 return 0;
860 859
861 document()->updateLayoutIgnorePendingStylesheets(); 860 document().updateLayoutIgnorePendingStylesheets();
862 861
863 RenderObject* renderer = container->renderer(); 862 RenderObject* renderer = container->renderer();
864 if (!renderer || !renderer->isBlockFlow()) 863 if (!renderer || !renderer->isBlockFlow())
865 return 0; 864 return 0;
866 865
867 // append the placeholder to make sure it follows 866 // append the placeholder to make sure it follows
868 // any unrendered blocks 867 // any unrendered blocks
869 RenderBlock* block = toRenderBlock(renderer); 868 RenderBlock* block = toRenderBlock(renderer);
870 if (block->height() == 0 || (block->isListItem() && block->isEmpty())) 869 if (block->height() == 0 || (block->isListItem() && block->isEmpty()))
871 return appendBlockPlaceholder(container); 870 return appendBlockPlaceholder(container);
(...skipping 10 matching lines...) Expand all
882 if (p.anchorNode()->hasTagName(brTag)) { 881 if (p.anchorNode()->hasTagName(brTag)) {
883 removeNode(p.anchorNode()); 882 removeNode(p.anchorNode());
884 return; 883 return;
885 } 884 }
886 885
887 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); 886 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1);
888 } 887 }
889 888
890 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position) 889 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
891 { 890 {
892 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document()) ; 891 RefPtr<Element> paragraphElement = createDefaultParagraphElement(&document() );
893 paragraphElement->appendChild(createBreakElement(document())); 892 paragraphElement->appendChild(createBreakElement(&document()));
894 insertNodeAt(paragraphElement, position); 893 insertNodeAt(paragraphElement, position);
895 return paragraphElement.release(); 894 return paragraphElement.release();
896 } 895 }
897 896
898 // If the paragraph is not entirely within it's own block, create one and move t he paragraph into 897 // If the paragraph is not entirely within it's own block, create one and move t he paragraph into
899 // it, and return that block. Otherwise return 0. 898 // it, and return that block. Otherwise return 0.
900 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar y(const Position& pos) 899 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar y(const Position& pos)
901 { 900 {
902 if (pos.isNull()) 901 if (pos.isNull())
903 return 0; 902 return 0;
904 903
905 document()->updateLayoutIgnorePendingStylesheets(); 904 document().updateLayoutIgnorePendingStylesheets();
906 905
907 // It's strange that this function is responsible for verifying that pos has not been invalidated 906 // It's strange that this function is responsible for verifying that pos has not been invalidated
908 // by an earlier call to this function. The caller, applyBlockStyle, should do this. 907 // by an earlier call to this function. The caller, applyBlockStyle, should do this.
909 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); 908 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
910 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); 909 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos));
911 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); 910 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos);
912 VisiblePosition next = visibleParagraphEnd.next(); 911 VisiblePosition next = visibleParagraphEnd.next();
913 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; 912 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd;
914 913
915 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); 914 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream();
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 // baz 1119 // baz
1121 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th at would 1120 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th at would
1122 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br . 1121 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br .
1123 // Must recononicalize these two VisiblePositions after the pruning above. 1122 // Must recononicalize these two VisiblePositions after the pruning above.
1124 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); 1123 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1125 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); 1124 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1126 1125
1127 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv alent().deprecatedNode()) 1126 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv alent().deprecatedNode())
1128 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar agraph)) || beforeParagraph == afterParagraph)) { 1127 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar agraph)) || beforeParagraph == afterParagraph)) {
1129 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal. 1128 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal.
1130 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival ent()); 1129 insertNodeAt(createBreakElement(&document()), beforeParagraph.deepEquiva lent());
1131 } 1130 }
1132 } 1131 }
1133 1132
1134 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor) 1133 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor)
1135 { 1134 {
1136 ASSERT(isStartOfParagraph(startOfParagraphToMove)); 1135 ASSERT(isStartOfParagraph(startOfParagraphToMove));
1137 ASSERT(isEndOfParagraph(endOfParagraphToMove)); 1136 ASSERT(isEndOfParagraph(endOfParagraphToMove));
1138 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, pr eserveSelection, preserveStyle, constrainingAncestor); 1137 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, pr eserveSelection, preserveStyle, constrainingAncestor);
1139 } 1138 }
1140 1139
(...skipping 12 matching lines...) Expand all
1153 1152
1154 bool startAfterParagraph = comparePositions(visibleStart, endOfParagraph ToMove) > 0; 1153 bool startAfterParagraph = comparePositions(visibleStart, endOfParagraph ToMove) > 0;
1155 bool endBeforeParagraph = comparePositions(visibleEnd, startOfParagraphT oMove) < 0; 1154 bool endBeforeParagraph = comparePositions(visibleEnd, startOfParagraphT oMove) < 0;
1156 1155
1157 if (!startAfterParagraph && !endBeforeParagraph) { 1156 if (!startAfterParagraph && !endBeforeParagraph) {
1158 bool startInParagraph = comparePositions(visibleStart, startOfParagr aphToMove) >= 0; 1157 bool startInParagraph = comparePositions(visibleStart, startOfParagr aphToMove) >= 0;
1159 bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToM ove) <= 0; 1158 bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToM ove) <= 0;
1160 1159
1161 startIndex = 0; 1160 startIndex = 0;
1162 if (startInParagraph) { 1161 if (startInParagraph) {
1163 RefPtr<Range> startRange = Range::create(document(), startOfPara graphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquiva lent().parentAnchoredEquivalent()); 1162 RefPtr<Range> startRange = Range::create(&document(), startOfPar agraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquiv alent().parentAnchoredEquivalent());
1164 startIndex = TextIterator::rangeLength(startRange.get(), true); 1163 startIndex = TextIterator::rangeLength(startRange.get(), true);
1165 } 1164 }
1166 1165
1167 endIndex = 0; 1166 endIndex = 0;
1168 if (endInParagraph) { 1167 if (endInParagraph) {
1169 RefPtr<Range> endRange = Range::create(document(), startOfParagr aphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent ().parentAnchoredEquivalent()); 1168 RefPtr<Range> endRange = Range::create(&document(), startOfParag raphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalen t().parentAnchoredEquivalent());
1170 endIndex = TextIterator::rangeLength(endRange.get(), true); 1169 endIndex = TextIterator::rangeLength(endRange.get(), true);
1171 } 1170 }
1172 } 1171 }
1173 } 1172 }
1174 1173
1175 VisiblePosition beforeParagraph = startOfParagraphToMove.previous(CannotCros sEditingBoundary); 1174 VisiblePosition beforeParagraph = startOfParagraphToMove.previous(CannotCros sEditingBoundary);
1176 VisiblePosition afterParagraph(endOfParagraphToMove.next(CannotCrossEditingB oundary)); 1175 VisiblePosition afterParagraph(endOfParagraphToMove.next(CannotCrossEditingB oundary));
1177 1176
1178 // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move. 1177 // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
1179 // When we paste a fragment, spaces after the end and before the start are t reated as though they were rendered. 1178 // When we paste a fragment, spaces after the end and before the start are t reated as though they were rendered.
1180 Position start = startOfParagraphToMove.deepEquivalent().downstream(); 1179 Position start = startOfParagraphToMove.deepEquivalent().downstream();
1181 Position end = endOfParagraphToMove.deepEquivalent().upstream(); 1180 Position end = endOfParagraphToMove.deepEquivalent().upstream();
1182 1181
1183 // start and end can't be used directly to create a Range; they are "editing positions" 1182 // start and end can't be used directly to create a Range; they are "editing positions"
1184 Position startRangeCompliant = start.parentAnchoredEquivalent(); 1183 Position startRangeCompliant = start.parentAnchoredEquivalent();
1185 Position endRangeCompliant = end.parentAnchoredEquivalent(); 1184 Position endRangeCompliant = end.parentAnchoredEquivalent();
1186 RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecat edNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.depre catedNode(), endRangeCompliant.deprecatedEditingOffset()); 1185 RefPtr<Range> range = Range::create(&document(), startRangeCompliant.depreca tedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.depr ecatedNode(), endRangeCompliant.deprecatedEditingOffset());
1187 1186
1188 // FIXME: This is an inefficient way to preserve style on nodes in the parag raph to move. It 1187 // FIXME: This is an inefficient way to preserve style on nodes in the parag raph to move. It
1189 // shouldn't matter though, since moved paragraphs will usually be quite sma ll. 1188 // shouldn't matter though, since moved paragraphs will usually be quite sma ll.
1190 RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraph ToMove ? 1189 RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraph ToMove ?
1191 createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotA nnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : 0; 1190 createFragmentFromMarkup(&document(), createMarkup(range.get(), 0, DoNot AnnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : 0;
1192 1191
1193 // A non-empty paragraph's style is moved when we copy and move it. We don' t move 1192 // A non-empty paragraph's style is moved when we copy and move it. We don' t move
1194 // anything if we're given an empty paragraph, but an empty paragraph can ha ve style 1193 // anything if we're given an empty paragraph, but an empty paragraph can ha ve style
1195 // too, <div><b><br></b></div> for example. Save it so that we can preserve it later. 1194 // too, <div><b><br></b></div> for example. Save it so that we can preserve it later.
1196 RefPtr<EditingStyle> styleInEmptyParagraph; 1195 RefPtr<EditingStyle> styleInEmptyParagraph;
1197 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) { 1196 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) {
1198 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep Equivalent()); 1197 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep Equivalent());
1199 styleInEmptyParagraph->mergeTypingStyle(document()); 1198 styleInEmptyParagraph->mergeTypingStyle(&document());
1200 // The moved paragraph should assume the block style of the destination. 1199 // The moved paragraph should assume the block style of the destination.
1201 styleInEmptyParagraph->removeBlockProperties(); 1200 styleInEmptyParagraph->removeBlockProperties();
1202 } 1201 }
1203 1202
1204 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo ved" and call shouldInsertFragment here. 1203 // FIXME (5098931): We should add a new insert action "WebViewInsertActionMo ved" and call shouldInsertFragment here.
1205 1204
1206 setEndingSelection(VisibleSelection(start, end, DOWNSTREAM)); 1205 setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
1207 document()->frame()->editor().clearMisspellingsAndBadGrammar(endingSelection ()); 1206 document().frame()->editor().clearMisspellingsAndBadGrammar(endingSelection( ));
1208 deleteSelection(false, false, false, false); 1207 deleteSelection(false, false, false, false);
1209 1208
1210 ASSERT(destination.deepEquivalent().anchorNode()->inDocument()); 1209 ASSERT(destination.deepEquivalent().anchorNode()->inDocument());
1211 cleanupAfterDeletion(destination); 1210 cleanupAfterDeletion(destination);
1212 ASSERT(destination.deepEquivalent().anchorNode()->inDocument()); 1211 ASSERT(destination.deepEquivalent().anchorNode()->inDocument());
1213 1212
1214 // Add a br if pruning an empty block level element caused a collapse. For e xample: 1213 // Add a br if pruning an empty block level element caused a collapse. For e xample:
1215 // foo^ 1214 // foo^
1216 // <div>bar</div> 1215 // <div>bar</div>
1217 // baz 1216 // baz
1218 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That would 1217 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That would
1219 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br . 1218 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br .
1220 // Must recononicalize these two VisiblePositions after the pruning above. 1219 // Must recononicalize these two VisiblePositions after the pruning above.
1221 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); 1220 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1222 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); 1221 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1223 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be foreParagraph == afterParagraph)) { 1222 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be foreParagraph == afterParagraph)) {
1224 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal. 1223 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal.
1225 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival ent()); 1224 insertNodeAt(createBreakElement(&document()), beforeParagraph.deepEquiva lent());
1226 // Need an updateLayout here in case inserting the br has split a text n ode. 1225 // Need an updateLayout here in case inserting the br has split a text n ode.
1227 document()->updateLayoutIgnorePendingStylesheets(); 1226 document().updateLayoutIgnorePendingStylesheets();
1228 } 1227 }
1229 1228
1230 RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositio nInNode(document()->documentElement()), destination.deepEquivalent().parentAncho redEquivalent())); 1229 RefPtr<Range> startToDestinationRange(Range::create(&document(), firstPositi onInNode(document().documentElement()), destination.deepEquivalent().parentAncho redEquivalent()));
1231 destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true); 1230 destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
1232 1231
1233 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); 1232 setEndingSelection(VisibleSelection(destination, originalIsDirectional));
1234 ASSERT(endingSelection().isCaretOrRange()); 1233 ASSERT(endingSelection().isCaretOrRange());
1235 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S electReplacement | ReplaceSelectionCommand::MovingParagraph; 1234 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S electReplacement | ReplaceSelectionCommand::MovingParagraph;
1236 if (!preserveStyle) 1235 if (!preserveStyle)
1237 options |= ReplaceSelectionCommand::MatchStyle; 1236 options |= ReplaceSelectionCommand::MatchStyle;
1238 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment , options)); 1237 applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment , options));
1239 1238
1240 document()->frame()->editor().markMisspellingsAndBadGrammar(endingSelection( )); 1239 document().frame()->editor().markMisspellingsAndBadGrammar(endingSelection() );
1241 1240
1242 // If the selection is in an empty paragraph, restore styles from the old em pty paragraph to the new empty paragraph. 1241 // If the selection is in an empty paragraph, restore styles from the old em pty paragraph to the new empty paragraph.
1243 bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfPar agraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().v isibleStart()); 1242 bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfPar agraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().v isibleStart());
1244 if (styleInEmptyParagraph && selectionIsEmptyParagraph) 1243 if (styleInEmptyParagraph && selectionIsEmptyParagraph)
1245 applyStyle(styleInEmptyParagraph.get()); 1244 applyStyle(styleInEmptyParagraph.get());
1246 1245
1247 if (preserveSelection && startIndex != -1) { 1246 if (preserveSelection && startIndex != -1) {
1248 // Fragment creation (using createMarkup) incorrectly uses regular 1247 // Fragment creation (using createMarkup) incorrectly uses regular
1249 // spaces instead of nbsps for some spaces that were rendered (11475), w hich 1248 // spaces instead of nbsps for some spaces that were rendered (11475), w hich
1250 // causes spaces to be collapsed during the move operation. This result s 1249 // causes spaces to be collapsed during the move operation. This result s
1251 // in a call to rangeFromLocationAndLength with a location past the end 1250 // in a call to rangeFromLocationAndLength with a location past the end
1252 // of the document (which will return null). 1251 // of the document (which will return null).
1253 RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document( )->documentElement(), destinationIndex + startIndex, 0, true); 1252 RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document( ).documentElement(), destinationIndex + startIndex, 0, true);
1254 RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document()- >documentElement(), destinationIndex + endIndex, 0, true); 1253 RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document(). documentElement(), destinationIndex + endIndex, 0, true);
1255 if (start && end) 1254 if (start && end)
1256 setEndingSelection(VisibleSelection(start->startPosition(), end->sta rtPosition(), DOWNSTREAM, originalIsDirectional)); 1255 setEndingSelection(VisibleSelection(start->startPosition(), end->sta rtPosition(), DOWNSTREAM, originalIsDirectional));
1257 } 1256 }
1258 } 1257 }
1259 1258
1260 // FIXME: Send an appropriate shouldDeleteRange call. 1259 // FIXME: Send an appropriate shouldDeleteRange call.
1261 bool CompositeEditCommand::breakOutOfEmptyListItem() 1260 bool CompositeEditCommand::breakOutOfEmptyListItem()
1262 { 1261 {
1263 RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl eStart()); 1262 RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl eStart());
1264 if (!emptyListItem) 1263 if (!emptyListItem)
1265 return false; 1264 return false;
1266 1265
1267 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ; 1266 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ;
1268 style->mergeTypingStyle(document()); 1267 style->mergeTypingStyle(&document());
1269 1268
1270 RefPtr<ContainerNode> listNode = emptyListItem->parentNode(); 1269 RefPtr<ContainerNode> listNode = emptyListItem->parentNode();
1271 // FIXME: Can't we do something better when the immediate parent wasn't a li st node? 1270 // FIXME: Can't we do something better when the immediate parent wasn't a li st node?
1272 if (!listNode 1271 if (!listNode
1273 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) 1272 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
1274 || !listNode->rendererIsEditable() 1273 || !listNode->rendererIsEditable()
1275 || listNode == emptyListItem->rootEditableElement()) 1274 || listNode == emptyListItem->rootEditableElement())
1276 return false; 1275 return false;
1277 1276
1278 RefPtr<Element> newBlock = 0; 1277 RefPtr<Element> newBlock = 0;
1279 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { 1278 if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
1280 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth er list item 1279 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth er list item
1281 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA fterNode(listNode.get())) { 1280 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA fterNode(listNode.get())) {
1282 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item 1281 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item
1283 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section 1282 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section
1284 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph. 1283 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph.
1285 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end 1284 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end
1286 splitElement(toElement(blockEnclosingList), listNode); 1285 splitElement(toElement(blockEnclosingList), listNode);
1287 removeNodePreservingChildren(listNode->parentNode()); 1286 removeNodePreservingChildren(listNode->parentNode());
1288 newBlock = createListItemElement(document()); 1287 newBlock = createListItemElement(&document());
1289 } 1288 }
1290 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph. 1289 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph.
1291 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList-> hasTagName(ulTag)) 1290 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList-> hasTagName(ulTag)) {
1292 newBlock = createListItemElement(document()); 1291 newBlock = createListItemElement(&document());
1292 }
1293 } 1293 }
1294 if (!newBlock) 1294 if (!newBlock)
1295 newBlock = createDefaultParagraphElement(document()); 1295 newBlock = createDefaultParagraphElement(&document());
1296 1296
1297 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(e mptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling(); 1297 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(e mptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling();
1298 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(empty ListItem.get())->nextElementSibling(): emptyListItem->nextSibling(); 1298 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(empty ListItem.get())->nextElementSibling(): emptyListItem->nextSibling();
1299 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { 1299 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) {
1300 // If emptyListItem follows another list item or nested list, split the list node. 1300 // If emptyListItem follows another list item or nested list, split the list node.
1301 if (isListItem(previousListNode.get()) || isListElement(previousListNode .get())) 1301 if (isListItem(previousListNode.get()) || isListElement(previousListNode .get()))
1302 splitElement(toElement(listNode.get()), emptyListItem); 1302 splitElement(toElement(listNode.get()), emptyListItem);
1303 1303
1304 // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node. 1304 // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
1305 // Because we have splitted the element, emptyListItem is the first elem ent in the list node. 1305 // Because we have splitted the element, emptyListItem is the first elem ent in the list node.
(...skipping 30 matching lines...) Expand all
1336 return false; 1336 return false;
1337 1337
1338 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) 1338 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret))
1339 return false; 1339 return false;
1340 1340
1341 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); 1341 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
1342 // Only move forward if there's nothing before the caret, or if there's unqu oted content before it. 1342 // Only move forward if there's nothing before the caret, or if there's unqu oted content before it.
1343 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) 1343 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
1344 return false; 1344 return false;
1345 1345
1346 RefPtr<Node> br = createBreakElement(document()); 1346 RefPtr<Node> br = createBreakElement(&document());
1347 // We want to replace this quoted paragraph with an unquoted one, so insert a br 1347 // We want to replace this quoted paragraph with an unquoted one, so insert a br
1348 // to hold the caret before the highest blockquote. 1348 // to hold the caret before the highest blockquote.
1349 insertNodeBefore(br, highestBlockquote); 1349 insertNodeBefore(br, highestBlockquote);
1350 VisiblePosition atBR(positionBeforeNode(br.get())); 1350 VisiblePosition atBR(positionBeforeNode(br.get()));
1351 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc kquote>, insert 1351 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc kquote>, insert
1352 // a second one. 1352 // a second one.
1353 if (!isStartOfParagraph(atBR)) 1353 if (!isStartOfParagraph(atBR))
1354 insertNodeBefore(createBreakElement(document()), br); 1354 insertNodeBefore(createBreakElement(&document()), br);
1355 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) ); 1355 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) );
1356 1356
1357 // If this is an empty paragraph there must be a line break here. 1357 // If this is an empty paragraph there must be a line break here.
1358 if (!lineBreakExistsAtVisiblePosition(caret)) 1358 if (!lineBreakExistsAtVisiblePosition(caret))
1359 return false; 1359 return false;
1360 1360
1361 Position caretPos(caret.deepEquivalent().downstream()); 1361 Position caretPos(caret.deepEquivalent().downstream());
1362 // A line break is either a br or a preserved newline. 1362 // A line break is either a br or a preserved newline.
1363 ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedN ode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveN ewline())); 1363 ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedN ode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveN ewline()));
1364 1364
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1464 return node.release(); 1464 return node.release();
1465 } 1465 }
1466 1466
1467 PassRefPtr<Element> createBlockPlaceholderElement(Document* document) 1467 PassRefPtr<Element> createBlockPlaceholderElement(Document* document)
1468 { 1468 {
1469 RefPtr<Element> breakNode = document->createElement(brTag, false); 1469 RefPtr<Element> breakNode = document->createElement(brTag, false);
1470 return breakNode.release(); 1470 return breakNode.release();
1471 } 1471 }
1472 1472
1473 } // namespace WebCore 1473 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/editing/CompositeEditCommand.h ('k') | Source/core/editing/CreateLinkCommand.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698