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

Side by Side Diff: Source/core/editing/ReplaceSelectionCommand.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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 352 }
353 353
354 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node* node, N ode* newNode) 354 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node* node, N ode* newNode)
355 { 355 {
356 if (m_firstNodeInserted == node) 356 if (m_firstNodeInserted == node)
357 m_firstNodeInserted = newNode; 357 m_firstNodeInserted = newNode;
358 if (m_lastNodeInserted == node) 358 if (m_lastNodeInserted == node)
359 m_lastNodeInserted = newNode; 359 m_lastNodeInserted = newNode;
360 } 360 }
361 361
362 ReplaceSelectionCommand::ReplaceSelectionCommand(Document* document, PassRefPtr< DocumentFragment> fragment, CommandOptions options, EditAction editAction) 362 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, PassRefPtr< DocumentFragment> fragment, CommandOptions options, EditAction editAction)
363 : CompositeEditCommand(document) 363 : CompositeEditCommand(document)
364 , m_selectReplacement(options & SelectReplacement) 364 , m_selectReplacement(options & SelectReplacement)
365 , m_smartReplace(options & SmartReplace) 365 , m_smartReplace(options & SmartReplace)
366 , m_matchStyle(options & MatchStyle) 366 , m_matchStyle(options & MatchStyle)
367 , m_documentFragment(fragment) 367 , m_documentFragment(fragment)
368 , m_preventNesting(options & PreventNesting) 368 , m_preventNesting(options & PreventNesting)
369 , m_movingParagraph(options & MovingParagraph) 369 , m_movingParagraph(options & MovingParagraph)
370 , m_editAction(editAction) 370 , m_editAction(editAction)
371 , m_sanitizeFragment(options & SanitizeFragment) 371 , m_sanitizeFragment(options & SanitizeFragment)
372 , m_shouldMergeEnd(false) 372 , m_shouldMergeEnd(false)
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 removeNodeAttribute(element, attributes[i]); 495 removeNodeAttribute(element, attributes[i]);
496 } 496 }
497 } 497 }
498 498
499 ContainerNode* context = element->parentNode(); 499 ContainerNode* context = element->parentNode();
500 500
501 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region, 501 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region,
502 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. 502 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>.
503 Node* blockquoteNode = !context || isMailPasteAsQuotationNode(contex t) ? context : enclosingNodeOfType(firstPositionInNode(context), isMailBlockquot e, CanCrossEditingBoundary); 503 Node* blockquoteNode = !context || isMailPasteAsQuotationNode(contex t) ? context : enclosingNodeOfType(firstPositionInNode(context), isMailBlockquot e, CanCrossEditingBoundary);
504 if (blockquoteNode) 504 if (blockquoteNode)
505 newInlineStyle->removeStyleFromRulesAndContext(element, document ()->documentElement()); 505 newInlineStyle->removeStyleFromRulesAndContext(element, document ().documentElement());
506 506
507 newInlineStyle->removeStyleFromRulesAndContext(element, context); 507 newInlineStyle->removeStyleFromRulesAndContext(element, context);
508 } 508 }
509 509
510 if (!inlineStyle || newInlineStyle->isEmpty()) { 510 if (!inlineStyle || newInlineStyle->isEmpty()) {
511 if (isStyleSpanOrSpanWithOnlyStyleAttribute(element) || isEmptyFontT ag(element, AllowNonEmptyStyleAttribute)) { 511 if (isStyleSpanOrSpanWithOnlyStyleAttribute(element) || isEmptyFontT ag(element, AllowNonEmptyStyleAttribute)) {
512 insertedNodes.willRemoveNodePreservingChildren(element); 512 insertedNodes.willRemoveNodePreservingChildren(element);
513 removeNodePreservingChildren(element); 513 removeNodePreservingChildren(element);
514 continue; 514 continue;
515 } 515 }
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 removeNode(ancestor.release()); 657 removeNode(ancestor.release());
658 } 658 }
659 659
660 static inline bool nodeHasVisibleRenderText(Text* text) 660 static inline bool nodeHasVisibleRenderText(Text* text)
661 { 661 {
662 return text->renderer() && toRenderText(text->renderer())->renderedTextLengt h() > 0; 662 return text->renderer() && toRenderText(text->renderer())->renderedTextLengt h() > 0;
663 } 663 }
664 664
665 void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins ertedNodes) 665 void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins ertedNodes)
666 { 666 {
667 document()->updateLayoutIgnorePendingStylesheets(); 667 document().updateLayoutIgnorePendingStylesheets();
668 668
669 Node* lastLeafInserted = insertedNodes.lastLeafInserted(); 669 Node* lastLeafInserted = insertedNodes.lastLeafInserted();
670 if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRen derText(toText(lastLeafInserted)) 670 if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRen derText(toText(lastLeafInserted))
671 && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), selectTag) 671 && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), selectTag)
672 && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), scriptTag)) { 672 && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), scriptTag)) {
673 insertedNodes.willRemoveNode(lastLeafInserted); 673 insertedNodes.willRemoveNode(lastLeafInserted);
674 removeNode(lastLeafInserted); 674 removeNode(lastLeafInserted);
675 } 675 }
676 676
677 // We don't have to make sure that firstNodeInserted isn't inside a select o r script element, because 677 // We don't have to make sure that firstNodeInserted isn't inside a select o r script element, because
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 if (!wrappingStyleSpan) 766 if (!wrappingStyleSpan)
767 return; 767 return;
768 768
769 RefPtr<EditingStyle> style = EditingStyle::create(wrappingStyleSpan->inlineS tyle()); 769 RefPtr<EditingStyle> style = EditingStyle::create(wrappingStyleSpan->inlineS tyle());
770 ContainerNode* context = wrappingStyleSpan->parentNode(); 770 ContainerNode* context = wrappingStyleSpan->parentNode();
771 771
772 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo u're pasting into a quoted region, 772 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo u're pasting into a quoted region,
773 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. 773 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>.
774 Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclo singNodeOfType(firstPositionInNode(context), isMailBlockquote, CanCrossEditingBo undary); 774 Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclo singNodeOfType(firstPositionInNode(context), isMailBlockquote, CanCrossEditingBo undary);
775 if (blockquoteNode) 775 if (blockquoteNode)
776 context = document()->documentElement(); 776 context = document().documentElement();
777 777
778 // This operation requires that only editing styles to be removed from sourc eDocumentStyle. 778 // This operation requires that only editing styles to be removed from sourc eDocumentStyle.
779 style->prepareToApplyAt(firstPositionInNode(context)); 779 style->prepareToApplyAt(firstPositionInNode(context));
780 780
781 // Remove block properties in the span's style. This prevents properties tha t probably have no effect 781 // Remove block properties in the span's style. This prevents properties tha t probably have no effect
782 // currently from affecting blocks later if the style is cloned for a new bl ock element during a future 782 // currently from affecting blocks later if the style is cloned for a new bl ock element during a future
783 // editing operation. 783 // editing operation.
784 // FIXME: They *can* have an effect currently if blocks beneath the style sp an aren't individually marked 784 // FIXME: They *can* have an effect currently if blocks beneath the style sp an aren't individually marked
785 // with block styles by the editing engine used to style them. WebKit doesn 't do this, but others might. 785 // with block styles by the editing engine used to style them. WebKit doesn 't do this, but others might.
786 style->removeBlockProperties(); 786 style->removeBlockProperties();
(...skipping 24 matching lines...) Expand all
811 // include the what was the start of the selection that was pasted into, so that we preserve that paragraph's 811 // include the what was the start of the selection that was pasted into, so that we preserve that paragraph's
812 // block styles. 812 // block styles.
813 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC ontent) && !isStartOfParagraph(startOfInsertedContent)); 813 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC ontent) && !isStartOfParagraph(startOfInsertedContent));
814 814
815 VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : e ndOfInsertedContent; 815 VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : e ndOfInsertedContent;
816 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end OfInsertedContent) : endOfInsertedContent.next(); 816 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end OfInsertedContent) : endOfInsertedContent.next();
817 817
818 // Merging forward could result in deleting the destination anchor node. 818 // Merging forward could result in deleting the destination anchor node.
819 // To avoid this, we add a placeholder node before the start of the paragrap h. 819 // To avoid this, we add a placeholder node before the start of the paragrap h.
820 if (endOfParagraph(startOfParagraphToMove) == destination) { 820 if (endOfParagraph(startOfParagraphToMove) == destination) {
821 RefPtr<Node> placeholder = createBreakElement(document()); 821 RefPtr<Node> placeholder = createBreakElement(&document());
822 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().de precatedNode()); 822 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().de precatedNode());
823 destination = VisiblePosition(positionBeforeNode(placeholder.get())); 823 destination = VisiblePosition(positionBeforeNode(placeholder.get()));
824 } 824 }
825 825
826 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove) , destination); 826 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove) , destination);
827 827
828 // Merging forward will remove m_endOfInsertedContent from the document. 828 // Merging forward will remove m_endOfInsertedContent from the document.
829 if (mergeForward) { 829 if (mergeForward) {
830 if (m_startOfInsertedContent.isOrphan()) 830 if (m_startOfInsertedContent.isOrphan())
831 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui valent(); 831 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui valent();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
882 { 882 {
883 VisibleSelection selection = endingSelection(); 883 VisibleSelection selection = endingSelection();
884 ASSERT(selection.isCaretOrRange()); 884 ASSERT(selection.isCaretOrRange());
885 ASSERT(selection.start().deprecatedNode()); 885 ASSERT(selection.start().deprecatedNode());
886 if (!selection.isNonOrphanedCaretOrRange() || !selection.start().deprecatedN ode()) 886 if (!selection.isNonOrphanedCaretOrRange() || !selection.start().deprecatedN ode())
887 return; 887 return;
888 888
889 if (!selection.rootEditableElement()) 889 if (!selection.rootEditableElement())
890 return; 890 return;
891 891
892 ReplacementFragment fragment(document(), m_documentFragment.get(), selection ); 892 ReplacementFragment fragment(&document(), m_documentFragment.get(), selectio n);
893 if (performTrivialReplace(fragment)) 893 if (performTrivialReplace(fragment))
894 return; 894 return;
895 895
896 // We can skip matching the style if the selection is plain text. 896 // We can skip matching the style if the selection is plain text.
897 if ((selection.start().deprecatedNode()->renderer() && selection.start().dep recatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) 897 if ((selection.start().deprecatedNode()->renderer() && selection.start().dep recatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY)
898 && (selection.end().deprecatedNode()->renderer() && selection.end().depr ecatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY)) 898 && (selection.end().deprecatedNode()->renderer() && selection.end().depr ecatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY))
899 m_matchStyle = false; 899 m_matchStyle = false;
900 900
901 if (m_matchStyle) { 901 if (m_matchStyle) {
902 m_insertionStyle = EditingStyle::create(selection.start()); 902 m_insertionStyle = EditingStyle::create(selection.start());
903 m_insertionStyle->mergeTypingStyle(document()); 903 m_insertionStyle->mergeTypingStyle(&document());
904 } 904 }
905 905
906 VisiblePosition visibleStart = selection.visibleStart(); 906 VisiblePosition visibleStart = selection.visibleStart();
907 VisiblePosition visibleEnd = selection.visibleEnd(); 907 VisiblePosition visibleEnd = selection.visibleEnd();
908 908
909 bool selectionEndWasEndOfParagraph = isEndOfParagraph(visibleEnd); 909 bool selectionEndWasEndOfParagraph = isEndOfParagraph(visibleEnd);
910 bool selectionStartWasStartOfParagraph = isStartOfParagraph(visibleStart); 910 bool selectionStartWasStartOfParagraph = isStartOfParagraph(visibleStart);
911 911
912 Node* startBlock = enclosingBlock(visibleStart.deepEquivalent().deprecatedNo de()); 912 Node* startBlock = enclosingBlock(visibleStart.deepEquivalent().deprecatedNo de());
913 913
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 insertionPos = positionInParentAfterNode(startBlock); 1002 insertionPos = positionInParentAfterNode(startBlock);
1003 else if (isStartOfBlock(visibleInsertionPos)) 1003 else if (isStartOfBlock(visibleInsertionPos))
1004 insertionPos = positionInParentBeforeNode(startBlock); 1004 insertionPos = positionInParentBeforeNode(startBlock);
1005 } 1005 }
1006 1006
1007 // Paste at start or end of link goes outside of link. 1007 // Paste at start or end of link goes outside of link.
1008 insertionPos = positionAvoidingSpecialElementBoundary(insertionPos); 1008 insertionPos = positionAvoidingSpecialElementBoundary(insertionPos);
1009 1009
1010 // FIXME: Can this wait until after the operation has been performed? There doesn't seem to be 1010 // FIXME: Can this wait until after the operation has been performed? There doesn't seem to be
1011 // any work performed after this that queries or uses the typing style. 1011 // any work performed after this that queries or uses the typing style.
1012 if (Frame* frame = document()->frame()) 1012 if (Frame* frame = document().frame())
1013 frame->selection()->clearTypingStyle(); 1013 frame->selection()->clearTypingStyle();
1014 1014
1015 removeHeadContents(fragment); 1015 removeHeadContents(fragment);
1016 1016
1017 // We don't want the destination to end up inside nodes that weren't selecte d. To avoid that, we move the 1017 // We don't want the destination to end up inside nodes that weren't selecte d. To avoid that, we move the
1018 // position forward without changing the visible position so we're still at the same visible location, but 1018 // position forward without changing the visible position so we're still at the same visible location, but
1019 // outside of preceding tags. 1019 // outside of preceding tags.
1020 insertionPos = positionAvoidingPrecedingNodes(insertionPos); 1020 insertionPos = positionAvoidingPrecedingNodes(insertionPos);
1021 1021
1022 // Paste into run of tabs splits the tab span. 1022 // Paste into run of tabs splits the tab span.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 1108
1109 // Mutation events (bug 20161) may have already removed the inserted content 1109 // Mutation events (bug 20161) may have already removed the inserted content
1110 if (!insertedNodes.firstNodeInserted() || !insertedNodes.firstNodeInserted() ->inDocument()) 1110 if (!insertedNodes.firstNodeInserted() || !insertedNodes.firstNodeInserted() ->inDocument())
1111 return; 1111 return;
1112 1112
1113 VisiblePosition startOfInsertedContent = firstPositionInOrBeforeNode(inserte dNodes.firstNodeInserted()); 1113 VisiblePosition startOfInsertedContent = firstPositionInOrBeforeNode(inserte dNodes.firstNodeInserted());
1114 1114
1115 // We inserted before the startBlock to prevent nesting, and the content bef ore the startBlock wasn't in its own block and 1115 // We inserted before the startBlock to prevent nesting, and the content bef ore the startBlock wasn't in its own block and
1116 // didn't have a br after it, so the inserted content ended up in the same p aragraph. 1116 // didn't have a br after it, so the inserted content ended up in the same p aragraph.
1117 if (startBlock && insertionPos.deprecatedNode() == startBlock->parentNode() && (unsigned)insertionPos.deprecatedEditingOffset() < startBlock->nodeIndex() && !isStartOfParagraph(startOfInsertedContent)) 1117 if (startBlock && insertionPos.deprecatedNode() == startBlock->parentNode() && (unsigned)insertionPos.deprecatedEditingOffset() < startBlock->nodeIndex() && !isStartOfParagraph(startOfInsertedContent))
1118 insertNodeAt(createBreakElement(document()).get(), startOfInsertedConten t.deepEquivalent()); 1118 insertNodeAt(createBreakElement(&document()).get(), startOfInsertedConte nt.deepEquivalent());
1119 1119
1120 if (endBR && (plainTextFragment || shouldRemoveEndBR(endBR, originalVisPosBe foreEndBR))) { 1120 if (endBR && (plainTextFragment || shouldRemoveEndBR(endBR, originalVisPosBe foreEndBR))) {
1121 RefPtr<Node> parent = endBR->parentNode(); 1121 RefPtr<Node> parent = endBR->parentNode();
1122 insertedNodes.willRemoveNode(endBR); 1122 insertedNodes.willRemoveNode(endBR);
1123 removeNode(endBR); 1123 removeNode(endBR);
1124 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { 1124 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) {
1125 insertedNodes.willRemoveNode(nodeToRemove); 1125 insertedNodes.willRemoveNode(nodeToRemove);
1126 removeNode(nodeToRemove); 1126 removeNode(nodeToRemove);
1127 } 1127 }
1128 } 1128 }
(...skipping 14 matching lines...) Expand all
1143 m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph); 1143 m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph);
1144 1144
1145 if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasIntercha ngeNewlineAtStart(), startIsInsideMailBlockquote)) { 1145 if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasIntercha ngeNewlineAtStart(), startIsInsideMailBlockquote)) {
1146 VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedConten t(); 1146 VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedConten t();
1147 VisiblePosition destination = startOfParagraphToMove.previous(); 1147 VisiblePosition destination = startOfParagraphToMove.previous();
1148 // We need to handle the case where we need to merge the end 1148 // We need to handle the case where we need to merge the end
1149 // but our destination node is inside an inline that is the last in the block. 1149 // but our destination node is inside an inline that is the last in the block.
1150 // We insert a placeholder before the newly inserted content to avoid be ing merged into the inline. 1150 // We insert a placeholder before the newly inserted content to avoid be ing merged into the inline.
1151 Node* destinationNode = destination.deepEquivalent().deprecatedNode(); 1151 Node* destinationNode = destination.deepEquivalent().deprecatedNode();
1152 if (m_shouldMergeEnd && destinationNode != enclosingInline(destinationNo de) && enclosingInline(destinationNode)->nextSibling()) 1152 if (m_shouldMergeEnd && destinationNode != enclosingInline(destinationNo de) && enclosingInline(destinationNode)->nextSibling())
1153 insertNodeBefore(createBreakElement(document()), refNode.get()); 1153 insertNodeBefore(createBreakElement(&document()), refNode.get());
1154 1154
1155 // Merging the the first paragraph of inserted content with the content that came 1155 // Merging the the first paragraph of inserted content with the content that came
1156 // before the selection that was pasted into would also move content aft er 1156 // before the selection that was pasted into would also move content aft er
1157 // the selection that was pasted into if: only one paragraph was being p asted, 1157 // the selection that was pasted into if: only one paragraph was being p asted,
1158 // and it was not wrapped in a block, the selection that was pasted into ended 1158 // and it was not wrapped in a block, the selection that was pasted into ended
1159 // at the end of a block and the next paragraph didn't start at the star t of a block. 1159 // at the end of a block and the next paragraph didn't start at the star t of a block.
1160 // Insert a line break just after the inserted content to separate it fr om what 1160 // Insert a line break just after the inserted content to separate it fr om what
1161 // comes after and prevent that from happening. 1161 // comes after and prevent that from happening.
1162 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); 1162 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent();
1163 if (startOfParagraph(endOfInsertedContent) == startOfParagraphToMove) { 1163 if (startOfParagraph(endOfInsertedContent) == startOfParagraphToMove) {
1164 insertNodeAt(createBreakElement(document()).get(), endOfInsertedCont ent.deepEquivalent()); 1164 insertNodeAt(createBreakElement(&document()).get(), endOfInsertedCon tent.deepEquivalent());
1165 // Mutation events (bug 22634) triggered by inserting the <br> might have removed the content we're about to move 1165 // Mutation events (bug 22634) triggered by inserting the <br> might have removed the content we're about to move
1166 if (!startOfParagraphToMove.deepEquivalent().anchorNode()->inDocumen t()) 1166 if (!startOfParagraphToMove.deepEquivalent().anchorNode()->inDocumen t())
1167 return; 1167 return;
1168 } 1168 }
1169 1169
1170 // FIXME: Maintain positions for the start and end of inserted content i nstead of keeping nodes. The nodes are 1170 // FIXME: Maintain positions for the start and end of inserted content i nstead of keeping nodes. The nodes are
1171 // only ever used to create positions where inserted content starts/ends . 1171 // only ever used to create positions where inserted content starts/ends .
1172 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToM ove), destination); 1172 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToM ove), destination);
1173 m_startOfInsertedContent = endingSelection().visibleStart().deepEquivale nt().downstream(); 1173 m_startOfInsertedContent = endingSelection().visibleStart().deepEquivale nt().downstream();
1174 if (m_endOfInsertedContent.isOrphan()) 1174 if (m_endOfInsertedContent.isOrphan())
1175 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivale nt().upstream(); 1175 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivale nt().upstream();
1176 } 1176 }
1177 1177
1178 Position lastPositionToSelect; 1178 Position lastPositionToSelect;
1179 if (fragment.hasInterchangeNewlineAtEnd()) { 1179 if (fragment.hasInterchangeNewlineAtEnd()) {
1180 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); 1180 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent();
1181 VisiblePosition next = endOfInsertedContent.next(CannotCrossEditingBound ary); 1181 VisiblePosition next = endOfInsertedContent.next(CannotCrossEditingBound ary);
1182 1182
1183 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont ent) || next.isNull()) { 1183 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont ent) || next.isNull()) {
1184 if (!isStartOfParagraph(endOfInsertedContent)) { 1184 if (!isStartOfParagraph(endOfInsertedContent)) {
1185 setEndingSelection(endOfInsertedContent); 1185 setEndingSelection(endOfInsertedContent);
1186 Node* enclosingNode = enclosingBlock(endOfInsertedContent.deepEq uivalent().deprecatedNode()); 1186 Node* enclosingNode = enclosingBlock(endOfInsertedContent.deepEq uivalent().deprecatedNode());
1187 if (isListItem(enclosingNode)) { 1187 if (isListItem(enclosingNode)) {
1188 RefPtr<Node> newListItem = createListItemElement(document()) ; 1188 RefPtr<Node> newListItem = createListItemElement(&document() );
1189 insertNodeAfter(newListItem, enclosingNode); 1189 insertNodeAfter(newListItem, enclosingNode);
1190 setEndingSelection(VisiblePosition(firstPositionInNode(newLi stItem.get()))); 1190 setEndingSelection(VisiblePosition(firstPositionInNode(newLi stItem.get())));
1191 } else { 1191 } else {
1192 // Use a default paragraph element (a plain div) for the emp ty paragraph, using the last paragraph 1192 // Use a default paragraph element (a plain div) for the emp ty paragraph, using the last paragraph
1193 // block's style seems to annoy users. 1193 // block's style seems to annoy users.
1194 insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), 1194 insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
1195 isMailBlockquote, CannotCrossEditingBoundary, insertedNo des.firstNodeInserted()->parentNode())); 1195 isMailBlockquote, CannotCrossEditingBoundary, insertedNo des.firstNodeInserted()->parentNode()));
1196 } 1196 }
1197 1197
1198 // Select up to the paragraph separator that was added. 1198 // Select up to the paragraph separator that was added.
(...skipping 27 matching lines...) Expand all
1226 if (!endBR || !endBR->inDocument()) 1226 if (!endBR || !endBR->inDocument())
1227 return false; 1227 return false;
1228 1228
1229 VisiblePosition visiblePos(positionBeforeNode(endBR)); 1229 VisiblePosition visiblePos(positionBeforeNode(endBR));
1230 1230
1231 // Don't remove the br if nothing was inserted. 1231 // Don't remove the br if nothing was inserted.
1232 if (visiblePos.previous() == originalVisPosBeforeEndBR) 1232 if (visiblePos.previous() == originalVisPosBeforeEndBR)
1233 return false; 1233 return false;
1234 1234
1235 // Remove the br if it is collapsed away and so is unnecessary. 1235 // Remove the br if it is collapsed away and so is unnecessary.
1236 if (!document()->inNoQuirksMode() && isEndOfBlock(visiblePos) && !isStartOfP aragraph(visiblePos)) 1236 if (!document().inNoQuirksMode() && isEndOfBlock(visiblePos) && !isStartOfPa ragraph(visiblePos))
1237 return true; 1237 return true;
1238 1238
1239 // A br that was originally holding a line open should be displaced by inser ted content or turned into a line break. 1239 // A br that was originally holding a line open should be displaced by inser ted content or turned into a line break.
1240 // A br that was originally acting as a line break should still be acting as a line break, not as a placeholder. 1240 // A br that was originally acting as a line break should still be acting as a line break, not as a placeholder.
1241 return isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos); 1241 return isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos);
1242 } 1242 }
1243 1243
1244 bool ReplaceSelectionCommand::shouldPerformSmartReplace() const 1244 bool ReplaceSelectionCommand::shouldPerformSmartReplace() const
1245 { 1245 {
1246 if (!m_smartReplace) 1246 if (!m_smartReplace)
(...skipping 25 matching lines...) Expand all
1272 } 1272 }
1273 1273
1274 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte rAfter(), false); 1274 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte rAfter(), false);
1275 if (needsTrailingSpace && endNode) { 1275 if (needsTrailingSpace && endNode) {
1276 bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->s tyle()->collapseWhiteSpace(); 1276 bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->s tyle()->collapseWhiteSpace();
1277 if (endNode->isTextNode()) { 1277 if (endNode->isTextNode()) {
1278 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " "); 1278 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " ");
1279 if (m_endOfInsertedContent.containerNode() == endNode) 1279 if (m_endOfInsertedContent.containerNode() == endNode)
1280 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); 1280 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1);
1281 } else { 1281 } else {
1282 RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteS pace ? nonBreakingSpaceString() : " "); 1282 RefPtr<Node> node = document().createEditingTextNode(collapseWhiteSp ace ? nonBreakingSpaceString() : " ");
1283 insertNodeAfter(node, endNode); 1283 insertNodeAfter(node, endNode);
1284 updateNodesInserted(node.get()); 1284 updateNodesInserted(node.get());
1285 } 1285 }
1286 } 1286 }
1287 1287
1288 document()->updateLayout(); 1288 document().updateLayout();
1289 1289
1290 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea m(); 1290 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea m();
1291 Node* startNode = startDownstream.computeNodeAfterPosition(); 1291 Node* startNode = startDownstream.computeNodeAfterPosition();
1292 unsigned startOffset = 0; 1292 unsigned startOffset = 0;
1293 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) { 1293 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) {
1294 startNode = startDownstream.containerNode(); 1294 startNode = startDownstream.containerNode();
1295 startOffset = startDownstream.offsetInContainerNode(); 1295 startOffset = startDownstream.offsetInContainerNode();
1296 } 1296 }
1297 1297
1298 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre vious().characterAfter(), true); 1298 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre vious().characterAfter(), true);
1299 if (needsLeadingSpace && startNode) { 1299 if (needsLeadingSpace && startNode) {
1300 bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer( )->style()->collapseWhiteSpace(); 1300 bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer( )->style()->collapseWhiteSpace();
1301 if (startNode->isTextNode()) { 1301 if (startNode->isTextNode()) {
1302 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac e ? nonBreakingSpaceString() : " "); 1302 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac e ? nonBreakingSpaceString() : " ");
1303 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn sertedContent.offsetInContainerNode()) 1303 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn sertedContent.offsetInContainerNode())
1304 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); 1304 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1);
1305 } else { 1305 } else {
1306 RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteS pace ? nonBreakingSpaceString() : " "); 1306 RefPtr<Node> node = document().createEditingTextNode(collapseWhiteSp ace ? nonBreakingSpaceString() : " ");
1307 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont ent to be the node containing the leading space, 1307 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont ent to be the node containing the leading space,
1308 // but m_endOfInsertedContent is supposed to mark the end of pasted content. 1308 // but m_endOfInsertedContent is supposed to mark the end of pasted content.
1309 insertNodeBefore(node, startNode); 1309 insertNodeBefore(node, startNode);
1310 m_startOfInsertedContent = firstPositionInNode(node.get()); 1310 m_startOfInsertedContent = firstPositionInNode(node.get());
1311 } 1311 }
1312 } 1312 }
1313 } 1313 }
1314 1314
1315 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi onToSelect) 1315 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi onToSelect)
1316 { 1316 {
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); 1486 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get());
1487 1487
1488 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en d); 1488 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en d);
1489 1489
1490 setEndingSelection(selectionAfterReplace); 1490 setEndingSelection(selectionAfterReplace);
1491 1491
1492 return true; 1492 return true;
1493 } 1493 }
1494 1494
1495 } // namespace WebCore 1495 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/editing/ReplaceSelectionCommand.h ('k') | Source/core/editing/SetNodeAttributeCommand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698