Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 upstream--; | 849 upstream--; |
| 850 | 850 |
| 851 int downstream = endOffset; | 851 int downstream = endOffset; |
| 852 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream])) | 852 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream])) |
| 853 downstream++; | 853 downstream++; |
| 854 | 854 |
| 855 int length = downstream - upstream; | 855 int length = downstream - upstream; |
| 856 if (!length) | 856 if (!length) |
| 857 return; | 857 return; |
| 858 | 858 |
| 859 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 859 VisiblePosition visibleUpstreamPos = | 860 VisiblePosition visibleUpstreamPos = |
|
yosin_UTC9
2016/10/12 02:12:06
BTW, should we replace |VisiblePosition| to |const
Xiaocheng
2016/10/12 02:15:54
Do you mean a global s/VisiblePosition/const Visib
| |
| 860 createVisiblePositionDeprecated(Position(textNode, upstream)); | 861 createVisiblePosition(Position(textNode, upstream)); |
| 861 VisiblePosition visibleDownstreamPos = | 862 VisiblePosition visibleDownstreamPos = |
| 862 createVisiblePositionDeprecated(Position(textNode, downstream)); | 863 createVisiblePosition(Position(textNode, downstream)); |
| 863 | 864 |
| 864 String string = text.substring(upstream, length); | 865 String string = text.substring(upstream, length); |
| 865 // FIXME: Because of the problem mentioned at the top of this function, we | 866 // FIXME: Because of the problem mentioned at the top of this function, we |
| 866 // must also use nbsps at the start/end of the string because this function | 867 // must also use nbsps at the start/end of the string because this function |
| 867 // doesn't get all surrounding whitespace, just the whitespace in the | 868 // doesn't get all surrounding whitespace, just the whitespace in the |
| 868 // current text node. However, if the next sibling node is a text node | 869 // current text node. However, if the next sibling node is a text node |
| 869 // (not empty, see http://crbug.com/632300), we should use a plain space. | 870 // (not empty, see http://crbug.com/632300), we should use a plain space. |
| 870 // See http://crbug.com/310149 | 871 // See http://crbug.com/310149 |
| 871 const bool nextSiblingIsTextNode = | 872 const bool nextSiblingIsTextNode = |
| 872 textNode->nextSibling() && textNode->nextSibling()->isTextNode() && | 873 textNode->nextSibling() && textNode->nextSibling()->isTextNode() && |
| 873 toText(textNode->nextSibling())->data().length(); | 874 toText(textNode->nextSibling())->data().length(); |
| 874 const bool shouldEmitNBSPbeforeEnd = | 875 const bool shouldEmitNBSPbeforeEnd = |
| 875 (isEndOfParagraphDeprecated(visibleDownstreamPos) || | 876 (isEndOfParagraph(visibleDownstreamPos) || |
| 876 (unsigned)downstream == text.length()) && | 877 (unsigned)downstream == text.length()) && |
| 877 !nextSiblingIsTextNode; | 878 !nextSiblingIsTextNode; |
| 878 String rebalancedString = stringWithRebalancedWhitespace( | 879 String rebalancedString = stringWithRebalancedWhitespace( |
| 879 string, isStartOfParagraphDeprecated(visibleUpstreamPos) || !upstream, | 880 string, isStartOfParagraph(visibleUpstreamPos) || !upstream, |
| 880 shouldEmitNBSPbeforeEnd); | 881 shouldEmitNBSPbeforeEnd); |
| 881 | 882 |
| 882 if (string != rebalancedString) | 883 if (string != rebalancedString) |
| 883 replaceTextInNodePreservingMarkers(textNode, upstream, length, | 884 replaceTextInNodePreservingMarkers(textNode, upstream, length, |
| 884 rebalancedString); | 885 rebalancedString); |
| 885 } | 886 } |
| 886 | 887 |
| 887 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit( | 888 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit( |
| 888 Position& position) { | 889 Position& position) { |
| 889 if (!isRichlyEditablePosition(position)) | 890 if (!isRichlyEditablePosition(position)) |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1046 : 0; | 1047 : 0; |
| 1047 int endOffset = textNode == end.anchorNode() | 1048 int endOffset = textNode == end.anchorNode() |
| 1048 ? end.computeOffsetInContainerNode() | 1049 ? end.computeOffsetInContainerNode() |
| 1049 : static_cast<int>(textNode->length()); | 1050 : static_cast<int>(textNode->length()); |
| 1050 deleteInsignificantText(textNode, startOffset, endOffset); | 1051 deleteInsignificantText(textNode, startOffset, endOffset); |
| 1051 } | 1052 } |
| 1052 } | 1053 } |
| 1053 | 1054 |
| 1054 void CompositeEditCommand::deleteInsignificantTextDownstream( | 1055 void CompositeEditCommand::deleteInsignificantTextDownstream( |
| 1055 const Position& pos) { | 1056 const Position& pos) { |
| 1057 DCHECK(!document().needsLayoutTreeUpdate()); | |
| 1056 Position end = mostForwardCaretPosition( | 1058 Position end = mostForwardCaretPosition( |
| 1057 nextPositionOf(createVisiblePositionDeprecated(pos, VP_DEFAULT_AFFINITY)) | 1059 nextPositionOf(createVisiblePosition(pos, VP_DEFAULT_AFFINITY)) |
| 1058 .deepEquivalent()); | 1060 .deepEquivalent()); |
| 1059 deleteInsignificantText(pos, end); | 1061 deleteInsignificantText(pos, end); |
| 1060 } | 1062 } |
| 1061 | 1063 |
| 1062 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder( | 1064 HTMLBRElement* CompositeEditCommand::appendBlockPlaceholder( |
| 1063 Element* container, | 1065 Element* container, |
| 1064 EditingState* editingState) { | 1066 EditingState* editingState) { |
| 1065 if (!container) | 1067 if (!container) |
| 1066 return nullptr; | 1068 return nullptr; |
| 1067 | 1069 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1142 if (editingState->isAborted()) | 1144 if (editingState->isAborted()) |
| 1143 return nullptr; | 1145 return nullptr; |
| 1144 return paragraphElement; | 1146 return paragraphElement; |
| 1145 } | 1147 } |
| 1146 | 1148 |
| 1147 // If the paragraph is not entirely within it's own block, create one and move | 1149 // If the paragraph is not entirely within it's own block, create one and move |
| 1148 // the paragraph into it, and return that block. Otherwise return 0. | 1150 // the paragraph into it, and return that block. Otherwise return 0. |
| 1149 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary( | 1151 HTMLElement* CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary( |
| 1150 const Position& pos, | 1152 const Position& pos, |
| 1151 EditingState* editingState) { | 1153 EditingState* editingState) { |
| 1154 DCHECK(!document().needsLayoutTreeUpdate()); | |
| 1152 DCHECK(isEditablePosition(pos)) << pos; | 1155 DCHECK(isEditablePosition(pos)) << pos; |
| 1153 | 1156 |
| 1154 // It's strange that this function is responsible for verifying that pos has | 1157 // It's strange that this function is responsible for verifying that pos has |
| 1155 // not been invalidated by an earlier call to this function. The caller, | 1158 // not been invalidated by an earlier call to this function. The caller, |
| 1156 // applyBlockStyle, should do this. | 1159 // applyBlockStyle, should do this. |
| 1157 VisiblePosition visiblePos = | 1160 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); |
| 1158 createVisiblePositionDeprecated(pos, VP_DEFAULT_AFFINITY); | 1161 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
| 1159 VisiblePosition visibleParagraphStart = | 1162 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 1160 startOfParagraphDeprecated(visiblePos); | |
| 1161 VisiblePosition visibleParagraphEnd = endOfParagraphDeprecated(visiblePos); | |
| 1162 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 1163 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
| 1163 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 1164 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| 1164 | 1165 |
| 1165 Position upstreamStart = | 1166 Position upstreamStart = |
| 1166 mostBackwardCaretPosition(visibleParagraphStart.deepEquivalent()); | 1167 mostBackwardCaretPosition(visibleParagraphStart.deepEquivalent()); |
| 1167 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()); | 1168 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()); |
| 1168 | 1169 |
| 1169 // If there are no VisiblePositions in the same block as pos then | 1170 // If there are no VisiblePositions in the same block as pos then |
| 1170 // upstreamStart will be outside the paragraph | 1171 // upstreamStart will be outside the paragraph |
| 1171 if (comparePositions(pos, upstreamStart) < 0) | 1172 if (comparePositions(pos, upstreamStart) < 0) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 HTMLElement* newBlock = | 1208 HTMLElement* newBlock = |
| 1208 insertNewDefaultParagraphElementAt(upstreamStart, editingState); | 1209 insertNewDefaultParagraphElementAt(upstreamStart, editingState); |
| 1209 if (editingState->isAborted()) | 1210 if (editingState->isAborted()) |
| 1210 return nullptr; | 1211 return nullptr; |
| 1211 | 1212 |
| 1212 bool endWasBr = | 1213 bool endWasBr = |
| 1213 isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchorNode()); | 1214 isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchorNode()); |
| 1214 | 1215 |
| 1215 // Inserting default paragraph element can change visible position. We | 1216 // Inserting default paragraph element can change visible position. We |
| 1216 // should update visible positions before use them. | 1217 // should update visible positions before use them. |
| 1217 visiblePos = createVisiblePositionDeprecated(pos, VP_DEFAULT_AFFINITY); | 1218 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1218 visibleParagraphStart = startOfParagraphDeprecated(visiblePos); | 1219 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); |
| 1219 visibleParagraphEnd = endOfParagraphDeprecated(visiblePos); | 1220 visibleParagraphStart = startOfParagraph(visiblePos); |
| 1221 visibleParagraphEnd = endOfParagraph(visiblePos); | |
| 1220 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, | 1222 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, |
| 1221 VisiblePosition::firstPositionInNode(newBlock), editingState); | 1223 VisiblePosition::firstPositionInNode(newBlock), editingState); |
| 1222 if (editingState->isAborted()) | 1224 if (editingState->isAborted()) |
| 1223 return nullptr; | 1225 return nullptr; |
| 1224 | 1226 |
| 1225 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && | 1227 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && |
| 1226 !endWasBr) { | 1228 !endWasBr) { |
| 1227 removeNode(newBlock->lastChild(), editingState); | 1229 removeNode(newBlock->lastChild(), editingState); |
| 1228 if (editingState->isAborted()) | 1230 if (editingState->isAborted()) |
| 1229 return nullptr; | 1231 return nullptr; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1346 } | 1348 } |
| 1347 | 1349 |
| 1348 // There are bugs in deletion when it removes a fully selected table/list. | 1350 // There are bugs in deletion when it removes a fully selected table/list. |
| 1349 // It expands and removes the entire table/list, but will let content | 1351 // It expands and removes the entire table/list, but will let content |
| 1350 // before and after the table/list collapse onto one line. | 1352 // before and after the table/list collapse onto one line. |
| 1351 // Deleting a paragraph will leave a placeholder. Remove it (and prune | 1353 // Deleting a paragraph will leave a placeholder. Remove it (and prune |
| 1352 // empty or unrendered parents). | 1354 // empty or unrendered parents). |
| 1353 | 1355 |
| 1354 void CompositeEditCommand::cleanupAfterDeletion(EditingState* editingState, | 1356 void CompositeEditCommand::cleanupAfterDeletion(EditingState* editingState, |
| 1355 VisiblePosition destination) { | 1357 VisiblePosition destination) { |
| 1356 VisiblePosition caretAfterDelete = endingSelection().visibleStartDeprecated(); | 1358 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1359 | |
| 1360 VisiblePosition caretAfterDelete = endingSelection().visibleStart(); | |
| 1357 Node* destinationNode = destination.deepEquivalent().anchorNode(); | 1361 Node* destinationNode = destination.deepEquivalent().anchorNode(); |
| 1358 if (caretAfterDelete.deepEquivalent() != destination.deepEquivalent() && | 1362 if (caretAfterDelete.deepEquivalent() != destination.deepEquivalent() && |
| 1359 isStartOfParagraphDeprecated(caretAfterDelete) && | 1363 isStartOfParagraph(caretAfterDelete) && |
| 1360 isEndOfParagraphDeprecated(caretAfterDelete)) { | 1364 isEndOfParagraph(caretAfterDelete)) { |
| 1361 // Note: We want the rightmost candidate. | 1365 // Note: We want the rightmost candidate. |
| 1362 Position position = | 1366 Position position = |
| 1363 mostForwardCaretPosition(caretAfterDelete.deepEquivalent()); | 1367 mostForwardCaretPosition(caretAfterDelete.deepEquivalent()); |
| 1364 Node* node = position.anchorNode(); | 1368 Node* node = position.anchorNode(); |
| 1365 | 1369 |
| 1366 // Bail if we'd remove an ancestor of our destination. | 1370 // Bail if we'd remove an ancestor of our destination. |
| 1367 if (destinationNode && destinationNode->isDescendantOf(node)) | 1371 if (destinationNode && destinationNode->isDescendantOf(node)) |
| 1368 return; | 1372 return; |
| 1369 | 1373 |
| 1370 // Normally deletion will leave a br as a placeholder. | 1374 // Normally deletion will leave a br as a placeholder. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1424 startOfParagraphToMove.deepEquivalent() == | 1428 startOfParagraphToMove.deepEquivalent() == |
| 1425 endOfParagraphToMove.deepEquivalent() | 1429 endOfParagraphToMove.deepEquivalent() |
| 1426 ? start | 1430 ? start |
| 1427 : mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent()); | 1431 : mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent()); |
| 1428 if (comparePositions(start, end) > 0) | 1432 if (comparePositions(start, end) > 0) |
| 1429 end = start; | 1433 end = start; |
| 1430 | 1434 |
| 1431 cloneParagraphUnderNewElement(start, end, outerNode, blockElement, | 1435 cloneParagraphUnderNewElement(start, end, outerNode, blockElement, |
| 1432 editingState); | 1436 editingState); |
| 1433 | 1437 |
| 1434 setEndingSelection(createVisibleSelectionDeprecated(start, end)); | 1438 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1439 | |
| 1440 setEndingSelection(createVisibleSelection(start, end)); | |
| 1435 deleteSelection(editingState, false, false, false); | 1441 deleteSelection(editingState, false, false, false); |
| 1436 if (editingState->isAborted()) | 1442 if (editingState->isAborted()) |
| 1437 return; | 1443 return; |
| 1438 | 1444 |
| 1439 // There are bugs in deletion when it removes a fully selected table/list. | 1445 // There are bugs in deletion when it removes a fully selected table/list. |
| 1440 // It expands and removes the entire table/list, but will let content | 1446 // It expands and removes the entire table/list, but will let content |
| 1441 // before and after the table/list collapse onto one line. | 1447 // before and after the table/list collapse onto one line. |
| 1442 | 1448 |
| 1443 cleanupAfterDeletion(editingState); | 1449 cleanupAfterDeletion(editingState); |
| 1444 if (editingState->isAborted()) | 1450 if (editingState->isAborted()) |
| 1445 return; | 1451 return; |
| 1446 | 1452 |
| 1453 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1454 | |
| 1447 // Add a br if pruning an empty block level element caused a collapse. For | 1455 // Add a br if pruning an empty block level element caused a collapse. For |
| 1448 // example: | 1456 // example: |
| 1449 // foo^ | 1457 // foo^ |
| 1450 // <div>bar</div> | 1458 // <div>bar</div> |
| 1451 // baz | 1459 // baz |
| 1452 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That | 1460 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That |
| 1453 // would cause 'baz' to collapse onto the line with 'foobar' unless we insert | 1461 // would cause 'baz' to collapse onto the line with 'foobar' unless we insert |
| 1454 // a br. Must recononicalize these two VisiblePositions after the pruning | 1462 // a br. Must recononicalize these two VisiblePositions after the pruning |
| 1455 // above. | 1463 // above. |
| 1456 // TODO(yosin): We should abort when |beforeParagraph| is a orphan when | 1464 // TODO(yosin): We should abort when |beforeParagraph| is a orphan when |
| 1457 // we have a sample. | 1465 // we have a sample. |
| 1458 beforeParagraph = | 1466 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); |
| 1459 createVisiblePositionDeprecated(beforeParagraph.deepEquivalent()); | |
| 1460 if (afterParagraph.isOrphan()) { | 1467 if (afterParagraph.isOrphan()) { |
| 1461 editingState->abort(); | 1468 editingState->abort(); |
| 1462 return; | 1469 return; |
| 1463 } | 1470 } |
| 1464 afterParagraph = | 1471 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); |
| 1465 createVisiblePositionDeprecated(afterParagraph.deepEquivalent()); | |
| 1466 | 1472 |
| 1467 if (beforeParagraph.isNotNull() && | 1473 if (beforeParagraph.isNotNull() && |
| 1468 !isDisplayInsideTable(beforeParagraph.deepEquivalent().anchorNode()) && | 1474 !isDisplayInsideTable(beforeParagraph.deepEquivalent().anchorNode()) && |
| 1469 ((!isEndOfParagraphDeprecated(beforeParagraph) && | 1475 ((!isEndOfParagraph(beforeParagraph) && |
| 1470 !isStartOfParagraphDeprecated(beforeParagraph)) || | 1476 !isStartOfParagraph(beforeParagraph)) || |
| 1471 beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1477 beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
| 1472 // FIXME: Trim text between beforeParagraph and afterParagraph if they | 1478 // FIXME: Trim text between beforeParagraph and afterParagraph if they |
| 1473 // aren't equal. | 1479 // aren't equal. |
| 1474 insertNodeAt(HTMLBRElement::create(document()), | 1480 insertNodeAt(HTMLBRElement::create(document()), |
| 1475 beforeParagraph.deepEquivalent(), editingState); | 1481 beforeParagraph.deepEquivalent(), editingState); |
| 1476 } | 1482 } |
| 1477 } | 1483 } |
| 1478 | 1484 |
| 1485 // TODO(xiaochengh): Ensure valid VisiblePositions are passed to this function. | |
| 1479 void CompositeEditCommand::moveParagraph( | 1486 void CompositeEditCommand::moveParagraph( |
| 1480 const VisiblePosition& startOfParagraphToMove, | 1487 const VisiblePosition& startOfParagraphToMove, |
| 1481 const VisiblePosition& endOfParagraphToMove, | 1488 const VisiblePosition& endOfParagraphToMove, |
| 1482 const VisiblePosition& destination, | 1489 const VisiblePosition& destination, |
| 1483 EditingState* editingState, | 1490 EditingState* editingState, |
| 1484 ShouldPreserveSelection shouldPreserveSelection, | 1491 ShouldPreserveSelection shouldPreserveSelection, |
| 1485 ShouldPreserveStyle shouldPreserveStyle, | 1492 ShouldPreserveStyle shouldPreserveStyle, |
| 1486 Node* constrainingAncestor) { | 1493 Node* constrainingAncestor) { |
| 1487 DCHECK(isStartOfParagraphDeprecated(startOfParagraphToMove)) | 1494 DCHECK(isStartOfParagraphDeprecated(startOfParagraphToMove)) |
| 1488 << startOfParagraphToMove; | 1495 << startOfParagraphToMove; |
| 1489 DCHECK(isEndOfParagraphDeprecated(endOfParagraphToMove)) | 1496 DCHECK(isEndOfParagraphDeprecated(endOfParagraphToMove)) |
| 1490 << endOfParagraphToMove; | 1497 << endOfParagraphToMove; |
| 1491 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, | 1498 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, |
| 1492 editingState, shouldPreserveSelection, shouldPreserveStyle, | 1499 editingState, shouldPreserveSelection, shouldPreserveStyle, |
| 1493 constrainingAncestor); | 1500 constrainingAncestor); |
| 1494 } | 1501 } |
| 1495 | 1502 |
| 1503 // TODO(xiaochengh): Ensure valid VisiblePositions are passed to this function, | |
| 1504 // and do proper recalculation after mutations so that they are still valid when | |
| 1505 // being used. | |
| 1496 void CompositeEditCommand::moveParagraphs( | 1506 void CompositeEditCommand::moveParagraphs( |
| 1497 const VisiblePosition& startOfParagraphToMove, | 1507 const VisiblePosition& startOfParagraphToMove, |
| 1498 const VisiblePosition& endOfParagraphToMove, | 1508 const VisiblePosition& endOfParagraphToMove, |
| 1499 const VisiblePosition& destination, | 1509 const VisiblePosition& destination, |
| 1500 EditingState* editingState, | 1510 EditingState* editingState, |
| 1501 ShouldPreserveSelection shouldPreserveSelection, | 1511 ShouldPreserveSelection shouldPreserveSelection, |
| 1502 ShouldPreserveStyle shouldPreserveStyle, | 1512 ShouldPreserveStyle shouldPreserveStyle, |
| 1503 Node* constrainingAncestor) { | 1513 Node* constrainingAncestor) { |
| 1504 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent() || | 1514 if (startOfParagraphToMove.deepEquivalent() == destination.deepEquivalent() || |
| 1505 startOfParagraphToMove.isNull()) | 1515 startOfParagraphToMove.isNull()) |
| 1506 return; | 1516 return; |
| 1507 | 1517 |
| 1518 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1519 | |
| 1508 int startIndex = -1; | 1520 int startIndex = -1; |
| 1509 int endIndex = -1; | 1521 int endIndex = -1; |
| 1510 int destinationIndex = -1; | 1522 int destinationIndex = -1; |
| 1511 bool originalIsDirectional = endingSelection().isDirectional(); | 1523 bool originalIsDirectional = endingSelection().isDirectional(); |
| 1512 if (shouldPreserveSelection == PreserveSelection && | 1524 if (shouldPreserveSelection == PreserveSelection && |
| 1513 !endingSelection().isNone()) { | 1525 !endingSelection().isNone()) { |
| 1514 VisiblePosition visibleStart = endingSelection().visibleStartDeprecated(); | 1526 VisiblePosition visibleStart = endingSelection().visibleStart(); |
| 1515 VisiblePosition visibleEnd = endingSelection().visibleEndDeprecated(); | 1527 VisiblePosition visibleEnd = endingSelection().visibleEnd(); |
| 1516 | 1528 |
| 1517 bool startAfterParagraph = | 1529 bool startAfterParagraph = |
| 1518 comparePositions(visibleStart, endOfParagraphToMove) > 0; | 1530 comparePositions(visibleStart, endOfParagraphToMove) > 0; |
| 1519 bool endBeforeParagraph = | 1531 bool endBeforeParagraph = |
| 1520 comparePositions(visibleEnd, startOfParagraphToMove) < 0; | 1532 comparePositions(visibleEnd, startOfParagraphToMove) < 0; |
| 1521 | 1533 |
| 1522 if (!startAfterParagraph && !endBeforeParagraph) { | 1534 if (!startAfterParagraph && !endBeforeParagraph) { |
| 1523 bool startInParagraph = | 1535 bool startInParagraph = |
| 1524 comparePositions(visibleStart, startOfParagraphToMove) >= 0; | 1536 comparePositions(visibleStart, startOfParagraphToMove) >= 0; |
| 1525 bool endInParagraph = | 1537 bool endInParagraph = |
| 1526 comparePositions(visibleEnd, endOfParagraphToMove) <= 0; | 1538 comparePositions(visibleEnd, endOfParagraphToMove) <= 0; |
| 1527 | 1539 |
| 1528 // TextIterator::rangeLength requires clean layout. | |
| 1529 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1530 | |
| 1531 startIndex = 0; | 1540 startIndex = 0; |
| 1532 if (startInParagraph) | 1541 if (startInParagraph) |
| 1533 startIndex = TextIterator::rangeLength( | 1542 startIndex = TextIterator::rangeLength( |
| 1534 startOfParagraphToMove.toParentAnchoredPosition(), | 1543 startOfParagraphToMove.toParentAnchoredPosition(), |
| 1535 visibleStart.toParentAnchoredPosition(), true); | 1544 visibleStart.toParentAnchoredPosition(), true); |
| 1536 | 1545 |
| 1537 endIndex = 0; | 1546 endIndex = 0; |
| 1538 if (endInParagraph) | 1547 if (endInParagraph) |
| 1539 endIndex = TextIterator::rangeLength( | 1548 endIndex = TextIterator::rangeLength( |
| 1540 startOfParagraphToMove.toParentAnchoredPosition(), | 1549 startOfParagraphToMove.toParentAnchoredPosition(), |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1585 styleInEmptyParagraph = | 1594 styleInEmptyParagraph = |
| 1586 EditingStyle::create(startOfParagraphToMove.deepEquivalent()); | 1595 EditingStyle::create(startOfParagraphToMove.deepEquivalent()); |
| 1587 styleInEmptyParagraph->mergeTypingStyle(&document()); | 1596 styleInEmptyParagraph->mergeTypingStyle(&document()); |
| 1588 // The moved paragraph should assume the block style of the destination. | 1597 // The moved paragraph should assume the block style of the destination. |
| 1589 styleInEmptyParagraph->removeBlockProperties(); | 1598 styleInEmptyParagraph->removeBlockProperties(); |
| 1590 } | 1599 } |
| 1591 | 1600 |
| 1592 // FIXME (5098931): We should add a new insert action | 1601 // FIXME (5098931): We should add a new insert action |
| 1593 // "WebViewInsertActionMoved" and call shouldInsertFragment here. | 1602 // "WebViewInsertActionMoved" and call shouldInsertFragment here. |
| 1594 | 1603 |
| 1595 setEndingSelection(createVisibleSelectionDeprecated(start, end)); | 1604 DCHECK(!document().needsLayoutTreeUpdate()); |
| 1605 | |
| 1606 setEndingSelection(createVisibleSelection(start, end)); | |
| 1596 document() | 1607 document() |
| 1597 .frame() | 1608 .frame() |
| 1598 ->spellChecker() | 1609 ->spellChecker() |
| 1599 .clearMisspellingsAndBadGrammarForMovingParagraphs(endingSelection()); | 1610 .clearMisspellingsAndBadGrammarForMovingParagraphs(endingSelection()); |
| 1600 deleteSelection(editingState, false, false, false); | 1611 deleteSelection(editingState, false, false, false); |
| 1601 if (editingState->isAborted()) | 1612 if (editingState->isAborted()) |
| 1602 return; | 1613 return; |
| 1603 | 1614 |
| 1604 DCHECK(destination.deepEquivalent().isConnected()) << destination; | 1615 DCHECK(destination.deepEquivalent().isConnected()) << destination; |
| 1605 cleanupAfterDeletion(editingState, destination); | 1616 cleanupAfterDeletion(editingState, destination); |
| 1606 if (editingState->isAborted()) | 1617 if (editingState->isAborted()) |
| 1607 return; | 1618 return; |
| 1608 DCHECK(destination.deepEquivalent().isConnected()) << destination; | 1619 DCHECK(destination.deepEquivalent().isConnected()) << destination; |
| 1609 | 1620 |
| 1621 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1622 | |
| 1610 // Add a br if pruning an empty block level element caused a collapse. For | 1623 // Add a br if pruning an empty block level element caused a collapse. For |
| 1611 // example: | 1624 // example: |
| 1612 // foo^ | 1625 // foo^ |
| 1613 // <div>bar</div> | 1626 // <div>bar</div> |
| 1614 // baz | 1627 // baz |
| 1615 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That | 1628 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That |
| 1616 // would cause 'baz' to collapse onto the line with 'foobar' unless we insert | 1629 // would cause 'baz' to collapse onto the line with 'foobar' unless we insert |
| 1617 // a br. Must recononicalize these two VisiblePositions after the pruning | 1630 // a br. Must recononicalize these two VisiblePositions after the pruning |
| 1618 // above. | 1631 // above. |
| 1619 VisiblePosition beforeParagraph = | 1632 VisiblePosition beforeParagraph = |
| 1620 createVisiblePositionDeprecated(beforeParagraphPosition.position()); | 1633 createVisiblePosition(beforeParagraphPosition.position()); |
| 1621 VisiblePosition afterParagraph = | 1634 VisiblePosition afterParagraph = |
| 1622 createVisiblePositionDeprecated(afterParagraphPosition.position()); | 1635 createVisiblePosition(afterParagraphPosition.position()); |
| 1623 if (beforeParagraph.isNotNull() && | 1636 if (beforeParagraph.isNotNull() && |
| 1624 (!isEndOfParagraphDeprecated(beforeParagraph) || | 1637 (!isEndOfParagraph(beforeParagraph) || |
| 1625 beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1638 beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
| 1626 // FIXME: Trim text between beforeParagraph and afterParagraph if they | 1639 // FIXME: Trim text between beforeParagraph and afterParagraph if they |
| 1627 // aren't equal. | 1640 // aren't equal. |
| 1628 insertNodeAt(HTMLBRElement::create(document()), | 1641 insertNodeAt(HTMLBRElement::create(document()), |
| 1629 beforeParagraph.deepEquivalent(), editingState); | 1642 beforeParagraph.deepEquivalent(), editingState); |
| 1630 if (editingState->isAborted()) | 1643 if (editingState->isAborted()) |
| 1631 return; | 1644 return; |
| 1632 // Need an updateLayout here in case inserting the br has split a text node. | 1645 // Need an updateLayout here in case inserting the br has split a text node. |
| 1633 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 1646 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1634 } | 1647 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1649 ReplaceSelectionCommand::SelectReplacement | | 1662 ReplaceSelectionCommand::SelectReplacement | |
| 1650 ReplaceSelectionCommand::MovingParagraph; | 1663 ReplaceSelectionCommand::MovingParagraph; |
| 1651 if (shouldPreserveStyle == DoNotPreserveStyle) | 1664 if (shouldPreserveStyle == DoNotPreserveStyle) |
| 1652 options |= ReplaceSelectionCommand::MatchStyle; | 1665 options |= ReplaceSelectionCommand::MatchStyle; |
| 1653 applyCommandToComposite( | 1666 applyCommandToComposite( |
| 1654 ReplaceSelectionCommand::create(document(), fragment, options), | 1667 ReplaceSelectionCommand::create(document(), fragment, options), |
| 1655 editingState); | 1668 editingState); |
| 1656 if (editingState->isAborted()) | 1669 if (editingState->isAborted()) |
| 1657 return; | 1670 return; |
| 1658 | 1671 |
| 1672 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1673 | |
| 1659 document() | 1674 document() |
| 1660 .frame() | 1675 .frame() |
| 1661 ->spellChecker() | 1676 ->spellChecker() |
| 1662 .markMisspellingsAndBadGrammarForMovingParagraphs(endingSelection()); | 1677 .markMisspellingsAndBadGrammarForMovingParagraphs(endingSelection()); |
| 1663 | 1678 |
| 1664 // If the selection is in an empty paragraph, restore styles from the old | 1679 // If the selection is in an empty paragraph, restore styles from the old |
| 1665 // empty paragraph to the new empty paragraph. | 1680 // empty paragraph to the new empty paragraph. |
| 1666 bool selectionIsEmptyParagraph = | 1681 bool selectionIsEmptyParagraph = |
| 1667 endingSelection().isCaret() && | 1682 endingSelection().isCaret() && |
| 1668 isStartOfParagraphDeprecated( | 1683 isStartOfParagraph(endingSelection().visibleStart()) && |
| 1669 endingSelection().visibleStartDeprecated()) && | 1684 isEndOfParagraph(endingSelection().visibleStart()); |
| 1670 isEndOfParagraphDeprecated(endingSelection().visibleStartDeprecated()); | |
| 1671 if (styleInEmptyParagraph && selectionIsEmptyParagraph) { | 1685 if (styleInEmptyParagraph && selectionIsEmptyParagraph) { |
| 1672 applyStyle(styleInEmptyParagraph, editingState); | 1686 applyStyle(styleInEmptyParagraph, editingState); |
| 1673 if (editingState->isAborted()) | 1687 if (editingState->isAborted()) |
| 1674 return; | 1688 return; |
| 1675 } | 1689 } |
| 1676 | 1690 |
| 1677 if (shouldPreserveSelection == DoNotPreserveSelection || startIndex == -1) | 1691 if (shouldPreserveSelection == DoNotPreserveSelection || startIndex == -1) |
| 1678 return; | 1692 return; |
| 1679 Element* documentElement = document().documentElement(); | 1693 Element* documentElement = document().documentElement(); |
| 1680 if (!documentElement) | 1694 if (!documentElement) |
| 1681 return; | 1695 return; |
| 1682 | 1696 |
| 1683 // We need clean layout in order to compute plain-text ranges below. | 1697 // We need clean layout in order to compute plain-text ranges below. |
| 1684 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 1698 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1685 | 1699 |
| 1686 // Fragment creation (using createMarkup) incorrectly uses regular spaces | 1700 // Fragment creation (using createMarkup) incorrectly uses regular spaces |
| 1687 // instead of nbsps for some spaces that were rendered (11475), which causes | 1701 // instead of nbsps for some spaces that were rendered (11475), which causes |
| 1688 // spaces to be collapsed during the move operation. This results in a call | 1702 // spaces to be collapsed during the move operation. This results in a call |
| 1689 // to rangeFromLocationAndLength with a location past the end of the | 1703 // to rangeFromLocationAndLength with a location past the end of the |
| 1690 // document (which will return null). | 1704 // document (which will return null). |
| 1691 EphemeralRange startRange = PlainTextRange(destinationIndex + startIndex) | 1705 EphemeralRange startRange = PlainTextRange(destinationIndex + startIndex) |
| 1692 .createRangeForSelection(*documentElement); | 1706 .createRangeForSelection(*documentElement); |
| 1693 if (startRange.isNull()) | 1707 if (startRange.isNull()) |
| 1694 return; | 1708 return; |
| 1695 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex) | 1709 EphemeralRange endRange = PlainTextRange(destinationIndex + endIndex) |
| 1696 .createRangeForSelection(*documentElement); | 1710 .createRangeForSelection(*documentElement); |
| 1697 if (endRange.isNull()) | 1711 if (endRange.isNull()) |
| 1698 return; | 1712 return; |
| 1699 setEndingSelection(createVisibleSelectionDeprecated( | 1713 setEndingSelection(createVisibleSelection( |
| 1700 startRange.startPosition(), endRange.startPosition(), | 1714 startRange.startPosition(), endRange.startPosition(), |
| 1701 TextAffinity::Downstream, originalIsDirectional)); | 1715 TextAffinity::Downstream, originalIsDirectional)); |
| 1702 } | 1716 } |
| 1703 | 1717 |
| 1704 // FIXME: Send an appropriate shouldDeleteRange call. | 1718 // FIXME: Send an appropriate shouldDeleteRange call. |
| 1705 bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState) { | 1719 bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState) { |
| 1720 DCHECK(!document().needsLayoutTreeUpdate()); | |
| 1706 Node* emptyListItem = | 1721 Node* emptyListItem = |
| 1707 enclosingEmptyListItem(endingSelection().visibleStartDeprecated()); | 1722 enclosingEmptyListItem(endingSelection().visibleStart()); |
| 1708 if (!emptyListItem) | 1723 if (!emptyListItem) |
| 1709 return false; | 1724 return false; |
| 1710 | 1725 |
| 1711 EditingStyle* style = EditingStyle::create(endingSelection().start()); | 1726 EditingStyle* style = EditingStyle::create(endingSelection().start()); |
| 1712 style->mergeTypingStyle(&document()); | 1727 style->mergeTypingStyle(&document()); |
| 1713 | 1728 |
| 1714 ContainerNode* listNode = emptyListItem->parentNode(); | 1729 ContainerNode* listNode = emptyListItem->parentNode(); |
| 1715 // FIXME: Can't we do something better when the immediate parent wasn't a list | 1730 // FIXME: Can't we do something better when the immediate parent wasn't a list |
| 1716 // node? | 1731 // node? |
| 1717 if (!listNode || | 1732 if (!listNode || |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1790 ? emptyListItem | 1805 ? emptyListItem |
| 1791 : listNode, | 1806 : listNode, |
| 1792 editingState); | 1807 editingState); |
| 1793 if (editingState->isAborted()) | 1808 if (editingState->isAborted()) |
| 1794 return false; | 1809 return false; |
| 1795 } | 1810 } |
| 1796 | 1811 |
| 1797 appendBlockPlaceholder(newBlock, editingState); | 1812 appendBlockPlaceholder(newBlock, editingState); |
| 1798 if (editingState->isAborted()) | 1813 if (editingState->isAborted()) |
| 1799 return false; | 1814 return false; |
| 1800 setEndingSelection(createVisibleSelectionDeprecated( | 1815 |
| 1816 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1817 setEndingSelection(createVisibleSelection( | |
| 1801 Position::firstPositionInNode(newBlock), TextAffinity::Downstream, | 1818 Position::firstPositionInNode(newBlock), TextAffinity::Downstream, |
| 1802 endingSelection().isDirectional())); | 1819 endingSelection().isDirectional())); |
| 1803 | 1820 |
| 1804 style->prepareToApplyAt(endingSelection().start()); | 1821 style->prepareToApplyAt(endingSelection().start()); |
| 1805 if (!style->isEmpty()) { | 1822 if (!style->isEmpty()) { |
| 1806 applyStyle(style, editingState); | 1823 applyStyle(style, editingState); |
| 1807 if (editingState->isAborted()) | 1824 if (editingState->isAborted()) |
| 1808 return false; | 1825 return false; |
| 1809 } | 1826 } |
| 1810 | 1827 |
| 1811 return true; | 1828 return true; |
| 1812 } | 1829 } |
| 1813 | 1830 |
| 1814 // If the caret is in an empty quoted paragraph, and either there is nothing | 1831 // If the caret is in an empty quoted paragraph, and either there is nothing |
| 1815 // before that paragraph, or what is before is unquoted, and the user presses | 1832 // before that paragraph, or what is before is unquoted, and the user presses |
| 1816 // delete, unquote that paragraph. | 1833 // delete, unquote that paragraph. |
| 1817 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph( | 1834 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph( |
| 1818 EditingState* editingState) { | 1835 EditingState* editingState) { |
| 1819 if (!endingSelection().isCaret()) | 1836 if (!endingSelection().isCaret()) |
| 1820 return false; | 1837 return false; |
| 1821 | 1838 |
| 1822 VisiblePosition caret = endingSelection().visibleStartDeprecated(); | 1839 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1840 | |
| 1841 VisiblePosition caret = endingSelection().visibleStart(); | |
| 1823 HTMLQuoteElement* highestBlockquote = | 1842 HTMLQuoteElement* highestBlockquote = |
| 1824 toHTMLQuoteElement(highestEnclosingNodeOfType( | 1843 toHTMLQuoteElement(highestEnclosingNodeOfType( |
| 1825 caret.deepEquivalent(), &isMailHTMLBlockquoteElement)); | 1844 caret.deepEquivalent(), &isMailHTMLBlockquoteElement)); |
| 1826 if (!highestBlockquote) | 1845 if (!highestBlockquote) |
| 1827 return false; | 1846 return false; |
| 1828 | 1847 |
| 1829 if (!isStartOfParagraphDeprecated(caret) || | 1848 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1830 !isEndOfParagraphDeprecated(caret)) | |
| 1831 return false; | 1849 return false; |
| 1832 | 1850 |
| 1833 VisiblePosition previous = | 1851 VisiblePosition previous = |
| 1834 previousPositionOf(caret, CannotCrossEditingBoundary); | 1852 previousPositionOf(caret, CannotCrossEditingBoundary); |
| 1835 // Only move forward if there's nothing before the caret, or if there's | 1853 // Only move forward if there's nothing before the caret, or if there's |
| 1836 // unquoted content before it. | 1854 // unquoted content before it. |
| 1837 if (enclosingNodeOfType(previous.deepEquivalent(), | 1855 if (enclosingNodeOfType(previous.deepEquivalent(), |
| 1838 &isMailHTMLBlockquoteElement)) | 1856 &isMailHTMLBlockquoteElement)) |
| 1839 return false; | 1857 return false; |
| 1840 | 1858 |
| 1841 HTMLBRElement* br = HTMLBRElement::create(document()); | 1859 HTMLBRElement* br = HTMLBRElement::create(document()); |
| 1842 // We want to replace this quoted paragraph with an unquoted one, so insert a | 1860 // We want to replace this quoted paragraph with an unquoted one, so insert a |
| 1843 // br to hold the caret before the highest blockquote. | 1861 // br to hold the caret before the highest blockquote. |
| 1844 insertNodeBefore(br, highestBlockquote, editingState); | 1862 insertNodeBefore(br, highestBlockquote, editingState); |
| 1845 if (editingState->isAborted()) | 1863 if (editingState->isAborted()) |
| 1846 return false; | 1864 return false; |
| 1865 | |
| 1866 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1867 | |
| 1847 VisiblePosition atBR = VisiblePosition::beforeNode(br); | 1868 VisiblePosition atBR = VisiblePosition::beforeNode(br); |
| 1848 // If the br we inserted collapsed, for example: | 1869 // If the br we inserted collapsed, for example: |
| 1849 // foo<br><blockquote>...</blockquote> | 1870 // foo<br><blockquote>...</blockquote> |
| 1850 // insert a second one. | 1871 // insert a second one. |
| 1851 if (!isStartOfParagraphDeprecated(atBR)) { | 1872 if (!isStartOfParagraph(atBR)) { |
| 1852 insertNodeBefore(HTMLBRElement::create(document()), br, editingState); | 1873 insertNodeBefore(HTMLBRElement::create(document()), br, editingState); |
| 1853 if (editingState->isAborted()) | 1874 if (editingState->isAborted()) |
| 1854 return false; | 1875 return false; |
| 1876 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 1855 } | 1877 } |
| 1856 setEndingSelection(createVisibleSelectionDeprecated( | 1878 setEndingSelection(createVisibleSelection(atBR.toPositionWithAffinity(), |
| 1857 atBR, endingSelection().isDirectional())); | 1879 endingSelection().isDirectional())); |
| 1858 | 1880 |
| 1859 // If this is an empty paragraph there must be a line break here. | 1881 // If this is an empty paragraph there must be a line break here. |
| 1860 if (!lineBreakExistsAtVisiblePosition(caret)) | 1882 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1861 return false; | 1883 return false; |
| 1862 | 1884 |
| 1863 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); | 1885 Position caretPos(mostForwardCaretPosition(caret.deepEquivalent())); |
| 1864 // A line break is either a br or a preserved newline. | 1886 // A line break is either a br or a preserved newline. |
| 1865 DCHECK(isHTMLBRElement(caretPos.anchorNode()) || | 1887 DCHECK(isHTMLBRElement(caretPos.anchorNode()) || |
| 1866 (caretPos.anchorNode()->isTextNode() && | 1888 (caretPos.anchorNode()->isTextNode() && |
| 1867 caretPos.anchorNode()->layoutObject()->style()->preserveNewline())) | 1889 caretPos.anchorNode()->layoutObject()->style()->preserveNewline())) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1890 // Operations use this function to avoid inserting content into an anchor when | 1912 // Operations use this function to avoid inserting content into an anchor when |
| 1891 // at the start or the end of that anchor, as in NSTextView. | 1913 // at the start or the end of that anchor, as in NSTextView. |
| 1892 // FIXME: This is only an approximation of NSTextViews insertion behavior, which | 1914 // FIXME: This is only an approximation of NSTextViews insertion behavior, which |
| 1893 // varies depending on how the caret was made. | 1915 // varies depending on how the caret was made. |
| 1894 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary( | 1916 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary( |
| 1895 const Position& original, | 1917 const Position& original, |
| 1896 EditingState* editingState) { | 1918 EditingState* editingState) { |
| 1897 if (original.isNull()) | 1919 if (original.isNull()) |
| 1898 return original; | 1920 return original; |
| 1899 | 1921 |
| 1900 VisiblePosition visiblePos = createVisiblePositionDeprecated(original); | 1922 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1923 VisiblePosition visiblePos = createVisiblePosition(original); | |
| 1901 Element* enclosingAnchor = enclosingAnchorElement(original); | 1924 Element* enclosingAnchor = enclosingAnchorElement(original); |
| 1902 Position result = original; | 1925 Position result = original; |
| 1903 | 1926 |
| 1904 if (!enclosingAnchor) | 1927 if (!enclosingAnchor) |
| 1905 return result; | 1928 return result; |
| 1906 | 1929 |
| 1907 // Don't avoid block level anchors, because that would insert content into the | 1930 // Don't avoid block level anchors, because that would insert content into the |
| 1908 // wrong paragraph. | 1931 // wrong paragraph. |
| 1909 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { | 1932 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { |
| 1910 VisiblePosition firstInAnchor = | 1933 VisiblePosition firstInAnchor = |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1975 end = end->parentNode(); | 1998 end = end->parentNode(); |
| 1976 if (!start->isDescendantOf(end)) | 1999 if (!start->isDescendantOf(end)) |
| 1977 return end; | 2000 return end; |
| 1978 | 2001 |
| 1979 Node* endNode = end; | 2002 Node* endNode = end; |
| 1980 Node* node = nullptr; | 2003 Node* node = nullptr; |
| 1981 for (node = start; node->parentNode() != endNode; node = node->parentNode()) { | 2004 for (node = start; node->parentNode() != endNode; node = node->parentNode()) { |
| 1982 Element* parentElement = node->parentElement(); | 2005 Element* parentElement = node->parentElement(); |
| 1983 if (!parentElement) | 2006 if (!parentElement) |
| 1984 break; | 2007 break; |
| 2008 | |
| 2009 document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 2010 | |
| 1985 // Do not split a node when doing so introduces an empty node. | 2011 // Do not split a node when doing so introduces an empty node. |
| 1986 VisiblePosition positionInParent = | 2012 VisiblePosition positionInParent = |
| 1987 VisiblePosition::firstPositionInNode(parentElement); | 2013 VisiblePosition::firstPositionInNode(parentElement); |
| 1988 VisiblePosition positionInNode = | 2014 VisiblePosition positionInNode = |
| 1989 createVisiblePositionDeprecated(firstPositionInOrBeforeNode(node)); | 2015 createVisiblePosition(firstPositionInOrBeforeNode(node)); |
| 1990 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()) | 2016 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()) |
| 1991 splitElement(parentElement, node); | 2017 splitElement(parentElement, node); |
| 1992 } | 2018 } |
| 1993 | 2019 |
| 1994 return node; | 2020 return node; |
| 1995 } | 2021 } |
| 1996 | 2022 |
| 1997 DEFINE_TRACE(CompositeEditCommand) { | 2023 DEFINE_TRACE(CompositeEditCommand) { |
| 1998 visitor->trace(m_commands); | 2024 visitor->trace(m_commands); |
| 1999 visitor->trace(m_composition); | 2025 visitor->trace(m_composition); |
| 2000 EditCommand::trace(visitor); | 2026 EditCommand::trace(visitor); |
| 2001 } | 2027 } |
| 2002 | 2028 |
| 2003 } // namespace blink | 2029 } // namespace blink |
| OLD | NEW |