| OLD | NEW |
| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 pos = nextPosition) { | 147 pos = nextPosition) { |
| 148 if (lineBreakExistsAtPosition(pos)) | 148 if (lineBreakExistsAtPosition(pos)) |
| 149 break; | 149 break; |
| 150 | 150 |
| 151 if (pos.computeContainerNode()->nonShadowBoundaryParentNode()) | 151 if (pos.computeContainerNode()->nonShadowBoundaryParentNode()) |
| 152 nextPosition = Position::inParentAfterNode(*pos.computeContainerNode()); | 152 nextPosition = Position::inParentAfterNode(*pos.computeContainerNode()); |
| 153 | 153 |
| 154 if (nextPosition == pos || | 154 if (nextPosition == pos || |
| 155 enclosingBlock(nextPosition.computeContainerNode()) != | 155 enclosingBlock(nextPosition.computeContainerNode()) != |
| 156 enclosingBlockElement || | 156 enclosingBlockElement || |
| 157 createVisiblePositionDeprecated(pos).deepEquivalent() != | 157 createVisiblePosition(pos).deepEquivalent() != |
| 158 createVisiblePositionDeprecated(nextPosition).deepEquivalent()) | 158 createVisiblePosition(nextPosition).deepEquivalent()) |
| 159 break; | 159 break; |
| 160 } | 160 } |
| 161 return pos; | 161 return pos; |
| 162 } | 162 } |
| 163 | 163 |
| 164 ReplacementFragment::ReplacementFragment(Document* document, | 164 ReplacementFragment::ReplacementFragment(Document* document, |
| 165 DocumentFragment* fragment, | 165 DocumentFragment* fragment, |
| 166 const VisibleSelection& selection) | 166 const VisibleSelection& selection) |
| 167 : m_document(document), | 167 : m_document(document), |
| 168 m_fragment(fragment), | 168 m_fragment(fragment), |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 return false; | 465 return false; |
| 466 | 466 |
| 467 // When we have matching quote levels, its ok to merge more frequently. | 467 // When we have matching quote levels, its ok to merge more frequently. |
| 468 // For a successful merge, we still need to make sure that the inserted | 468 // For a successful merge, we still need to make sure that the inserted |
| 469 // content starts with the beginning of a paragraph. And we should only merge | 469 // content starts with the beginning of a paragraph. And we should only merge |
| 470 // here if the selection start was inside a mail blockquote. This prevents | 470 // here if the selection start was inside a mail blockquote. This prevents |
| 471 // against removing a blockquote from newly pasted quoted content that was | 471 // against removing a blockquote from newly pasted quoted content that was |
| 472 // pasted into an unquoted position. If that unquoted position happens to be | 472 // pasted into an unquoted position. If that unquoted position happens to be |
| 473 // right after another blockquote, we don't want to merge and risk stripping a | 473 // right after another blockquote, we don't want to merge and risk stripping a |
| 474 // valid block (and newline) from the pasted content. | 474 // valid block (and newline) from the pasted content. |
| 475 if (isStartOfParagraphDeprecated(startOfInsertedContent) && | 475 if (isStartOfParagraph(startOfInsertedContent) && |
| 476 selectionStartWasInsideMailBlockquote && | 476 selectionStartWasInsideMailBlockquote && |
| 477 hasMatchingQuoteLevel(prev, positionAtEndOfInsertedContent())) | 477 hasMatchingQuoteLevel(prev, positionAtEndOfInsertedContent())) |
| 478 return true; | 478 return true; |
| 479 | 479 |
| 480 return !selectionStartWasStartOfParagraph && | 480 return !selectionStartWasStartOfParagraph && |
| 481 !fragmentHasInterchangeNewlineAtStart && | 481 !fragmentHasInterchangeNewlineAtStart && |
| 482 isStartOfParagraphDeprecated(startOfInsertedContent) && | 482 isStartOfParagraph(startOfInsertedContent) && |
| 483 !isHTMLBRElement( | 483 !isHTMLBRElement( |
| 484 *startOfInsertedContent.deepEquivalent().anchorNode()) && | 484 *startOfInsertedContent.deepEquivalent().anchorNode()) && |
| 485 shouldMerge(startOfInsertedContent, prev); | 485 shouldMerge(startOfInsertedContent, prev); |
| 486 } | 486 } |
| 487 | 487 |
| 488 bool ReplaceSelectionCommand::shouldMergeEnd( | 488 bool ReplaceSelectionCommand::shouldMergeEnd( |
| 489 bool selectionEndWasEndOfParagraph) { | 489 bool selectionEndWasEndOfParagraph) { |
| 490 VisiblePosition endOfInsertedContent(positionAtEndOfInsertedContent()); | 490 VisiblePosition endOfInsertedContent(positionAtEndOfInsertedContent()); |
| 491 VisiblePosition next = | 491 VisiblePosition next = |
| 492 nextPositionOf(endOfInsertedContent, CannotCrossEditingBoundary); | 492 nextPositionOf(endOfInsertedContent, CannotCrossEditingBoundary); |
| 493 if (next.isNull()) | 493 if (next.isNull()) |
| 494 return false; | 494 return false; |
| 495 | 495 |
| 496 return !selectionEndWasEndOfParagraph && | 496 return !selectionEndWasEndOfParagraph && |
| 497 isEndOfParagraphDeprecated(endOfInsertedContent) && | 497 isEndOfParagraph(endOfInsertedContent) && |
| 498 !isHTMLBRElement( | 498 !isHTMLBRElement( |
| 499 *endOfInsertedContent.deepEquivalent().anchorNode()) && | 499 *endOfInsertedContent.deepEquivalent().anchorNode()) && |
| 500 shouldMerge(endOfInsertedContent, next); | 500 shouldMerge(endOfInsertedContent, next); |
| 501 } | 501 } |
| 502 | 502 |
| 503 static bool isMailPasteAsQuotationHTMLBlockQuoteElement(const Node* node) { | 503 static bool isMailPasteAsQuotationHTMLBlockQuoteElement(const Node* node) { |
| 504 if (!node || !node->isHTMLElement()) | 504 if (!node || !node->isHTMLElement()) |
| 505 return false; | 505 return false; |
| 506 const HTMLElement& element = toHTMLElement(*node); | 506 const HTMLElement& element = toHTMLElement(*node); |
| 507 if (!element.hasTagName(blockquoteTag) || | 507 if (!element.hasTagName(blockquoteTag) || |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 | 750 |
| 751 void ReplaceSelectionCommand::moveElementOutOfAncestor( | 751 void ReplaceSelectionCommand::moveElementOutOfAncestor( |
| 752 Element* element, | 752 Element* element, |
| 753 Element* ancestor, | 753 Element* ancestor, |
| 754 EditingState* editingState) { | 754 EditingState* editingState) { |
| 755 if (!hasEditableStyle(*ancestor->parentNode())) | 755 if (!hasEditableStyle(*ancestor->parentNode())) |
| 756 return; | 756 return; |
| 757 | 757 |
| 758 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 758 VisiblePosition positionAtEndOfNode = | 759 VisiblePosition positionAtEndOfNode = |
| 759 createVisiblePositionDeprecated(lastPositionInOrAfterNode(element)); | 760 createVisiblePosition(lastPositionInOrAfterNode(element)); |
| 760 VisiblePosition lastPositionInParagraph = | 761 VisiblePosition lastPositionInParagraph = |
| 761 VisiblePosition::lastPositionInNode(ancestor); | 762 VisiblePosition::lastPositionInNode(ancestor); |
| 762 if (positionAtEndOfNode.deepEquivalent() == | 763 if (positionAtEndOfNode.deepEquivalent() == |
| 763 lastPositionInParagraph.deepEquivalent()) { | 764 lastPositionInParagraph.deepEquivalent()) { |
| 764 removeNode(element, editingState); | 765 removeNode(element, editingState); |
| 765 if (editingState->isAborted()) | 766 if (editingState->isAborted()) |
| 766 return; | 767 return; |
| 767 if (ancestor->nextSibling()) | 768 if (ancestor->nextSibling()) |
| 768 insertNodeBefore(element, ancestor->nextSibling(), editingState); | 769 insertNodeBefore(element, ancestor->nextSibling(), editingState); |
| 769 else | 770 else |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 if (firstNodeInserted && firstNodeInserted->isTextNode() && | 811 if (firstNodeInserted && firstNodeInserted->isTextNode() && |
| 811 !nodeHasVisibleLayoutText(toText(*firstNodeInserted))) { | 812 !nodeHasVisibleLayoutText(toText(*firstNodeInserted))) { |
| 812 insertedNodes.willRemoveNode(*firstNodeInserted); | 813 insertedNodes.willRemoveNode(*firstNodeInserted); |
| 813 // Removing a Text node won't dispatch synchronous events. | 814 // Removing a Text node won't dispatch synchronous events. |
| 814 removeNode(firstNodeInserted, ASSERT_NO_EDITING_ABORT); | 815 removeNode(firstNodeInserted, ASSERT_NO_EDITING_ABORT); |
| 815 } | 816 } |
| 816 } | 817 } |
| 817 | 818 |
| 818 VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() | 819 VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() |
| 819 const { | 820 const { |
| 821 // TODO(xiaochengh): Hoist the call and change it into a DCHECK. |
| 822 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 820 // TODO(yosin): We should set |m_endOfInsertedContent| not in SELECT | 823 // TODO(yosin): We should set |m_endOfInsertedContent| not in SELECT |
| 821 // element, since contents of SELECT elements, e.g. OPTION, OPTGROUP, are | 824 // element, since contents of SELECT elements, e.g. OPTION, OPTGROUP, are |
| 822 // not editable, or SELECT element is an atomic on editing. | 825 // not editable, or SELECT element is an atomic on editing. |
| 823 HTMLSelectElement* enclosingSelect = toHTMLSelectElement( | 826 HTMLSelectElement* enclosingSelect = toHTMLSelectElement( |
| 824 enclosingElementWithTag(m_endOfInsertedContent, selectTag)); | 827 enclosingElementWithTag(m_endOfInsertedContent, selectTag)); |
| 825 if (enclosingSelect) | 828 if (enclosingSelect) |
| 826 return createVisiblePositionDeprecated( | 829 return createVisiblePosition(lastPositionInOrAfterNode(enclosingSelect)); |
| 827 lastPositionInOrAfterNode(enclosingSelect)); | |
| 828 if (m_endOfInsertedContent.isOrphan()) | 830 if (m_endOfInsertedContent.isOrphan()) |
| 829 return VisiblePosition(); | 831 return VisiblePosition(); |
| 830 return createVisiblePositionDeprecated(m_endOfInsertedContent); | 832 return createVisiblePosition(m_endOfInsertedContent); |
| 831 } | 833 } |
| 832 | 834 |
| 833 VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() | 835 VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() |
| 834 const { | 836 const { |
| 837 // TODO(xiaochengh): Hoist the call and change it into a DCHECK. |
| 838 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 835 if (m_startOfInsertedContent.isOrphan()) | 839 if (m_startOfInsertedContent.isOrphan()) |
| 836 return VisiblePosition(); | 840 return VisiblePosition(); |
| 837 return createVisiblePositionDeprecated(m_startOfInsertedContent); | 841 return createVisiblePosition(m_startOfInsertedContent); |
| 838 } | 842 } |
| 839 | 843 |
| 840 static void removeHeadContents(ReplacementFragment& fragment) { | 844 static void removeHeadContents(ReplacementFragment& fragment) { |
| 841 Node* next = nullptr; | 845 Node* next = nullptr; |
| 842 for (Node* node = fragment.firstChild(); node; node = next) { | 846 for (Node* node = fragment.firstChild(); node; node = next) { |
| 843 if (isHTMLBaseElement(*node) || isHTMLLinkElement(*node) || | 847 if (isHTMLBaseElement(*node) || isHTMLLinkElement(*node) || |
| 844 isHTMLMetaElement(*node) || isHTMLTitleElement(*node)) { | 848 isHTMLMetaElement(*node) || isHTMLTitleElement(*node)) { |
| 845 next = NodeTraversal::nextSkippingChildren(*node); | 849 next = NodeTraversal::nextSkippingChildren(*node); |
| 846 fragment.removeNode(node); | 850 fragment.removeNode(node); |
| 847 } else { | 851 } else { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 if (m_movingParagraph) { | 1002 if (m_movingParagraph) { |
| 999 NOTREACHED(); | 1003 NOTREACHED(); |
| 1000 return; | 1004 return; |
| 1001 } | 1005 } |
| 1002 | 1006 |
| 1003 // Merging two paragraphs will destroy the moved one's block styles. Always | 1007 // Merging two paragraphs will destroy the moved one's block styles. Always |
| 1004 // move the end of inserted forward to preserve the block style of the | 1008 // move the end of inserted forward to preserve the block style of the |
| 1005 // paragraph already in the document, unless the paragraph to move would | 1009 // paragraph already in the document, unless the paragraph to move would |
| 1006 // include the what was the start of the selection that was pasted into, so | 1010 // include the what was the start of the selection that was pasted into, so |
| 1007 // that we preserve that paragraph's block styles. | 1011 // that we preserve that paragraph's block styles. |
| 1008 bool mergeForward = !( | 1012 bool mergeForward = |
| 1009 inSameParagraphDeprecated(startOfInsertedContent, endOfInsertedContent) && | 1013 !(inSameParagraph(startOfInsertedContent, endOfInsertedContent) && |
| 1010 !isStartOfParagraphDeprecated(startOfInsertedContent)); | 1014 !isStartOfParagraph(startOfInsertedContent)); |
| 1011 | 1015 |
| 1012 VisiblePosition destination = mergeForward | 1016 VisiblePosition destination = mergeForward |
| 1013 ? nextPositionOf(endOfInsertedContent) | 1017 ? nextPositionOf(endOfInsertedContent) |
| 1014 : endOfInsertedContent; | 1018 : endOfInsertedContent; |
| 1019 // TODO(xiaochengh): Stop storing VisiblePositions through mutations. |
| 1015 VisiblePosition startOfParagraphToMove = | 1020 VisiblePosition startOfParagraphToMove = |
| 1016 mergeForward ? startOfParagraphDeprecated(endOfInsertedContent) | 1021 mergeForward ? startOfParagraph(endOfInsertedContent) |
| 1017 : nextPositionOf(endOfInsertedContent); | 1022 : nextPositionOf(endOfInsertedContent); |
| 1018 | 1023 |
| 1019 // Merging forward could result in deleting the destination anchor node. | 1024 // Merging forward could result in deleting the destination anchor node. |
| 1020 // To avoid this, we add a placeholder node before the start of the paragraph. | 1025 // To avoid this, we add a placeholder node before the start of the paragraph. |
| 1021 if (endOfParagraphDeprecated(startOfParagraphToMove).deepEquivalent() == | 1026 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == |
| 1022 destination.deepEquivalent()) { | 1027 destination.deepEquivalent()) { |
| 1023 HTMLBRElement* placeholder = HTMLBRElement::create(document()); | 1028 HTMLBRElement* placeholder = HTMLBRElement::create(document()); |
| 1024 insertNodeBefore(placeholder, | 1029 insertNodeBefore(placeholder, |
| 1025 startOfParagraphToMove.deepEquivalent().anchorNode(), | 1030 startOfParagraphToMove.deepEquivalent().anchorNode(), |
| 1026 editingState); | 1031 editingState); |
| 1027 if (editingState->isAborted()) | 1032 if (editingState->isAborted()) |
| 1028 return; | 1033 return; |
| 1034 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1029 destination = VisiblePosition::beforeNode(placeholder); | 1035 destination = VisiblePosition::beforeNode(placeholder); |
| 1036 startOfParagraphToMove = |
| 1037 createVisiblePosition(startOfParagraphToMove.toPositionWithAffinity()); |
| 1030 } | 1038 } |
| 1031 | 1039 |
| 1032 moveParagraph(startOfParagraphToMove, | 1040 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove), |
| 1033 endOfParagraphDeprecated(startOfParagraphToMove), destination, | 1041 destination, editingState); |
| 1034 editingState); | |
| 1035 if (editingState->isAborted()) | 1042 if (editingState->isAborted()) |
| 1036 return; | 1043 return; |
| 1037 | 1044 |
| 1045 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1046 |
| 1038 // Merging forward will remove m_endOfInsertedContent from the document. | 1047 // Merging forward will remove m_endOfInsertedContent from the document. |
| 1039 if (mergeForward) { | 1048 if (mergeForward) { |
| 1040 if (m_startOfInsertedContent.isOrphan()) | 1049 if (m_startOfInsertedContent.isOrphan()) { |
| 1041 m_startOfInsertedContent = | 1050 m_startOfInsertedContent = |
| 1042 endingSelection().visibleStartDeprecated().deepEquivalent(); | 1051 endingSelection().visibleStart().deepEquivalent(); |
| 1043 m_endOfInsertedContent = | 1052 } |
| 1044 endingSelection().visibleEndDeprecated().deepEquivalent(); | 1053 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivalent(); |
| 1045 // If we merged text nodes, m_endOfInsertedContent could be null. If | 1054 // If we merged text nodes, m_endOfInsertedContent could be null. If |
| 1046 // this is the case, we use m_startOfInsertedContent. | 1055 // this is the case, we use m_startOfInsertedContent. |
| 1047 if (m_endOfInsertedContent.isNull()) | 1056 if (m_endOfInsertedContent.isNull()) |
| 1048 m_endOfInsertedContent = m_startOfInsertedContent; | 1057 m_endOfInsertedContent = m_startOfInsertedContent; |
| 1049 } | 1058 } |
| 1050 } | 1059 } |
| 1051 | 1060 |
| 1052 static Node* enclosingInline(Node* node) { | 1061 static Node* enclosingInline(Node* node) { |
| 1053 while (ContainerNode* parent = node->parentNode()) { | 1062 while (ContainerNode* parent = node->parentNode()) { |
| 1054 if (isBlockFlowElement(*parent) || isHTMLBodyElement(*parent)) | 1063 if (isBlockFlowElement(*parent) || isHTMLBodyElement(*parent)) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 return; | 1126 return; |
| 1118 | 1127 |
| 1119 ReplacementFragment fragment(&document(), m_documentFragment.get(), | 1128 ReplacementFragment fragment(&document(), m_documentFragment.get(), |
| 1120 selection); | 1129 selection); |
| 1121 bool trivialReplaceResult = performTrivialReplace(fragment, editingState); | 1130 bool trivialReplaceResult = performTrivialReplace(fragment, editingState); |
| 1122 if (editingState->isAborted()) | 1131 if (editingState->isAborted()) |
| 1123 return; | 1132 return; |
| 1124 if (trivialReplaceResult) | 1133 if (trivialReplaceResult) |
| 1125 return; | 1134 return; |
| 1126 | 1135 |
| 1136 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1137 |
| 1127 // We can skip matching the style if the selection is plain text. | 1138 // We can skip matching the style if the selection is plain text. |
| 1128 if ((selection.start().anchorNode()->layoutObject() && | 1139 if ((selection.start().anchorNode()->layoutObject() && |
| 1129 selection.start().anchorNode()->layoutObject()->style()->userModify() == | 1140 selection.start().anchorNode()->layoutObject()->style()->userModify() == |
| 1130 READ_WRITE_PLAINTEXT_ONLY) && | 1141 READ_WRITE_PLAINTEXT_ONLY) && |
| 1131 (selection.end().anchorNode()->layoutObject() && | 1142 (selection.end().anchorNode()->layoutObject() && |
| 1132 selection.end().anchorNode()->layoutObject()->style()->userModify() == | 1143 selection.end().anchorNode()->layoutObject()->style()->userModify() == |
| 1133 READ_WRITE_PLAINTEXT_ONLY)) | 1144 READ_WRITE_PLAINTEXT_ONLY)) |
| 1134 m_matchStyle = false; | 1145 m_matchStyle = false; |
| 1135 | 1146 |
| 1136 if (m_matchStyle) { | 1147 if (m_matchStyle) { |
| 1137 m_insertionStyle = EditingStyle::create(selection.start()); | 1148 m_insertionStyle = EditingStyle::create(selection.start()); |
| 1138 m_insertionStyle->mergeTypingStyle(&document()); | 1149 m_insertionStyle->mergeTypingStyle(&document()); |
| 1139 } | 1150 } |
| 1140 | 1151 |
| 1141 const VisiblePosition visibleStart = selection.visibleStartDeprecated(); | 1152 const VisiblePosition visibleStart = selection.visibleStart(); |
| 1142 const VisiblePosition visibleEnd = selection.visibleEndDeprecated(); | 1153 const VisiblePosition visibleEnd = selection.visibleEnd(); |
| 1143 | 1154 |
| 1144 const bool selectionEndWasEndOfParagraph = | 1155 const bool selectionEndWasEndOfParagraph = isEndOfParagraph(visibleEnd); |
| 1145 isEndOfParagraphDeprecated(visibleEnd); | |
| 1146 const bool selectionStartWasStartOfParagraph = | 1156 const bool selectionStartWasStartOfParagraph = |
| 1147 isStartOfParagraphDeprecated(visibleStart); | 1157 isStartOfParagraph(visibleStart); |
| 1148 | 1158 |
| 1149 Element* enclosingBlockOfVisibleStart = | 1159 Element* enclosingBlockOfVisibleStart = |
| 1150 enclosingBlock(visibleStart.deepEquivalent().anchorNode()); | 1160 enclosingBlock(visibleStart.deepEquivalent().anchorNode()); |
| 1151 | 1161 |
| 1152 const bool startIsInsideMailBlockquote = enclosingNodeOfType( | 1162 const bool startIsInsideMailBlockquote = enclosingNodeOfType( |
| 1153 selection.start(), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); | 1163 selection.start(), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); |
| 1154 const bool selectionIsPlainText = !selection.isContentRichlyEditable(); | 1164 const bool selectionIsPlainText = !selection.isContentRichlyEditable(); |
| 1155 Element* currentRoot = selection.rootEditableElement(); | 1165 Element* currentRoot = selection.rootEditableElement(); |
| 1156 | 1166 |
| 1157 if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && | 1167 if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && |
| 1158 !startIsInsideMailBlockquote) || | 1168 !startIsInsideMailBlockquote) || |
| 1159 enclosingBlockOfVisibleStart == currentRoot || | 1169 enclosingBlockOfVisibleStart == currentRoot || |
| 1160 isListItem(enclosingBlockOfVisibleStart) || selectionIsPlainText) { | 1170 isListItem(enclosingBlockOfVisibleStart) || selectionIsPlainText) { |
| 1161 m_preventNesting = false; | 1171 m_preventNesting = false; |
| 1162 } | 1172 } |
| 1163 | 1173 |
| 1164 if (selection.isRange()) { | 1174 if (selection.isRange()) { |
| 1165 // When the end of the selection being pasted into is at the end of a | 1175 // When the end of the selection being pasted into is at the end of a |
| 1166 // paragraph, and that selection spans multiple blocks, not merging may | 1176 // paragraph, and that selection spans multiple blocks, not merging may |
| 1167 // leave an empty line. | 1177 // leave an empty line. |
| 1168 // When the start of the selection being pasted into is at the start of a | 1178 // When the start of the selection being pasted into is at the start of a |
| 1169 // block, not merging will leave hanging block(s). | 1179 // block, not merging will leave hanging block(s). |
| 1170 // Merge blocks if the start of the selection was in a Mail blockquote, | 1180 // Merge blocks if the start of the selection was in a Mail blockquote, |
| 1171 // since we handle that case specially to prevent nesting. | 1181 // since we handle that case specially to prevent nesting. |
| 1172 bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || | 1182 bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || |
| 1173 isEndOfParagraphDeprecated(visibleEnd) || | 1183 isEndOfParagraph(visibleEnd) || |
| 1174 isStartOfBlock(visibleStart); | 1184 isStartOfBlock(visibleStart); |
| 1175 // FIXME: We should only expand to include fully selected special elements | 1185 // FIXME: We should only expand to include fully selected special elements |
| 1176 // if we are copying a selection and pasting it on top of itself. | 1186 // if we are copying a selection and pasting it on top of itself. |
| 1177 deleteSelection(editingState, false, mergeBlocksAfterDelete, false); | 1187 deleteSelection(editingState, false, mergeBlocksAfterDelete, false); |
| 1178 if (editingState->isAborted()) | 1188 if (editingState->isAborted()) |
| 1179 return; | 1189 return; |
| 1180 if (fragment.hasInterchangeNewlineAtStart()) { | 1190 if (fragment.hasInterchangeNewlineAtStart()) { |
| 1181 VisiblePosition startAfterDelete = | 1191 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1182 endingSelection().visibleStartDeprecated(); | 1192 VisiblePosition startAfterDelete = endingSelection().visibleStart(); |
| 1183 if (isEndOfParagraphDeprecated(startAfterDelete) && | 1193 if (isEndOfParagraph(startAfterDelete) && |
| 1184 !isStartOfParagraphDeprecated(startAfterDelete) && | 1194 !isStartOfParagraph(startAfterDelete) && |
| 1185 !isEndOfEditableOrNonEditableContent(startAfterDelete)) | 1195 !isEndOfEditableOrNonEditableContent(startAfterDelete)) |
| 1186 setEndingSelection(nextPositionOf(startAfterDelete)); | 1196 setEndingSelection(nextPositionOf(startAfterDelete)); |
| 1187 else | 1197 else |
| 1188 insertParagraphSeparator(editingState); | 1198 insertParagraphSeparator(editingState); |
| 1189 if (editingState->isAborted()) | 1199 if (editingState->isAborted()) |
| 1190 return; | 1200 return; |
| 1191 } | 1201 } |
| 1192 } else { | 1202 } else { |
| 1193 DCHECK(selection.isCaret()); | 1203 DCHECK(selection.isCaret()); |
| 1194 if (fragment.hasInterchangeNewlineAtStart()) { | 1204 if (fragment.hasInterchangeNewlineAtStart()) { |
| 1195 const VisiblePosition next = | 1205 const VisiblePosition next = |
| 1196 nextPositionOf(visibleStart, CannotCrossEditingBoundary); | 1206 nextPositionOf(visibleStart, CannotCrossEditingBoundary); |
| 1197 if (isEndOfParagraphDeprecated(visibleStart) && | 1207 if (isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart) && |
| 1198 !isStartOfParagraphDeprecated(visibleStart) && next.isNotNull()) | 1208 next.isNotNull()) { |
| 1199 setEndingSelection(next); | 1209 setEndingSelection(next); |
| 1200 else | 1210 } else { |
| 1201 insertParagraphSeparator(editingState); | 1211 insertParagraphSeparator(editingState); |
| 1202 if (editingState->isAborted()) | 1212 if (editingState->isAborted()) |
| 1203 return; | 1213 return; |
| 1214 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1215 } |
| 1204 } | 1216 } |
| 1205 // We split the current paragraph in two to avoid nesting the blocks from | 1217 // We split the current paragraph in two to avoid nesting the blocks from |
| 1206 // the fragment inside the current block. | 1218 // the fragment inside the current block. |
| 1207 // | 1219 // |
| 1208 // For example, paste | 1220 // For example, paste |
| 1209 // <div>foo</div><div>bar</div><div>baz</div> | 1221 // <div>foo</div><div>bar</div><div>baz</div> |
| 1210 // into | 1222 // into |
| 1211 // <div>x^x</div> | 1223 // <div>x^x</div> |
| 1212 // where ^ is the caret. | 1224 // where ^ is the caret. |
| 1213 // | 1225 // |
| 1214 // As long as the div styles are the same, visually you'd expect: | 1226 // As long as the div styles are the same, visually you'd expect: |
| 1215 // <div>xbar</div><div>bar</div><div>bazx</div> | 1227 // <div>xbar</div><div>bar</div><div>bazx</div> |
| 1216 // not | 1228 // not |
| 1217 // <div>xbar<div>bar</div><div>bazx</div></div> | 1229 // <div>xbar<div>bar</div><div>bazx</div></div> |
| 1218 // Don't do this if the selection started in a Mail blockquote. | 1230 // Don't do this if the selection started in a Mail blockquote. |
| 1219 if (m_preventNesting && !startIsInsideMailBlockquote && | 1231 if (m_preventNesting && !startIsInsideMailBlockquote && |
| 1220 !isEndOfParagraphDeprecated( | 1232 !isEndOfParagraph(endingSelection().visibleStart()) && |
| 1221 endingSelection().visibleStartDeprecated()) && | 1233 !isStartOfParagraph(endingSelection().visibleStart())) { |
| 1222 !isStartOfParagraphDeprecated( | |
| 1223 endingSelection().visibleStartDeprecated())) { | |
| 1224 insertParagraphSeparator(editingState); | 1234 insertParagraphSeparator(editingState); |
| 1225 if (editingState->isAborted()) | 1235 if (editingState->isAborted()) |
| 1226 return; | 1236 return; |
| 1227 setEndingSelection( | 1237 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1228 previousPositionOf(endingSelection().visibleStartDeprecated())); | 1238 setEndingSelection(previousPositionOf(endingSelection().visibleStart())); |
| 1229 } | 1239 } |
| 1230 } | 1240 } |
| 1231 | 1241 |
| 1232 Position insertionPos = endingSelection().start(); | 1242 Position insertionPos = endingSelection().start(); |
| 1233 // We don't want any of the pasted content to end up nested in a Mail | 1243 // We don't want any of the pasted content to end up nested in a Mail |
| 1234 // blockquote, so first break out of any surrounding Mail blockquotes. Unless | 1244 // blockquote, so first break out of any surrounding Mail blockquotes. Unless |
| 1235 // we're inserting in a table, in which case breaking the blockquote will | 1245 // we're inserting in a table, in which case breaking the blockquote will |
| 1236 // prevent the content from actually being inserted in the table. | 1246 // prevent the content from actually being inserted in the table. |
| 1237 if (enclosingNodeOfType(insertionPos, isMailHTMLBlockquoteElement, | 1247 if (enclosingNodeOfType(insertionPos, isMailHTMLBlockquoteElement, |
| 1238 CanCrossEditingBoundary) && | 1248 CanCrossEditingBoundary) && |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1250 insertionPos = Position::inParentBeforeNode(*br); | 1260 insertionPos = Position::inParentBeforeNode(*br); |
| 1251 removeNode(br, editingState); | 1261 removeNode(br, editingState); |
| 1252 if (editingState->isAborted()) | 1262 if (editingState->isAborted()) |
| 1253 return; | 1263 return; |
| 1254 } | 1264 } |
| 1255 | 1265 |
| 1256 // Inserting content could cause whitespace to collapse, e.g. inserting | 1266 // Inserting content could cause whitespace to collapse, e.g. inserting |
| 1257 // <div>foo</div> into hello^ world. | 1267 // <div>foo</div> into hello^ world. |
| 1258 prepareWhitespaceAtPositionForSplit(insertionPos); | 1268 prepareWhitespaceAtPositionForSplit(insertionPos); |
| 1259 | 1269 |
| 1270 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1271 |
| 1260 // If the downstream node has been removed there's no point in continuing. | 1272 // If the downstream node has been removed there's no point in continuing. |
| 1261 if (!mostForwardCaretPosition(insertionPos).anchorNode()) | 1273 if (!mostForwardCaretPosition(insertionPos).anchorNode()) |
| 1262 return; | 1274 return; |
| 1263 | 1275 |
| 1264 // NOTE: This would be an incorrect usage of downstream() if downstream() were | 1276 // NOTE: This would be an incorrect usage of downstream() if downstream() were |
| 1265 // changed to mean the last position after p that maps to the same visible | 1277 // changed to mean the last position after p that maps to the same visible |
| 1266 // position as p (since in the case where a br is at the end of a block and | 1278 // position as p (since in the case where a br is at the end of a block and |
| 1267 // collapsed away, there are positions after the br which map to the same | 1279 // collapsed away, there are positions after the br which map to the same |
| 1268 // visible position as [br, 0]). | 1280 // visible position as [br, 0]). |
| 1269 HTMLBRElement* endBR = | 1281 HTMLBRElement* endBR = |
| 1270 isHTMLBRElement(*mostForwardCaretPosition(insertionPos).anchorNode()) | 1282 isHTMLBRElement(*mostForwardCaretPosition(insertionPos).anchorNode()) |
| 1271 ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchorNode()) | 1283 ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchorNode()) |
| 1272 : 0; | 1284 : 0; |
| 1273 VisiblePosition originalVisPosBeforeEndBR; | 1285 VisiblePosition originalVisPosBeforeEndBR; |
| 1274 if (endBR) | 1286 if (endBR) |
| 1275 originalVisPosBeforeEndBR = | 1287 originalVisPosBeforeEndBR = |
| 1276 previousPositionOf(VisiblePosition::beforeNode(endBR)); | 1288 previousPositionOf(VisiblePosition::beforeNode(endBR)); |
| 1277 | 1289 |
| 1278 Element* enclosingBlockOfInsertionPos = | 1290 Element* enclosingBlockOfInsertionPos = |
| 1279 enclosingBlock(insertionPos.anchorNode()); | 1291 enclosingBlock(insertionPos.anchorNode()); |
| 1280 | 1292 |
| 1281 // Adjust |enclosingBlockOfInsertionPos| to prevent nesting. | 1293 // Adjust |enclosingBlockOfInsertionPos| to prevent nesting. |
| 1282 // If the start was in a Mail blockquote, we will have already handled | 1294 // If the start was in a Mail blockquote, we will have already handled |
| 1283 // adjusting |enclosingBlockOfInsertionPos| above. | 1295 // adjusting |enclosingBlockOfInsertionPos| above. |
| 1284 if (m_preventNesting && enclosingBlockOfInsertionPos && | 1296 if (m_preventNesting && enclosingBlockOfInsertionPos && |
| 1285 enclosingBlockOfInsertionPos != currentRoot && | 1297 enclosingBlockOfInsertionPos != currentRoot && |
| 1286 !isTableCell(enclosingBlockOfInsertionPos) && | 1298 !isTableCell(enclosingBlockOfInsertionPos) && |
| 1287 !startIsInsideMailBlockquote) { | 1299 !startIsInsideMailBlockquote) { |
| 1288 VisiblePosition visibleInsertionPos = | 1300 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos); |
| 1289 createVisiblePositionDeprecated(insertionPos); | |
| 1290 if (isEndOfBlock(visibleInsertionPos) && | 1301 if (isEndOfBlock(visibleInsertionPos) && |
| 1291 !(isStartOfBlock(visibleInsertionPos) && | 1302 !(isStartOfBlock(visibleInsertionPos) && |
| 1292 fragment.hasInterchangeNewlineAtEnd())) | 1303 fragment.hasInterchangeNewlineAtEnd())) |
| 1293 insertionPos = Position::inParentAfterNode(*enclosingBlockOfInsertionPos); | 1304 insertionPos = Position::inParentAfterNode(*enclosingBlockOfInsertionPos); |
| 1294 else if (isStartOfBlock(visibleInsertionPos)) | 1305 else if (isStartOfBlock(visibleInsertionPos)) |
| 1295 insertionPos = | 1306 insertionPos = |
| 1296 Position::inParentBeforeNode(*enclosingBlockOfInsertionPos); | 1307 Position::inParentBeforeNode(*enclosingBlockOfInsertionPos); |
| 1297 } | 1308 } |
| 1298 | 1309 |
| 1299 // Paste at start or end of link goes outside of link. | 1310 // Paste at start or end of link goes outside of link. |
| 1300 insertionPos = | 1311 insertionPos = |
| 1301 positionAvoidingSpecialElementBoundary(insertionPos, editingState); | 1312 positionAvoidingSpecialElementBoundary(insertionPos, editingState); |
| 1302 if (editingState->isAborted()) | 1313 if (editingState->isAborted()) |
| 1303 return; | 1314 return; |
| 1304 | 1315 |
| 1305 // FIXME: Can this wait until after the operation has been performed? There | 1316 // FIXME: Can this wait until after the operation has been performed? There |
| 1306 // doesn't seem to be any work performed after this that queries or uses the | 1317 // doesn't seem to be any work performed after this that queries or uses the |
| 1307 // typing style. | 1318 // typing style. |
| 1308 if (LocalFrame* frame = document().frame()) | 1319 if (LocalFrame* frame = document().frame()) |
| 1309 frame->selection().clearTypingStyle(); | 1320 frame->selection().clearTypingStyle(); |
| 1310 | 1321 |
| 1311 removeHeadContents(fragment); | 1322 removeHeadContents(fragment); |
| 1312 | 1323 |
| 1324 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1325 |
| 1313 // We don't want the destination to end up inside nodes that weren't selected. | 1326 // We don't want the destination to end up inside nodes that weren't selected. |
| 1314 // To avoid that, we move the position forward without changing the visible | 1327 // To avoid that, we move the position forward without changing the visible |
| 1315 // position so we're still at the same visible location, but outside of | 1328 // position so we're still at the same visible location, but outside of |
| 1316 // preceding tags. | 1329 // preceding tags. |
| 1317 insertionPos = positionAvoidingPrecedingNodes(insertionPos); | 1330 insertionPos = positionAvoidingPrecedingNodes(insertionPos); |
| 1318 | 1331 |
| 1319 // Paste into run of tabs splits the tab span. | 1332 // Paste into run of tabs splits the tab span. |
| 1320 insertionPos = positionOutsideTabSpan(insertionPos); | 1333 insertionPos = positionOutsideTabSpan(insertionPos); |
| 1321 | 1334 |
| 1322 bool handledStyleSpans = | 1335 bool handledStyleSpans = |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 | 1436 |
| 1424 if (isRichlyEditablePosition(insertionPos)) | 1437 if (isRichlyEditablePosition(insertionPos)) |
| 1425 removeUnrenderedTextNodesAtEnds(insertedNodes); | 1438 removeUnrenderedTextNodesAtEnds(insertedNodes); |
| 1426 | 1439 |
| 1427 if (!handledStyleSpans) { | 1440 if (!handledStyleSpans) { |
| 1428 handleStyleSpans(insertedNodes, editingState); | 1441 handleStyleSpans(insertedNodes, editingState); |
| 1429 if (editingState->isAborted()) | 1442 if (editingState->isAborted()) |
| 1430 return; | 1443 return; |
| 1431 } | 1444 } |
| 1432 | 1445 |
| 1446 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1447 |
| 1433 // Mutation events (bug 20161) may have already removed the inserted content | 1448 // Mutation events (bug 20161) may have already removed the inserted content |
| 1434 if (!insertedNodes.firstNodeInserted() || | 1449 if (!insertedNodes.firstNodeInserted() || |
| 1435 !insertedNodes.firstNodeInserted()->isConnected()) | 1450 !insertedNodes.firstNodeInserted()->isConnected()) |
| 1436 return; | 1451 return; |
| 1437 | 1452 |
| 1438 // Scripts specified in javascript protocol may remove | 1453 // Scripts specified in javascript protocol may remove |
| 1439 // |enclosingBlockOfInsertionPos| during insertion, e.g. <iframe | 1454 // |enclosingBlockOfInsertionPos| during insertion, e.g. <iframe |
| 1440 // src="javascript:..."> | 1455 // src="javascript:..."> |
| 1441 if (enclosingBlockOfInsertionPos && | 1456 if (enclosingBlockOfInsertionPos && |
| 1442 !enclosingBlockOfInsertionPos->isConnected()) | 1457 !enclosingBlockOfInsertionPos->isConnected()) |
| 1443 enclosingBlockOfInsertionPos = nullptr; | 1458 enclosingBlockOfInsertionPos = nullptr; |
| 1444 | 1459 |
| 1445 VisiblePosition startOfInsertedContent = createVisiblePositionDeprecated( | 1460 VisiblePosition startOfInsertedContent = createVisiblePosition( |
| 1446 firstPositionInOrBeforeNode(insertedNodes.firstNodeInserted())); | 1461 firstPositionInOrBeforeNode(insertedNodes.firstNodeInserted())); |
| 1447 | 1462 |
| 1448 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, and | 1463 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, and |
| 1449 // the content before the enclosingBlockOfInsertionPos wasn't in its own block | 1464 // the content before the enclosingBlockOfInsertionPos wasn't in its own block |
| 1450 // and didn't have a br after it, so the inserted content ended up in the same | 1465 // and didn't have a br after it, so the inserted content ended up in the same |
| 1451 // paragraph. | 1466 // paragraph. |
| 1452 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && | 1467 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && |
| 1453 insertionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && | 1468 insertionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && |
| 1454 (unsigned)insertionPos.computeEditingOffset() < | 1469 (unsigned)insertionPos.computeEditingOffset() < |
| 1455 enclosingBlockOfInsertionPos->nodeIndex() && | 1470 enclosingBlockOfInsertionPos->nodeIndex() && |
| 1456 !isStartOfParagraphDeprecated(startOfInsertedContent)) { | 1471 !isStartOfParagraph(startOfInsertedContent)) { |
| 1457 insertNodeAt(HTMLBRElement::create(document()), | 1472 insertNodeAt(HTMLBRElement::create(document()), |
| 1458 startOfInsertedContent.deepEquivalent(), editingState); | 1473 startOfInsertedContent.deepEquivalent(), editingState); |
| 1459 if (editingState->isAborted()) | 1474 if (editingState->isAborted()) |
| 1460 return; | 1475 return; |
| 1461 } | 1476 } |
| 1462 | 1477 |
| 1463 if (endBR && | 1478 if (endBR && |
| 1464 (plainTextFragment || | 1479 (plainTextFragment || |
| 1465 (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR) && | 1480 (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR) && |
| 1466 !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)))) { | 1481 !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)))) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1503 lastPositionInOrAfterNode(insertedNodes.lastLeafInserted()); | 1518 lastPositionInOrAfterNode(insertedNodes.lastLeafInserted()); |
| 1504 | 1519 |
| 1505 // Determine whether or not we should merge the end of inserted content with | 1520 // Determine whether or not we should merge the end of inserted content with |
| 1506 // what's after it before we do the start merge so that the start merge | 1521 // what's after it before we do the start merge so that the start merge |
| 1507 // doesn't effect our decision. | 1522 // doesn't effect our decision. |
| 1508 m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph); | 1523 m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph); |
| 1509 | 1524 |
| 1510 if (shouldMergeStart(selectionStartWasStartOfParagraph, | 1525 if (shouldMergeStart(selectionStartWasStartOfParagraph, |
| 1511 fragment.hasInterchangeNewlineAtStart(), | 1526 fragment.hasInterchangeNewlineAtStart(), |
| 1512 startIsInsideMailBlockquote)) { | 1527 startIsInsideMailBlockquote)) { |
| 1528 // TODO(xiaochengh): Stop storing VisiblePositions through mutations. |
| 1513 VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedContent(); | 1529 VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedContent(); |
| 1514 VisiblePosition destination = previousPositionOf(startOfParagraphToMove); | 1530 VisiblePosition destination = previousPositionOf(startOfParagraphToMove); |
| 1515 // We need to handle the case where we need to merge the end | 1531 // We need to handle the case where we need to merge the end |
| 1516 // but our destination node is inside an inline that is the last in the | 1532 // but our destination node is inside an inline that is the last in the |
| 1517 // block. | 1533 // block. |
| 1518 // We insert a placeholder before the newly inserted content to avoid being | 1534 // We insert a placeholder before the newly inserted content to avoid being |
| 1519 // merged into the inline. | 1535 // merged into the inline. |
| 1520 Node* destinationNode = destination.deepEquivalent().anchorNode(); | 1536 Node* destinationNode = destination.deepEquivalent().anchorNode(); |
| 1521 if (m_shouldMergeEnd && | 1537 if (m_shouldMergeEnd && |
| 1522 destinationNode != enclosingInline(destinationNode) && | 1538 destinationNode != enclosingInline(destinationNode) && |
| 1523 enclosingInline(destinationNode)->nextSibling()) { | 1539 enclosingInline(destinationNode)->nextSibling()) { |
| 1524 insertNodeBefore(HTMLBRElement::create(document()), refNode, | 1540 insertNodeBefore(HTMLBRElement::create(document()), refNode, |
| 1525 editingState); | 1541 editingState); |
| 1526 if (editingState->isAborted()) | 1542 if (editingState->isAborted()) |
| 1527 return; | 1543 return; |
| 1528 } | 1544 } |
| 1529 | 1545 |
| 1530 // Merging the the first paragraph of inserted content with the content that | 1546 // Merging the the first paragraph of inserted content with the content that |
| 1531 // came before the selection that was pasted into would also move content | 1547 // came before the selection that was pasted into would also move content |
| 1532 // after the selection that was pasted into if: only one paragraph was being | 1548 // after the selection that was pasted into if: only one paragraph was being |
| 1533 // pasted, and it was not wrapped in a block, the selection that was pasted | 1549 // pasted, and it was not wrapped in a block, the selection that was pasted |
| 1534 // into ended at the end of a block and the next paragraph didn't start at | 1550 // into ended at the end of a block and the next paragraph didn't start at |
| 1535 // the start of a block. | 1551 // the start of a block. |
| 1536 // Insert a line break just after the inserted content to separate it from | 1552 // Insert a line break just after the inserted content to separate it from |
| 1537 // what comes after and prevent that from happening. | 1553 // what comes after and prevent that from happening. |
| 1538 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1554 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
| 1539 if (startOfParagraphDeprecated(endOfInsertedContent).deepEquivalent() == | 1555 if (startOfParagraph(endOfInsertedContent).deepEquivalent() == |
| 1540 startOfParagraphToMove.deepEquivalent()) { | 1556 startOfParagraphToMove.deepEquivalent()) { |
| 1541 insertNodeAt(HTMLBRElement::create(document()), | 1557 insertNodeAt(HTMLBRElement::create(document()), |
| 1542 endOfInsertedContent.deepEquivalent(), editingState); | 1558 endOfInsertedContent.deepEquivalent(), editingState); |
| 1543 if (editingState->isAborted()) | 1559 if (editingState->isAborted()) |
| 1544 return; | 1560 return; |
| 1545 // Mutation events (bug 22634) triggered by inserting the <br> might have | 1561 // Mutation events (bug 22634) triggered by inserting the <br> might have |
| 1546 // removed the content we're about to move | 1562 // removed the content we're about to move |
| 1547 if (!startOfParagraphToMove.deepEquivalent().isConnected()) | 1563 if (!startOfParagraphToMove.deepEquivalent().isConnected()) |
| 1548 return; | 1564 return; |
| 1549 } | 1565 } |
| 1550 | 1566 |
| 1567 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1568 |
| 1551 // FIXME: Maintain positions for the start and end of inserted content | 1569 // FIXME: Maintain positions for the start and end of inserted content |
| 1552 // instead of keeping nodes. The nodes are only ever used to create | 1570 // instead of keeping nodes. The nodes are only ever used to create |
| 1553 // positions where inserted content starts/ends. | 1571 // positions where inserted content starts/ends. |
| 1554 moveParagraph(startOfParagraphToMove, | 1572 moveParagraph(startOfParagraphToMove, |
| 1555 endOfParagraphDeprecated(startOfParagraphToMove), destination, | 1573 endOfParagraph(createVisiblePosition( |
| 1556 editingState); | 1574 startOfParagraphToMove.toPositionWithAffinity())), |
| 1575 destination, editingState); |
| 1557 if (editingState->isAborted()) | 1576 if (editingState->isAborted()) |
| 1558 return; | 1577 return; |
| 1578 |
| 1579 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1559 m_startOfInsertedContent = mostForwardCaretPosition( | 1580 m_startOfInsertedContent = mostForwardCaretPosition( |
| 1560 endingSelection().visibleStartDeprecated().deepEquivalent()); | 1581 endingSelection().visibleStart().deepEquivalent()); |
| 1561 if (m_endOfInsertedContent.isOrphan()) | 1582 if (m_endOfInsertedContent.isOrphan()) { |
| 1562 m_endOfInsertedContent = mostBackwardCaretPosition( | 1583 m_endOfInsertedContent = mostBackwardCaretPosition( |
| 1563 endingSelection().visibleEndDeprecated().deepEquivalent()); | 1584 endingSelection().visibleEnd().deepEquivalent()); |
| 1585 } |
| 1564 } | 1586 } |
| 1565 | 1587 |
| 1566 Position lastPositionToSelect; | 1588 Position lastPositionToSelect; |
| 1567 if (fragment.hasInterchangeNewlineAtEnd()) { | 1589 if (fragment.hasInterchangeNewlineAtEnd()) { |
| 1568 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1590 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
| 1569 VisiblePosition next = | 1591 VisiblePosition next = |
| 1570 nextPositionOf(endOfInsertedContent, CannotCrossEditingBoundary); | 1592 nextPositionOf(endOfInsertedContent, CannotCrossEditingBoundary); |
| 1571 | 1593 |
| 1572 if (selectionEndWasEndOfParagraph || | 1594 if (selectionEndWasEndOfParagraph || |
| 1573 !isEndOfParagraphDeprecated(endOfInsertedContent) || next.isNull()) { | 1595 !isEndOfParagraph(endOfInsertedContent) || next.isNull()) { |
| 1574 if (HTMLTextFormControlElement* textControl = | 1596 if (HTMLTextFormControlElement* textControl = |
| 1575 enclosingTextFormControl(currentRoot)) { | 1597 enclosingTextFormControl(currentRoot)) { |
| 1576 if (!insertedNodes.lastLeafInserted()->nextSibling()) { | 1598 if (!insertedNodes.lastLeafInserted()->nextSibling()) { |
| 1577 insertNodeAfter(textControl->createPlaceholderBreakElement(), | 1599 insertNodeAfter(textControl->createPlaceholderBreakElement(), |
| 1578 insertedNodes.lastLeafInserted(), editingState); | 1600 insertedNodes.lastLeafInserted(), editingState); |
| 1579 if (editingState->isAborted()) | 1601 if (editingState->isAborted()) |
| 1580 return; | 1602 return; |
| 1581 } | 1603 } |
| 1582 setEndingSelection( | 1604 setEndingSelection( |
| 1583 VisiblePosition::afterNode(insertedNodes.lastLeafInserted())); | 1605 VisiblePosition::afterNode(insertedNodes.lastLeafInserted())); |
| 1584 // Select up to the paragraph separator that was added. | 1606 // Select up to the paragraph separator that was added. |
| 1585 lastPositionToSelect = | 1607 lastPositionToSelect = |
| 1586 endingSelection().visibleStartDeprecated().deepEquivalent(); | 1608 endingSelection().visibleStart().deepEquivalent(); |
| 1587 } else if (!isStartOfParagraphDeprecated(endOfInsertedContent)) { | 1609 } else if (!isStartOfParagraph(endOfInsertedContent)) { |
| 1588 setEndingSelection(endOfInsertedContent); | 1610 setEndingSelection(endOfInsertedContent); |
| 1589 Element* enclosingBlockElement = | 1611 Element* enclosingBlockElement = |
| 1590 enclosingBlock(endOfInsertedContent.deepEquivalent().anchorNode()); | 1612 enclosingBlock(endOfInsertedContent.deepEquivalent().anchorNode()); |
| 1591 if (isListItem(enclosingBlockElement)) { | 1613 if (isListItem(enclosingBlockElement)) { |
| 1592 HTMLLIElement* newListItem = HTMLLIElement::create(document()); | 1614 HTMLLIElement* newListItem = HTMLLIElement::create(document()); |
| 1593 insertNodeAfter(newListItem, enclosingBlockElement, editingState); | 1615 insertNodeAfter(newListItem, enclosingBlockElement, editingState); |
| 1594 if (editingState->isAborted()) | 1616 if (editingState->isAborted()) |
| 1595 return; | 1617 return; |
| 1596 setEndingSelection(VisiblePosition::firstPositionInNode(newListItem)); | 1618 setEndingSelection(VisiblePosition::firstPositionInNode(newListItem)); |
| 1597 } else { | 1619 } else { |
| 1598 // Use a default paragraph element (a plain div) for the empty | 1620 // Use a default paragraph element (a plain div) for the empty |
| 1599 // paragraph, using the last paragraph block's style seems to annoy | 1621 // paragraph, using the last paragraph block's style seems to annoy |
| 1600 // users. | 1622 // users. |
| 1601 insertParagraphSeparator( | 1623 insertParagraphSeparator( |
| 1602 editingState, true, | 1624 editingState, true, |
| 1603 !startIsInsideMailBlockquote && | 1625 !startIsInsideMailBlockquote && |
| 1604 highestEnclosingNodeOfType( | 1626 highestEnclosingNodeOfType( |
| 1605 endOfInsertedContent.deepEquivalent(), | 1627 endOfInsertedContent.deepEquivalent(), |
| 1606 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary, | 1628 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary, |
| 1607 insertedNodes.firstNodeInserted()->parentNode())); | 1629 insertedNodes.firstNodeInserted()->parentNode())); |
| 1608 if (editingState->isAborted()) | 1630 if (editingState->isAborted()) |
| 1609 return; | 1631 return; |
| 1610 } | 1632 } |
| 1611 | 1633 |
| 1634 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1635 |
| 1612 // Select up to the paragraph separator that was added. | 1636 // Select up to the paragraph separator that was added. |
| 1613 lastPositionToSelect = | 1637 lastPositionToSelect = |
| 1614 endingSelection().visibleStartDeprecated().deepEquivalent(); | 1638 endingSelection().visibleStart().deepEquivalent(); |
| 1615 updateNodesInserted(lastPositionToSelect.anchorNode()); | 1639 updateNodesInserted(lastPositionToSelect.anchorNode()); |
| 1616 } | 1640 } |
| 1617 } else { | 1641 } else { |
| 1618 // Select up to the beginning of the next paragraph. | 1642 // Select up to the beginning of the next paragraph. |
| 1619 lastPositionToSelect = mostForwardCaretPosition(next.deepEquivalent()); | 1643 lastPositionToSelect = mostForwardCaretPosition(next.deepEquivalent()); |
| 1620 } | 1644 } |
| 1621 } else { | 1645 } else { |
| 1622 mergeEndIfNeeded(editingState); | 1646 mergeEndIfNeeded(editingState); |
| 1623 if (editingState->isAborted()) | 1647 if (editingState->isAborted()) |
| 1624 return; | 1648 return; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1651 | 1675 |
| 1652 VisiblePosition visiblePos = VisiblePosition::beforeNode(endBR); | 1676 VisiblePosition visiblePos = VisiblePosition::beforeNode(endBR); |
| 1653 | 1677 |
| 1654 // Don't remove the br if nothing was inserted. | 1678 // Don't remove the br if nothing was inserted. |
| 1655 if (previousPositionOf(visiblePos).deepEquivalent() == | 1679 if (previousPositionOf(visiblePos).deepEquivalent() == |
| 1656 originalVisPosBeforeEndBR.deepEquivalent()) | 1680 originalVisPosBeforeEndBR.deepEquivalent()) |
| 1657 return false; | 1681 return false; |
| 1658 | 1682 |
| 1659 // Remove the br if it is collapsed away and so is unnecessary. | 1683 // Remove the br if it is collapsed away and so is unnecessary. |
| 1660 if (!document().inNoQuirksMode() && isEndOfBlock(visiblePos) && | 1684 if (!document().inNoQuirksMode() && isEndOfBlock(visiblePos) && |
| 1661 !isStartOfParagraphDeprecated(visiblePos)) | 1685 !isStartOfParagraph(visiblePos)) |
| 1662 return true; | 1686 return true; |
| 1663 | 1687 |
| 1664 // A br that was originally holding a line open should be displaced by | 1688 // A br that was originally holding a line open should be displaced by |
| 1665 // inserted content or turned into a line break. | 1689 // inserted content or turned into a line break. |
| 1666 // A br that was originally acting as a line break should still be acting as a | 1690 // A br that was originally acting as a line break should still be acting as a |
| 1667 // line break, not as a placeholder. | 1691 // line break, not as a placeholder. |
| 1668 return isStartOfParagraphDeprecated(visiblePos) && | 1692 return isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos); |
| 1669 isEndOfParagraphDeprecated(visiblePos); | |
| 1670 } | 1693 } |
| 1671 | 1694 |
| 1672 bool ReplaceSelectionCommand::shouldPerformSmartReplace() const { | 1695 bool ReplaceSelectionCommand::shouldPerformSmartReplace() const { |
| 1673 if (!m_smartReplace) | 1696 if (!m_smartReplace) |
| 1674 return false; | 1697 return false; |
| 1675 | 1698 |
| 1676 HTMLTextFormControlElement* textControl = enclosingTextFormControl( | 1699 HTMLTextFormControlElement* textControl = enclosingTextFormControl( |
| 1677 positionAtStartOfInsertedContent().deepEquivalent()); | 1700 positionAtStartOfInsertedContent().deepEquivalent()); |
| 1678 if (isHTMLInputElement(textControl) && | 1701 if (isHTMLInputElement(textControl) && |
| 1679 toHTMLInputElement(textControl)->type() == InputTypeNames::password) | 1702 toHTMLInputElement(textControl)->type() == InputTypeNames::password) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1696 mostBackwardCaretPosition(endOfInsertedContent.deepEquivalent()); | 1719 mostBackwardCaretPosition(endOfInsertedContent.deepEquivalent()); |
| 1697 Node* endNode = endUpstream.computeNodeBeforePosition(); | 1720 Node* endNode = endUpstream.computeNodeBeforePosition(); |
| 1698 int endOffset = | 1721 int endOffset = |
| 1699 endNode && endNode->isTextNode() ? toText(endNode)->length() : 0; | 1722 endNode && endNode->isTextNode() ? toText(endNode)->length() : 0; |
| 1700 if (endUpstream.isOffsetInAnchor()) { | 1723 if (endUpstream.isOffsetInAnchor()) { |
| 1701 endNode = endUpstream.computeContainerNode(); | 1724 endNode = endUpstream.computeContainerNode(); |
| 1702 endOffset = endUpstream.offsetInContainerNode(); | 1725 endOffset = endUpstream.offsetInContainerNode(); |
| 1703 } | 1726 } |
| 1704 | 1727 |
| 1705 bool needsTrailingSpace = | 1728 bool needsTrailingSpace = |
| 1706 !isEndOfParagraphDeprecated(endOfInsertedContent) && | 1729 !isEndOfParagraph(endOfInsertedContent) && |
| 1707 !isCharacterSmartReplaceExemptConsideringNonBreakingSpace( | 1730 !isCharacterSmartReplaceExemptConsideringNonBreakingSpace( |
| 1708 characterAfter(endOfInsertedContent), false); | 1731 characterAfter(endOfInsertedContent), false); |
| 1709 if (needsTrailingSpace && endNode) { | 1732 if (needsTrailingSpace && endNode) { |
| 1710 bool collapseWhiteSpace = | 1733 bool collapseWhiteSpace = |
| 1711 !endNode->layoutObject() || | 1734 !endNode->layoutObject() || |
| 1712 endNode->layoutObject()->style()->collapseWhiteSpace(); | 1735 endNode->layoutObject()->style()->collapseWhiteSpace(); |
| 1713 if (endNode->isTextNode()) { | 1736 if (endNode->isTextNode()) { |
| 1714 insertTextIntoNode(toText(endNode), endOffset, | 1737 insertTextIntoNode(toText(endNode), endOffset, |
| 1715 collapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1738 collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
| 1716 if (m_endOfInsertedContent.computeContainerNode() == endNode) | 1739 if (m_endOfInsertedContent.computeContainerNode() == endNode) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1735 Position startDownstream = | 1758 Position startDownstream = |
| 1736 mostForwardCaretPosition(startOfInsertedContent.deepEquivalent()); | 1759 mostForwardCaretPosition(startOfInsertedContent.deepEquivalent()); |
| 1737 Node* startNode = startDownstream.computeNodeAfterPosition(); | 1760 Node* startNode = startDownstream.computeNodeAfterPosition(); |
| 1738 unsigned startOffset = 0; | 1761 unsigned startOffset = 0; |
| 1739 if (startDownstream.isOffsetInAnchor()) { | 1762 if (startDownstream.isOffsetInAnchor()) { |
| 1740 startNode = startDownstream.computeContainerNode(); | 1763 startNode = startDownstream.computeContainerNode(); |
| 1741 startOffset = startDownstream.offsetInContainerNode(); | 1764 startOffset = startDownstream.offsetInContainerNode(); |
| 1742 } | 1765 } |
| 1743 | 1766 |
| 1744 bool needsLeadingSpace = | 1767 bool needsLeadingSpace = |
| 1745 !isStartOfParagraphDeprecated(startOfInsertedContent) && | 1768 !isStartOfParagraph(startOfInsertedContent) && |
| 1746 !isCharacterSmartReplaceExemptConsideringNonBreakingSpace( | 1769 !isCharacterSmartReplaceExemptConsideringNonBreakingSpace( |
| 1747 characterBefore(startOfInsertedContent), true); | 1770 characterBefore(startOfInsertedContent), true); |
| 1748 if (needsLeadingSpace && startNode) { | 1771 if (needsLeadingSpace && startNode) { |
| 1749 bool collapseWhiteSpace = | 1772 bool collapseWhiteSpace = |
| 1750 !startNode->layoutObject() || | 1773 !startNode->layoutObject() || |
| 1751 startNode->layoutObject()->style()->collapseWhiteSpace(); | 1774 startNode->layoutObject()->style()->collapseWhiteSpace(); |
| 1752 if (startNode->isTextNode()) { | 1775 if (startNode->isTextNode()) { |
| 1753 insertTextIntoNode(toText(startNode), startOffset, | 1776 insertTextIntoNode(toText(startNode), startOffset, |
| 1754 collapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1777 collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
| 1755 if (m_endOfInsertedContent.computeContainerNode() == startNode && | 1778 if (m_endOfInsertedContent.computeContainerNode() == startNode && |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 return; | 1822 return; |
| 1800 } else if (lastPositionToSelect.isNotNull()) { | 1823 } else if (lastPositionToSelect.isNotNull()) { |
| 1801 start = end = lastPositionToSelect; | 1824 start = end = lastPositionToSelect; |
| 1802 } else { | 1825 } else { |
| 1803 return; | 1826 return; |
| 1804 } | 1827 } |
| 1805 | 1828 |
| 1806 m_startOfInsertedRange = start; | 1829 m_startOfInsertedRange = start; |
| 1807 m_endOfInsertedRange = end; | 1830 m_endOfInsertedRange = end; |
| 1808 | 1831 |
| 1832 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1833 |
| 1809 if (m_selectReplacement) | 1834 if (m_selectReplacement) |
| 1810 setEndingSelection(createVisibleSelectionDeprecated( | 1835 setEndingSelection(createVisibleSelection( |
| 1811 start, end, SelDefaultAffinity, endingSelection().isDirectional())); | 1836 start, end, SelDefaultAffinity, endingSelection().isDirectional())); |
| 1812 else | 1837 else |
| 1813 setEndingSelection(createVisibleSelectionDeprecated( | 1838 setEndingSelection(createVisibleSelection( |
| 1814 end, SelDefaultAffinity, endingSelection().isDirectional())); | 1839 end, SelDefaultAffinity, endingSelection().isDirectional())); |
| 1815 } | 1840 } |
| 1816 | 1841 |
| 1817 void ReplaceSelectionCommand::mergeTextNodesAroundPosition( | 1842 void ReplaceSelectionCommand::mergeTextNodesAroundPosition( |
| 1818 Position& position, | 1843 Position& position, |
| 1819 Position& positionOnlyToBeUpdated, | 1844 Position& positionOnlyToBeUpdated, |
| 1820 EditingState* editingState) { | 1845 EditingState* editingState) { |
| 1821 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); | 1846 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); |
| 1822 bool positionOnlyToBeUpdatedIsOffsetInAnchor = | 1847 bool positionOnlyToBeUpdatedIsOffsetInAnchor = |
| 1823 positionOnlyToBeUpdated.isOffsetInAnchor(); | 1848 positionOnlyToBeUpdated.isOffsetInAnchor(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 // list, we put the list items into the existing list. | 1940 // list, we put the list items into the existing list. |
| 1916 Node* ReplaceSelectionCommand::insertAsListItems(HTMLElement* listElement, | 1941 Node* ReplaceSelectionCommand::insertAsListItems(HTMLElement* listElement, |
| 1917 Element* insertionBlock, | 1942 Element* insertionBlock, |
| 1918 const Position& insertPos, | 1943 const Position& insertPos, |
| 1919 InsertedNodes& insertedNodes, | 1944 InsertedNodes& insertedNodes, |
| 1920 EditingState* editingState) { | 1945 EditingState* editingState) { |
| 1921 while (listElement->hasOneChild() && | 1946 while (listElement->hasOneChild() && |
| 1922 isHTMLListElement(listElement->firstChild())) | 1947 isHTMLListElement(listElement->firstChild())) |
| 1923 listElement = toHTMLElement(listElement->firstChild()); | 1948 listElement = toHTMLElement(listElement->firstChild()); |
| 1924 | 1949 |
| 1925 bool isStart = | 1950 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1926 isStartOfParagraphDeprecated(createVisiblePositionDeprecated(insertPos)); | 1951 bool isStart = isStartOfParagraph(createVisiblePosition(insertPos)); |
| 1927 bool isEnd = | 1952 bool isEnd = isEndOfParagraph(createVisiblePosition(insertPos)); |
| 1928 isEndOfParagraphDeprecated(createVisiblePositionDeprecated(insertPos)); | |
| 1929 bool isMiddle = !isStart && !isEnd; | 1953 bool isMiddle = !isStart && !isEnd; |
| 1930 Node* lastNode = insertionBlock; | 1954 Node* lastNode = insertionBlock; |
| 1931 | 1955 |
| 1932 // If we're in the middle of a list item, we should split it into two separate | 1956 // If we're in the middle of a list item, we should split it into two separate |
| 1933 // list items and insert these nodes between them. | 1957 // list items and insert these nodes between them. |
| 1934 if (isMiddle) { | 1958 if (isMiddle) { |
| 1935 int textNodeOffset = insertPos.offsetInContainerNode(); | 1959 int textNodeOffset = insertPos.offsetInContainerNode(); |
| 1936 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) | 1960 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) |
| 1937 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); | 1961 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); |
| 1938 splitTreeToNode(insertPos.anchorNode(), lastNode, true); | 1962 splitTreeToNode(insertPos.anchorNode(), lastNode, true); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos), | 2037 shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos), |
| 2014 VisiblePosition::beforeNode(nodeAfterInsertionPos))) { | 2038 VisiblePosition::beforeNode(nodeAfterInsertionPos))) { |
| 2015 removeNodeAndPruneAncestors(nodeAfterInsertionPos, editingState); | 2039 removeNodeAndPruneAncestors(nodeAfterInsertionPos, editingState); |
| 2016 if (editingState->isAborted()) | 2040 if (editingState->isAborted()) |
| 2017 return false; | 2041 return false; |
| 2018 } | 2042 } |
| 2019 | 2043 |
| 2020 m_startOfInsertedRange = start; | 2044 m_startOfInsertedRange = start; |
| 2021 m_endOfInsertedRange = end; | 2045 m_endOfInsertedRange = end; |
| 2022 | 2046 |
| 2047 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 2023 VisibleSelection selectionAfterReplace = | 2048 VisibleSelection selectionAfterReplace = |
| 2024 createVisibleSelectionDeprecated(m_selectReplacement ? start : end, end); | 2049 createVisibleSelection(m_selectReplacement ? start : end, end); |
| 2025 | 2050 |
| 2026 setEndingSelection(selectionAfterReplace); | 2051 setEndingSelection(selectionAfterReplace); |
| 2027 | 2052 |
| 2028 return true; | 2053 return true; |
| 2029 } | 2054 } |
| 2030 | 2055 |
| 2031 bool ReplaceSelectionCommand::isReplaceSelectionCommand() const { | 2056 bool ReplaceSelectionCommand::isReplaceSelectionCommand() const { |
| 2032 return true; | 2057 return true; |
| 2033 } | 2058 } |
| 2034 | 2059 |
| 2035 EphemeralRange ReplaceSelectionCommand::insertedRange() const { | 2060 EphemeralRange ReplaceSelectionCommand::insertedRange() const { |
| 2036 return EphemeralRange(m_startOfInsertedRange, m_endOfInsertedRange); | 2061 return EphemeralRange(m_startOfInsertedRange, m_endOfInsertedRange); |
| 2037 } | 2062 } |
| 2038 | 2063 |
| 2039 DEFINE_TRACE(ReplaceSelectionCommand) { | 2064 DEFINE_TRACE(ReplaceSelectionCommand) { |
| 2040 visitor->trace(m_startOfInsertedContent); | 2065 visitor->trace(m_startOfInsertedContent); |
| 2041 visitor->trace(m_endOfInsertedContent); | 2066 visitor->trace(m_endOfInsertedContent); |
| 2042 visitor->trace(m_insertionStyle); | 2067 visitor->trace(m_insertionStyle); |
| 2043 visitor->trace(m_documentFragment); | 2068 visitor->trace(m_documentFragment); |
| 2044 visitor->trace(m_startOfInsertedRange); | 2069 visitor->trace(m_startOfInsertedRange); |
| 2045 visitor->trace(m_endOfInsertedRange); | 2070 visitor->trace(m_endOfInsertedRange); |
| 2046 CompositeEditCommand::trace(visitor); | 2071 CompositeEditCommand::trace(visitor); |
| 2047 } | 2072 } |
| 2048 | 2073 |
| 2049 } // namespace blink | 2074 } // namespace blink |
| OLD | NEW |