| 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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 destination = VisiblePosition::beforeNode(placeholder); | 950 destination = VisiblePosition::beforeNode(placeholder); |
| 951 } | 951 } |
| 952 | 952 |
| 953 moveParagraph(startOfParagraphToMove, endOfParagraphDeprecated(startOfParagr
aphToMove), destination, editingState); | 953 moveParagraph(startOfParagraphToMove, endOfParagraphDeprecated(startOfParagr
aphToMove), destination, editingState); |
| 954 if (editingState->isAborted()) | 954 if (editingState->isAborted()) |
| 955 return; | 955 return; |
| 956 | 956 |
| 957 // Merging forward will remove m_endOfInsertedContent from the document. | 957 // Merging forward will remove m_endOfInsertedContent from the document. |
| 958 if (mergeForward) { | 958 if (mergeForward) { |
| 959 if (m_startOfInsertedContent.isOrphan()) | 959 if (m_startOfInsertedContent.isOrphan()) |
| 960 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui
valent(); | 960 m_startOfInsertedContent = endingSelection().visibleStartDeprecated(
).deepEquivalent(); |
| 961 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivalent()
; | 961 m_endOfInsertedContent = endingSelection().visibleEndDeprecated().deepEq
uivalent(); |
| 962 // If we merged text nodes, m_endOfInsertedContent could be null. If | 962 // If we merged text nodes, m_endOfInsertedContent could be null. If |
| 963 // this is the case, we use m_startOfInsertedContent. | 963 // this is the case, we use m_startOfInsertedContent. |
| 964 if (m_endOfInsertedContent.isNull()) | 964 if (m_endOfInsertedContent.isNull()) |
| 965 m_endOfInsertedContent = m_startOfInsertedContent; | 965 m_endOfInsertedContent = m_startOfInsertedContent; |
| 966 } | 966 } |
| 967 } | 967 } |
| 968 | 968 |
| 969 static Node* enclosingInline(Node* node) | 969 static Node* enclosingInline(Node* node) |
| 970 { | 970 { |
| 971 while (ContainerNode* parent = node->parentNode()) { | 971 while (ContainerNode* parent = node->parentNode()) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 // We can skip matching the style if the selection is plain text. | 1038 // We can skip matching the style if the selection is plain text. |
| 1039 if ((selection.start().anchorNode()->layoutObject() && selection.start().anc
horNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) | 1039 if ((selection.start().anchorNode()->layoutObject() && selection.start().anc
horNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) |
| 1040 && (selection.end().anchorNode()->layoutObject() && selection.end().anch
orNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY)) | 1040 && (selection.end().anchorNode()->layoutObject() && selection.end().anch
orNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY)) |
| 1041 m_matchStyle = false; | 1041 m_matchStyle = false; |
| 1042 | 1042 |
| 1043 if (m_matchStyle) { | 1043 if (m_matchStyle) { |
| 1044 m_insertionStyle = EditingStyle::create(selection.start()); | 1044 m_insertionStyle = EditingStyle::create(selection.start()); |
| 1045 m_insertionStyle->mergeTypingStyle(&document()); | 1045 m_insertionStyle->mergeTypingStyle(&document()); |
| 1046 } | 1046 } |
| 1047 | 1047 |
| 1048 const VisiblePosition visibleStart = selection.visibleStart(); | 1048 const VisiblePosition visibleStart = selection.visibleStartDeprecated(); |
| 1049 const VisiblePosition visibleEnd = selection.visibleEnd(); | 1049 const VisiblePosition visibleEnd = selection.visibleEndDeprecated(); |
| 1050 | 1050 |
| 1051 const bool selectionEndWasEndOfParagraph = isEndOfParagraphDeprecated(visibl
eEnd); | 1051 const bool selectionEndWasEndOfParagraph = isEndOfParagraphDeprecated(visibl
eEnd); |
| 1052 const bool selectionStartWasStartOfParagraph = isStartOfParagraphDeprecated(
visibleStart); | 1052 const bool selectionStartWasStartOfParagraph = isStartOfParagraphDeprecated(
visibleStart); |
| 1053 | 1053 |
| 1054 Element* enclosingBlockOfVisibleStart = enclosingBlock(visibleStart.deepEqui
valent().anchorNode()); | 1054 Element* enclosingBlockOfVisibleStart = enclosingBlock(visibleStart.deepEqui
valent().anchorNode()); |
| 1055 | 1055 |
| 1056 const bool startIsInsideMailBlockquote = enclosingNodeOfType(selection.start
(), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); | 1056 const bool startIsInsideMailBlockquote = enclosingNodeOfType(selection.start
(), isMailHTMLBlockquoteElement, CanCrossEditingBoundary); |
| 1057 const bool selectionIsPlainText = !selection.isContentRichlyEditable(); | 1057 const bool selectionIsPlainText = !selection.isContentRichlyEditable(); |
| 1058 Element* currentRoot = selection.rootEditableElement(); | 1058 Element* currentRoot = selection.rootEditableElement(); |
| 1059 | 1059 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1071 // will leave hanging block(s). | 1071 // will leave hanging block(s). |
| 1072 // Merge blocks if the start of the selection was in a Mail blockquote,
since we handle | 1072 // Merge blocks if the start of the selection was in a Mail blockquote,
since we handle |
| 1073 // that case specially to prevent nesting. | 1073 // that case specially to prevent nesting. |
| 1074 bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfPara
graphDeprecated(visibleEnd) || isStartOfBlock(visibleStart); | 1074 bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfPara
graphDeprecated(visibleEnd) || isStartOfBlock(visibleStart); |
| 1075 // FIXME: We should only expand to include fully selected special elemen
ts if we are copying a | 1075 // FIXME: We should only expand to include fully selected special elemen
ts if we are copying a |
| 1076 // selection and pasting it on top of itself. | 1076 // selection and pasting it on top of itself. |
| 1077 deleteSelection(editingState, false, mergeBlocksAfterDelete, false); | 1077 deleteSelection(editingState, false, mergeBlocksAfterDelete, false); |
| 1078 if (editingState->isAborted()) | 1078 if (editingState->isAborted()) |
| 1079 return; | 1079 return; |
| 1080 if (fragment.hasInterchangeNewlineAtStart()) { | 1080 if (fragment.hasInterchangeNewlineAtStart()) { |
| 1081 VisiblePosition startAfterDelete = endingSelection().visibleStart(); | 1081 VisiblePosition startAfterDelete = endingSelection().visibleStartDep
recated(); |
| 1082 if (isEndOfParagraphDeprecated(startAfterDelete) && !isStartOfParagr
aphDeprecated(startAfterDelete) && !isEndOfEditableOrNonEditableContent(startAft
erDelete)) | 1082 if (isEndOfParagraphDeprecated(startAfterDelete) && !isStartOfParagr
aphDeprecated(startAfterDelete) && !isEndOfEditableOrNonEditableContent(startAft
erDelete)) |
| 1083 setEndingSelection(nextPositionOf(startAfterDelete)); | 1083 setEndingSelection(nextPositionOf(startAfterDelete)); |
| 1084 else | 1084 else |
| 1085 insertParagraphSeparator(editingState); | 1085 insertParagraphSeparator(editingState); |
| 1086 if (editingState->isAborted()) | 1086 if (editingState->isAborted()) |
| 1087 return; | 1087 return; |
| 1088 } | 1088 } |
| 1089 } else { | 1089 } else { |
| 1090 DCHECK(selection.isCaret()); | 1090 DCHECK(selection.isCaret()); |
| 1091 if (fragment.hasInterchangeNewlineAtStart()) { | 1091 if (fragment.hasInterchangeNewlineAtStart()) { |
| 1092 const VisiblePosition next = nextPositionOf(visibleStart, CannotCros
sEditingBoundary); | 1092 const VisiblePosition next = nextPositionOf(visibleStart, CannotCros
sEditingBoundary); |
| 1093 if (isEndOfParagraphDeprecated(visibleStart) && !isStartOfParagraphD
eprecated(visibleStart) && next.isNotNull()) | 1093 if (isEndOfParagraphDeprecated(visibleStart) && !isStartOfParagraphD
eprecated(visibleStart) && next.isNotNull()) |
| 1094 setEndingSelection(next); | 1094 setEndingSelection(next); |
| 1095 else | 1095 else |
| 1096 insertParagraphSeparator(editingState); | 1096 insertParagraphSeparator(editingState); |
| 1097 if (editingState->isAborted()) | 1097 if (editingState->isAborted()) |
| 1098 return; | 1098 return; |
| 1099 } | 1099 } |
| 1100 // We split the current paragraph in two to avoid nesting the blocks fro
m the fragment inside the current block. | 1100 // We split the current paragraph in two to avoid nesting the blocks fro
m the fragment inside the current block. |
| 1101 // For example paste <div>foo</div><div>bar</div><div>baz</div> into <di
v>x^x</div>, where ^ is the caret. | 1101 // For example paste <div>foo</div><div>bar</div><div>baz</div> into <di
v>x^x</div>, where ^ is the caret. |
| 1102 // As long as the div styles are the same, visually you'd expect: <div>
xbar</div><div>bar</div><div>bazx</div>, | 1102 // As long as the div styles are the same, visually you'd expect: <div>
xbar</div><div>bar</div><div>bazx</div>, |
| 1103 // not <div>xbar<div>bar</div><div>bazx</div></div>. | 1103 // not <div>xbar<div>bar</div><div>bazx</div></div>. |
| 1104 // Don't do this if the selection started in a Mail blockquote. | 1104 // Don't do this if the selection started in a Mail blockquote. |
| 1105 if (m_preventNesting && !startIsInsideMailBlockquote && !isEndOfParagrap
hDeprecated(endingSelection().visibleStart()) && !isStartOfParagraphDeprecated(e
ndingSelection().visibleStart())) { | 1105 if (m_preventNesting && !startIsInsideMailBlockquote && !isEndOfParagrap
hDeprecated(endingSelection().visibleStartDeprecated()) && !isStartOfParagraphDe
precated(endingSelection().visibleStartDeprecated())) { |
| 1106 insertParagraphSeparator(editingState); | 1106 insertParagraphSeparator(editingState); |
| 1107 if (editingState->isAborted()) | 1107 if (editingState->isAborted()) |
| 1108 return; | 1108 return; |
| 1109 setEndingSelection(previousPositionOf(endingSelection().visibleStart
())); | 1109 setEndingSelection(previousPositionOf(endingSelection().visibleStart
Deprecated())); |
| 1110 } | 1110 } |
| 1111 } | 1111 } |
| 1112 | 1112 |
| 1113 Position insertionPos = endingSelection().start(); | 1113 Position insertionPos = endingSelection().start(); |
| 1114 // We don't want any of the pasted content to end up nested in a Mail blockq
uote, so first break | 1114 // We don't want any of the pasted content to end up nested in a Mail blockq
uote, so first break |
| 1115 // out of any surrounding Mail blockquotes. Unless we're inserting in a tabl
e, in which case | 1115 // out of any surrounding Mail blockquotes. Unless we're inserting in a tabl
e, in which case |
| 1116 // breaking the blockquote will prevent the content from actually being inse
rted in the table. | 1116 // breaking the blockquote will prevent the content from actually being inse
rted in the table. |
| 1117 if (enclosingNodeOfType(insertionPos, isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary) && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTa
bleStructureNode))) { | 1117 if (enclosingNodeOfType(insertionPos, isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary) && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTa
bleStructureNode))) { |
| 1118 applyCommandToComposite(BreakBlockquoteCommand::create(document()), edit
ingState); | 1118 applyCommandToComposite(BreakBlockquoteCommand::create(document()), edit
ingState); |
| 1119 if (editingState->isAborted()) | 1119 if (editingState->isAborted()) |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 // Mutation events (bug 22634) triggered by inserting the <br> might
have removed the content we're about to move | 1354 // Mutation events (bug 22634) triggered by inserting the <br> might
have removed the content we're about to move |
| 1355 if (!startOfParagraphToMove.deepEquivalent().isConnected()) | 1355 if (!startOfParagraphToMove.deepEquivalent().isConnected()) |
| 1356 return; | 1356 return; |
| 1357 } | 1357 } |
| 1358 | 1358 |
| 1359 // FIXME: Maintain positions for the start and end of inserted content i
nstead of keeping nodes. The nodes are | 1359 // FIXME: Maintain positions for the start and end of inserted content i
nstead of keeping nodes. The nodes are |
| 1360 // only ever used to create positions where inserted content starts/ends
. | 1360 // only ever used to create positions where inserted content starts/ends
. |
| 1361 moveParagraph(startOfParagraphToMove, endOfParagraphDeprecated(startOfPa
ragraphToMove), destination, editingState); | 1361 moveParagraph(startOfParagraphToMove, endOfParagraphDeprecated(startOfPa
ragraphToMove), destination, editingState); |
| 1362 if (editingState->isAborted()) | 1362 if (editingState->isAborted()) |
| 1363 return; | 1363 return; |
| 1364 m_startOfInsertedContent = mostForwardCaretPosition(endingSelection().vi
sibleStart().deepEquivalent()); | 1364 m_startOfInsertedContent = mostForwardCaretPosition(endingSelection().vi
sibleStartDeprecated().deepEquivalent()); |
| 1365 if (m_endOfInsertedContent.isOrphan()) | 1365 if (m_endOfInsertedContent.isOrphan()) |
| 1366 m_endOfInsertedContent = mostBackwardCaretPosition(endingSelection()
.visibleEnd().deepEquivalent()); | 1366 m_endOfInsertedContent = mostBackwardCaretPosition(endingSelection()
.visibleEndDeprecated().deepEquivalent()); |
| 1367 } | 1367 } |
| 1368 | 1368 |
| 1369 Position lastPositionToSelect; | 1369 Position lastPositionToSelect; |
| 1370 if (fragment.hasInterchangeNewlineAtEnd()) { | 1370 if (fragment.hasInterchangeNewlineAtEnd()) { |
| 1371 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1371 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
| 1372 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); | 1372 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); |
| 1373 | 1373 |
| 1374 if (selectionEndWasEndOfParagraph || !isEndOfParagraphDeprecated(endOfIn
sertedContent) || next.isNull()) { | 1374 if (selectionEndWasEndOfParagraph || !isEndOfParagraphDeprecated(endOfIn
sertedContent) || next.isNull()) { |
| 1375 if (HTMLTextFormControlElement* textControl = enclosingTextFormContr
ol(currentRoot)) { | 1375 if (HTMLTextFormControlElement* textControl = enclosingTextFormContr
ol(currentRoot)) { |
| 1376 if (!insertedNodes.lastLeafInserted()->nextSibling()) { | 1376 if (!insertedNodes.lastLeafInserted()->nextSibling()) { |
| 1377 insertNodeAfter(textControl->createPlaceholderBreakElement()
, insertedNodes.lastLeafInserted(), editingState); | 1377 insertNodeAfter(textControl->createPlaceholderBreakElement()
, insertedNodes.lastLeafInserted(), editingState); |
| 1378 if (editingState->isAborted()) | 1378 if (editingState->isAborted()) |
| 1379 return; | 1379 return; |
| 1380 } | 1380 } |
| 1381 setEndingSelection(VisiblePosition::afterNode(insertedNodes.last
LeafInserted())); | 1381 setEndingSelection(VisiblePosition::afterNode(insertedNodes.last
LeafInserted())); |
| 1382 // Select up to the paragraph separator that was added. | 1382 // Select up to the paragraph separator that was added. |
| 1383 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); | 1383 lastPositionToSelect = endingSelection().visibleStartDeprecated(
).deepEquivalent(); |
| 1384 } else if (!isStartOfParagraphDeprecated(endOfInsertedContent)) { | 1384 } else if (!isStartOfParagraphDeprecated(endOfInsertedContent)) { |
| 1385 setEndingSelection(endOfInsertedContent); | 1385 setEndingSelection(endOfInsertedContent); |
| 1386 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); | 1386 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); |
| 1387 if (isListItem(enclosingBlockElement)) { | 1387 if (isListItem(enclosingBlockElement)) { |
| 1388 HTMLLIElement* newListItem = HTMLLIElement::create(document(
)); | 1388 HTMLLIElement* newListItem = HTMLLIElement::create(document(
)); |
| 1389 insertNodeAfter(newListItem, enclosingBlockElement, editingS
tate); | 1389 insertNodeAfter(newListItem, enclosingBlockElement, editingS
tate); |
| 1390 if (editingState->isAborted()) | 1390 if (editingState->isAborted()) |
| 1391 return; | 1391 return; |
| 1392 setEndingSelection(VisiblePosition::firstPositionInNode(newL
istItem)); | 1392 setEndingSelection(VisiblePosition::firstPositionInNode(newL
istItem)); |
| 1393 } else { | 1393 } else { |
| 1394 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph | 1394 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph |
| 1395 // block's style seems to annoy users. | 1395 // block's style seems to annoy users. |
| 1396 insertParagraphSeparator(editingState, true, !startIsInsideM
ailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(
), | 1396 insertParagraphSeparator(editingState, true, !startIsInsideM
ailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(
), |
| 1397 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); | 1397 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); |
| 1398 if (editingState->isAborted()) | 1398 if (editingState->isAborted()) |
| 1399 return; | 1399 return; |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 // Select up to the paragraph separator that was added. | 1402 // Select up to the paragraph separator that was added. |
| 1403 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); | 1403 lastPositionToSelect = endingSelection().visibleStartDeprecated(
).deepEquivalent(); |
| 1404 updateNodesInserted(lastPositionToSelect.anchorNode()); | 1404 updateNodesInserted(lastPositionToSelect.anchorNode()); |
| 1405 } | 1405 } |
| 1406 } else { | 1406 } else { |
| 1407 // Select up to the beginning of the next paragraph. | 1407 // Select up to the beginning of the next paragraph. |
| 1408 lastPositionToSelect = mostForwardCaretPosition(next.deepEquivalent(
)); | 1408 lastPositionToSelect = mostForwardCaretPosition(next.deepEquivalent(
)); |
| 1409 } | 1409 } |
| 1410 } else { | 1410 } else { |
| 1411 mergeEndIfNeeded(editingState); | 1411 mergeEndIfNeeded(editingState); |
| 1412 if (editingState->isAborted()) | 1412 if (editingState->isAborted()) |
| 1413 return; | 1413 return; |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 visitor->trace(m_startOfInsertedContent); | 1760 visitor->trace(m_startOfInsertedContent); |
| 1761 visitor->trace(m_endOfInsertedContent); | 1761 visitor->trace(m_endOfInsertedContent); |
| 1762 visitor->trace(m_insertionStyle); | 1762 visitor->trace(m_insertionStyle); |
| 1763 visitor->trace(m_documentFragment); | 1763 visitor->trace(m_documentFragment); |
| 1764 visitor->trace(m_startOfInsertedRange); | 1764 visitor->trace(m_startOfInsertedRange); |
| 1765 visitor->trace(m_endOfInsertedRange); | 1765 visitor->trace(m_endOfInsertedRange); |
| 1766 CompositeEditCommand::trace(visitor); | 1766 CompositeEditCommand::trace(visitor); |
| 1767 } | 1767 } |
| 1768 | 1768 |
| 1769 } // namespace blink | 1769 } // namespace blink |
| OLD | NEW |