| 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 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 upstream--; | 663 upstream--; |
| 664 | 664 |
| 665 int downstream = endOffset; | 665 int downstream = endOffset; |
| 666 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) | 666 while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]
)) |
| 667 downstream++; | 667 downstream++; |
| 668 | 668 |
| 669 int length = downstream - upstream; | 669 int length = downstream - upstream; |
| 670 if (!length) | 670 if (!length) |
| 671 return; | 671 return; |
| 672 | 672 |
| 673 VisiblePosition visibleUpstreamPos(Position(textNode, upstream)); | 673 VisiblePosition visibleUpstreamPos = createVisiblePosition(Position(textNode
, upstream)); |
| 674 VisiblePosition visibleDownstreamPos(Position(textNode, downstream)); | 674 VisiblePosition visibleDownstreamPos = createVisiblePosition(Position(textNo
de, downstream)); |
| 675 | 675 |
| 676 String string = text.substring(upstream, length); | 676 String string = text.substring(upstream, length); |
| 677 String rebalancedString = stringWithRebalancedWhitespace(string, | 677 String rebalancedString = stringWithRebalancedWhitespace(string, |
| 678 // FIXME: Because of the problem mentioned at the top of this function, we | 678 // FIXME: Because of the problem mentioned at the top of this function, we |
| 679 // must also use nbsps at the start/end of the string because this function | 679 // must also use nbsps at the start/end of the string because this function |
| 680 // doesn't get all surrounding whitespace, just the whitespace in the | 680 // doesn't get all surrounding whitespace, just the whitespace in the |
| 681 // current text node. | 681 // current text node. |
| 682 isStartOfParagraph(visibleUpstreamPos) || upstream == 0, | 682 isStartOfParagraph(visibleUpstreamPos) || upstream == 0, |
| 683 isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.l
ength()); | 683 isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.l
ength()); |
| 684 | 684 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 697 return; | 697 return; |
| 698 LayoutText* layoutText = textNode->layoutObject(); | 698 LayoutText* layoutText = textNode->layoutObject(); |
| 699 if (layoutText && !layoutText->style()->collapseWhiteSpace()) | 699 if (layoutText && !layoutText->style()->collapseWhiteSpace()) |
| 700 return; | 700 return; |
| 701 | 701 |
| 702 // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it
. | 702 // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it
. |
| 703 Position upstreamPos = mostBackwardCaretPosition(position); | 703 Position upstreamPos = mostBackwardCaretPosition(position); |
| 704 deleteInsignificantText(upstreamPos, mostForwardCaretPosition(position)); | 704 deleteInsignificantText(upstreamPos, mostForwardCaretPosition(position)); |
| 705 position = mostForwardCaretPosition(upstreamPos); | 705 position = mostForwardCaretPosition(upstreamPos); |
| 706 | 706 |
| 707 VisiblePosition visiblePos(position); | 707 VisiblePosition visiblePos = createVisiblePosition(position); |
| 708 VisiblePosition previousVisiblePos(previousPositionOf(visiblePos)); | 708 VisiblePosition previousVisiblePos = previousPositionOf(visiblePos); |
| 709 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos)
; | 709 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos)
; |
| 710 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos); | 710 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos); |
| 711 } | 711 } |
| 712 | 712 |
| 713 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee
ded(const VisiblePosition& visiblePosition) | 713 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee
ded(const VisiblePosition& visiblePosition) |
| 714 { | 714 { |
| 715 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) | 715 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) |
| 716 return; | 716 return; |
| 717 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); | 717 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); |
| 718 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode()
) | 718 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode()
) |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 for (const auto& node : nodes) { | 831 for (const auto& node : nodes) { |
| 832 Text* textNode = node.get(); | 832 Text* textNode = node.get(); |
| 833 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; | 833 int startOffset = textNode == start.anchorNode() ? start.computeOffsetIn
ContainerNode() : 0; |
| 834 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); | 834 int endOffset = textNode == end.anchorNode() ? end.computeOffsetInContai
nerNode() : static_cast<int>(textNode->length()); |
| 835 deleteInsignificantText(textNode, startOffset, endOffset); | 835 deleteInsignificantText(textNode, startOffset, endOffset); |
| 836 } | 836 } |
| 837 } | 837 } |
| 838 | 838 |
| 839 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 839 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
| 840 { | 840 { |
| 841 Position end = mostForwardCaretPosition(nextPositionOf(VisiblePosition(pos,
VP_DEFAULT_AFFINITY)).deepEquivalent()); | 841 Position end = mostForwardCaretPosition(nextPositionOf(createVisiblePosition
(pos, VP_DEFAULT_AFFINITY)).deepEquivalent()); |
| 842 deleteInsignificantText(pos, end); | 842 deleteInsignificantText(pos, end); |
| 843 } | 843 } |
| 844 | 844 |
| 845 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlacehold
er(PassRefPtrWillBeRawPtr<Element> container) | 845 PassRefPtrWillBeRawPtr<HTMLBRElement> CompositeEditCommand::appendBlockPlacehold
er(PassRefPtrWillBeRawPtr<Element> container) |
| 846 { | 846 { |
| 847 if (!container) | 847 if (!container) |
| 848 return nullptr; | 848 return nullptr; |
| 849 | 849 |
| 850 document().updateLayoutIgnorePendingStylesheets(); | 850 document().updateLayoutIgnorePendingStylesheets(); |
| 851 | 851 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 } | 913 } |
| 914 | 914 |
| 915 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 915 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 916 // it, and return that block. Otherwise return 0. | 916 // it, and return that block. Otherwise return 0. |
| 917 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsT
oNewBlockIfNecessary(const Position& pos) | 917 PassRefPtrWillBeRawPtr<HTMLElement> CompositeEditCommand::moveParagraphContentsT
oNewBlockIfNecessary(const Position& pos) |
| 918 { | 918 { |
| 919 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); | 919 ASSERT(isEditablePosition(pos, ContentIsEditable, DoNotUpdateStyle)); |
| 920 | 920 |
| 921 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 921 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 922 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 922 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 923 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); | 923 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; |
| 924 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); | 924 VisiblePosition visibleParagraphStart = startOfParagraph(visiblePos); |
| 925 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 925 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 926 VisiblePosition next = nextPositionOf(visibleParagraphEnd); | 926 VisiblePosition next = nextPositionOf(visibleParagraphEnd); |
| 927 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 927 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| 928 | 928 |
| 929 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); | 929 Position upstreamStart = mostBackwardCaretPosition(visibleParagraphStart.dee
pEquivalent()); |
| 930 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()
); | 930 Position upstreamEnd = mostBackwardCaretPosition(visibleEnd.deepEquivalent()
); |
| 931 | 931 |
| 932 // If there are no VisiblePositions in the same block as pos then | 932 // If there are no VisiblePositions in the same block as pos then |
| 933 // upstreamStart will be outside the paragraph | 933 // upstreamStart will be outside the paragraph |
| 934 if (comparePositions(pos, upstreamStart) < 0) | 934 if (comparePositions(pos, upstreamStart) < 0) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 961 | 961 |
| 962 if (visibleParagraphEnd.isNull()) | 962 if (visibleParagraphEnd.isNull()) |
| 963 return nullptr; | 963 return nullptr; |
| 964 | 964 |
| 965 RefPtrWillBeRawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementA
t(upstreamStart); | 965 RefPtrWillBeRawPtr<HTMLElement> newBlock = insertNewDefaultParagraphElementA
t(upstreamStart); |
| 966 | 966 |
| 967 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); | 967 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().anchor
Node()); |
| 968 | 968 |
| 969 // Inserting default paragraph element can change visible position. We | 969 // Inserting default paragraph element can change visible position. We |
| 970 // should update visible positions before use them. | 970 // should update visible positions before use them. |
| 971 visiblePos = VisiblePosition(pos, VP_DEFAULT_AFFINITY); | 971 visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY); |
| 972 visibleParagraphStart = VisiblePosition(startOfParagraph(visiblePos)); | 972 visibleParagraphStart = startOfParagraph(visiblePos); |
| 973 visibleParagraphEnd = VisiblePosition(endOfParagraph(visiblePos)); | 973 visibleParagraphEnd = endOfParagraph(visiblePos); |
| 974 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f
irstPositionInNode(newBlock.get()))); | 974 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, createVisiblePosi
tion(firstPositionInNode(newBlock.get()))); |
| 975 | 975 |
| 976 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) | 976 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end
WasBr) |
| 977 removeNode(newBlock->lastChild()); | 977 removeNode(newBlock->lastChild()); |
| 978 | 978 |
| 979 return newBlock.release(); | 979 return newBlock.release(); |
| 980 } | 980 } |
| 981 | 981 |
| 982 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode) | 982 void CompositeEditCommand::pushAnchorElementDown(Element* anchorNode) |
| 983 { | 983 { |
| 984 if (!anchorNode) | 984 if (!anchorNode) |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 // future by several other commands such as InsertList and the align commands. | 1124 // future by several other commands such as InsertList and the align commands. |
| 1125 // The blockElement parameter is the element to move the paragraph to, | 1125 // The blockElement parameter is the element to move the paragraph to, |
| 1126 // outerNode is the top element of the paragraph hierarchy. | 1126 // outerNode is the top element of the paragraph hierarchy. |
| 1127 | 1127 |
| 1128 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode) | 1128 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startO
fParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* bloc
kElement, Node* outerNode) |
| 1129 { | 1129 { |
| 1130 ASSERT(outerNode); | 1130 ASSERT(outerNode); |
| 1131 ASSERT(blockElement); | 1131 ASSERT(blockElement); |
| 1132 | 1132 |
| 1133 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; | 1133 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove)
; |
| 1134 VisiblePosition afterParagraph(nextPositionOf(endOfParagraphToMove)); | 1134 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove); |
| 1135 | 1135 |
| 1136 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1136 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1137 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1137 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1138 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1138 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1139 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); | 1139 Position end = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMo
ve.deepEquivalent() ? start : mostBackwardCaretPosition(endOfParagraphToMove.dee
pEquivalent()); |
| 1140 if (comparePositions(start, end) > 0) | 1140 if (comparePositions(start, end) > 0) |
| 1141 end = start; | 1141 end = start; |
| 1142 | 1142 |
| 1143 cloneParagraphUnderNewElement(start, end, outerNode, blockElement); | 1143 cloneParagraphUnderNewElement(start, end, outerNode, blockElement); |
| 1144 | 1144 |
| 1145 setEndingSelection(VisibleSelection(start, end)); | 1145 setEndingSelection(VisibleSelection(start, end)); |
| 1146 deleteSelection(false, false, false); | 1146 deleteSelection(false, false, false); |
| 1147 | 1147 |
| 1148 // There are bugs in deletion when it removes a fully selected table/list. | 1148 // There are bugs in deletion when it removes a fully selected table/list. |
| 1149 // It expands and removes the entire table/list, but will let content | 1149 // It expands and removes the entire table/list, but will let content |
| 1150 // before and after the table/list collapse onto one line. | 1150 // before and after the table/list collapse onto one line. |
| 1151 | 1151 |
| 1152 cleanupAfterDeletion(); | 1152 cleanupAfterDeletion(); |
| 1153 | 1153 |
| 1154 // Add a br if pruning an empty block level element caused a collapse. For
example: | 1154 // Add a br if pruning an empty block level element caused a collapse. For
example: |
| 1155 // foo^ | 1155 // foo^ |
| 1156 // <div>bar</div> | 1156 // <div>bar</div> |
| 1157 // baz | 1157 // baz |
| 1158 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would | 1158 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would |
| 1159 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1159 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1160 // Must recononicalize these two VisiblePositions after the pruning above. | 1160 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1161 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); | 1161 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); |
| 1162 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); | 1162 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); |
| 1163 | 1163 |
| 1164 if (beforeParagraph.isNotNull() && !isRenderedTableElement(beforeParagraph.d
eepEquivalent().anchorNode()) | 1164 if (beforeParagraph.isNotNull() && !isRenderedTableElement(beforeParagraph.d
eepEquivalent().anchorNode()) |
| 1165 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { | 1165 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph.deepEquivalent() == afterParagraph.deepEquivalent())
) { |
| 1166 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1166 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1167 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); | 1167 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); |
| 1168 } | 1168 } |
| 1169 } | 1169 } |
| 1170 | 1170 |
| 1171 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor) | 1171 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor) |
| 1172 { | 1172 { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1199 if (startInParagraph) | 1199 if (startInParagraph) |
| 1200 startIndex = TextIterator::rangeLength(startOfParagraphToMove.to
ParentAnchoredPosition(), visibleStart.toParentAnchoredPosition(), true); | 1200 startIndex = TextIterator::rangeLength(startOfParagraphToMove.to
ParentAnchoredPosition(), visibleStart.toParentAnchoredPosition(), true); |
| 1201 | 1201 |
| 1202 endIndex = 0; | 1202 endIndex = 0; |
| 1203 if (endInParagraph) | 1203 if (endInParagraph) |
| 1204 endIndex = TextIterator::rangeLength(startOfParagraphToMove.toPa
rentAnchoredPosition(), visibleEnd.toParentAnchoredPosition(), true); | 1204 endIndex = TextIterator::rangeLength(startOfParagraphToMove.toPa
rentAnchoredPosition(), visibleEnd.toParentAnchoredPosition(), true); |
| 1205 } | 1205 } |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); | 1208 VisiblePosition beforeParagraph = previousPositionOf(startOfParagraphToMove,
CannotCrossEditingBoundary); |
| 1209 VisiblePosition afterParagraph(nextPositionOf(endOfParagraphToMove, CannotCr
ossEditingBoundary)); | 1209 VisiblePosition afterParagraph = nextPositionOf(endOfParagraphToMove, Cannot
CrossEditingBoundary); |
| 1210 | 1210 |
| 1211 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. | 1211 // We upstream() the end and downstream() the start so that we don't include
collapsed whitespace in the move. |
| 1212 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. | 1212 // When we paste a fragment, spaces after the end and before the start are t
reated as though they were rendered. |
| 1213 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); | 1213 Position start = mostForwardCaretPosition(startOfParagraphToMove.deepEquival
ent()); |
| 1214 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); | 1214 Position end = mostBackwardCaretPosition(endOfParagraphToMove.deepEquivalent
()); |
| 1215 | 1215 |
| 1216 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It | 1216 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It |
| 1217 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. | 1217 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. |
| 1218 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepE
quivalent() != endOfParagraphToMove.deepEquivalent() ? | 1218 RefPtrWillBeRawPtr<DocumentFragment> fragment = startOfParagraphToMove.deepE
quivalent() != endOfParagraphToMove.deepEquivalent() ? |
| 1219 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; | 1219 createFragmentFromMarkup(document(), createMarkup(start.parentAnchoredEq
uivalent(), end.parentAnchoredEquivalent(), DoNotAnnotateForInterchange, Convert
BlocksToInlines::Convert, DoNotResolveURLs, constrainingAncestor), "") : nullptr
; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1239 cleanupAfterDeletion(destination); | 1239 cleanupAfterDeletion(destination); |
| 1240 ASSERT(destination.deepEquivalent().inDocument()); | 1240 ASSERT(destination.deepEquivalent().inDocument()); |
| 1241 | 1241 |
| 1242 // Add a br if pruning an empty block level element caused a collapse. For e
xample: | 1242 // Add a br if pruning an empty block level element caused a collapse. For e
xample: |
| 1243 // foo^ | 1243 // foo^ |
| 1244 // <div>bar</div> | 1244 // <div>bar</div> |
| 1245 // baz | 1245 // baz |
| 1246 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would | 1246 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would |
| 1247 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1247 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1248 // Must recononicalize these two VisiblePositions after the pruning above. | 1248 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1249 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); | 1249 beforeParagraph = createVisiblePosition(beforeParagraph.deepEquivalent()); |
| 1250 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); | 1250 afterParagraph = createVisiblePosition(afterParagraph.deepEquivalent()); |
| 1251 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { | 1251 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph.deepEquivalent() == afterParagraph.deepEquivalent())) { |
| 1252 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1252 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1253 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); | 1253 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); |
| 1254 // Need an updateLayout here in case inserting the br has split a text n
ode. | 1254 // Need an updateLayout here in case inserting the br has split a text n
ode. |
| 1255 document().updateLayoutIgnorePendingStylesheets(); | 1255 document().updateLayoutIgnorePendingStylesheets(); |
| 1256 } | 1256 } |
| 1257 | 1257 |
| 1258 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); | 1258 destinationIndex = TextIterator::rangeLength(firstPositionInNode(document().
documentElement()), destination.toParentAnchoredPosition(), true); |
| 1259 | 1259 |
| 1260 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); | 1260 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 return true; | 1357 return true; |
| 1358 } | 1358 } |
| 1359 | 1359 |
| 1360 // If the caret is in an empty quoted paragraph, and either there is nothing bef
ore that | 1360 // If the caret is in an empty quoted paragraph, and either there is nothing bef
ore that |
| 1361 // paragraph, or what is before is unquoted, and the user presses delete, unquot
e that paragraph. | 1361 // paragraph, or what is before is unquoted, and the user presses delete, unquot
e that paragraph. |
| 1362 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() | 1362 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() |
| 1363 { | 1363 { |
| 1364 if (!endingSelection().isCaret()) | 1364 if (!endingSelection().isCaret()) |
| 1365 return false; | 1365 return false; |
| 1366 | 1366 |
| 1367 VisiblePosition caret(endingSelection().visibleStart()); | 1367 VisiblePosition caret = endingSelection().visibleStart(); |
| 1368 HTMLQuoteElement* highestBlockquote = toHTMLQuoteElement(highestEnclosingNod
eOfType(caret.deepEquivalent(), &isMailHTMLBlockquoteElement)); | 1368 HTMLQuoteElement* highestBlockquote = toHTMLQuoteElement(highestEnclosingNod
eOfType(caret.deepEquivalent(), &isMailHTMLBlockquoteElement)); |
| 1369 if (!highestBlockquote) | 1369 if (!highestBlockquote) |
| 1370 return false; | 1370 return false; |
| 1371 | 1371 |
| 1372 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1372 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1373 return false; | 1373 return false; |
| 1374 | 1374 |
| 1375 VisiblePosition previous(previousPositionOf(caret, CannotCrossEditingBoundar
y)); | 1375 VisiblePosition previous = previousPositionOf(caret, CannotCrossEditingBound
ary); |
| 1376 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1376 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1377 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) | 1377 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailHTMLBlockquoteElem
ent)) |
| 1378 return false; | 1378 return false; |
| 1379 | 1379 |
| 1380 RefPtrWillBeRawPtr<HTMLBRElement> br = createBreakElement(document()); | 1380 RefPtrWillBeRawPtr<HTMLBRElement> br = createBreakElement(document()); |
| 1381 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1381 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1382 // to hold the caret before the highest blockquote. | 1382 // to hold the caret before the highest blockquote. |
| 1383 insertNodeBefore(br, highestBlockquote); | 1383 insertNodeBefore(br, highestBlockquote); |
| 1384 VisiblePosition atBR(positionBeforeNode(br.get())); | 1384 VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get())); |
| 1385 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1385 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1386 // a second one. | 1386 // a second one. |
| 1387 if (!isStartOfParagraph(atBR)) | 1387 if (!isStartOfParagraph(atBR)) |
| 1388 insertNodeBefore(createBreakElement(document()), br); | 1388 insertNodeBefore(createBreakElement(document()), br); |
| 1389 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1389 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1390 | 1390 |
| 1391 // If this is an empty paragraph there must be a line break here. | 1391 // If this is an empty paragraph there must be a line break here. |
| 1392 if (!lineBreakExistsAtVisiblePosition(caret)) | 1392 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1393 return false; | 1393 return false; |
| 1394 | 1394 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1413 | 1413 |
| 1414 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of | 1414 // Operations use this function to avoid inserting content into an anchor when a
t the start or the end of |
| 1415 // that anchor, as in NSTextView. | 1415 // that anchor, as in NSTextView. |
| 1416 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how | 1416 // FIXME: This is only an approximation of NSTextViews insertion behavior, which
varies depending on how |
| 1417 // the caret was made. | 1417 // the caret was made. |
| 1418 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original) | 1418 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi
tion& original) |
| 1419 { | 1419 { |
| 1420 if (original.isNull()) | 1420 if (original.isNull()) |
| 1421 return original; | 1421 return original; |
| 1422 | 1422 |
| 1423 VisiblePosition visiblePos(original); | 1423 VisiblePosition visiblePos = createVisiblePosition(original); |
| 1424 Element* enclosingAnchor = enclosingAnchorElement(original); | 1424 Element* enclosingAnchor = enclosingAnchorElement(original); |
| 1425 Position result = original; | 1425 Position result = original; |
| 1426 | 1426 |
| 1427 if (!enclosingAnchor) | 1427 if (!enclosingAnchor) |
| 1428 return result; | 1428 return result; |
| 1429 | 1429 |
| 1430 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. | 1430 // Don't avoid block level anchors, because that would insert content into t
he wrong paragraph. |
| 1431 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { | 1431 if (enclosingAnchor && !isEnclosingBlock(enclosingAnchor)) { |
| 1432 VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor)); | 1432 VisiblePosition firstInAnchor = createVisiblePosition(firstPositionInNod
e(enclosingAnchor)); |
| 1433 VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor)); | 1433 VisiblePosition lastInAnchor = createVisiblePosition(lastPositionInNode(
enclosingAnchor)); |
| 1434 // If visually just after the anchor, insert *inside* the anchor unless
it's the last | 1434 // If visually just after the anchor, insert *inside* the anchor unless
it's the last |
| 1435 // VisiblePosition in the document, to match NSTextView. | 1435 // VisiblePosition in the document, to match NSTextView. |
| 1436 if (visiblePos.deepEquivalent() == lastInAnchor.deepEquivalent()) { | 1436 if (visiblePos.deepEquivalent() == lastInAnchor.deepEquivalent()) { |
| 1437 // Make sure anchors are pushed down before avoiding them so that we
don't | 1437 // Make sure anchors are pushed down before avoiding them so that we
don't |
| 1438 // also avoid structural elements like lists and blocks (5142012). | 1438 // also avoid structural elements like lists and blocks (5142012). |
| 1439 if (original.anchorNode() != enclosingAnchor && original.anchorNode(
)->parentNode() != enclosingAnchor) { | 1439 if (original.anchorNode() != enclosingAnchor && original.anchorNode(
)->parentNode() != enclosingAnchor) { |
| 1440 pushAnchorElementDown(enclosingAnchor); | 1440 pushAnchorElementDown(enclosingAnchor); |
| 1441 enclosingAnchor = enclosingAnchorElement(original); | 1441 enclosingAnchor = enclosingAnchorElement(original); |
| 1442 if (!enclosingAnchor) | 1442 if (!enclosingAnchor) |
| 1443 return original; | 1443 return original; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 if (!start->isDescendantOf(end)) | 1485 if (!start->isDescendantOf(end)) |
| 1486 return end; | 1486 return end; |
| 1487 | 1487 |
| 1488 RefPtrWillBeRawPtr<Node> endNode = end; | 1488 RefPtrWillBeRawPtr<Node> endNode = end; |
| 1489 RefPtrWillBeRawPtr<Node> node = nullptr; | 1489 RefPtrWillBeRawPtr<Node> node = nullptr; |
| 1490 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ | 1490 for (node = start; node->parentNode() != endNode; node = node->parentNode())
{ |
| 1491 Element* parentElement = node->parentElement(); | 1491 Element* parentElement = node->parentElement(); |
| 1492 if (!parentElement) | 1492 if (!parentElement) |
| 1493 break; | 1493 break; |
| 1494 // Do not split a node when doing so introduces an empty node. | 1494 // Do not split a node when doing so introduces an empty node. |
| 1495 VisiblePosition positionInParent(firstPositionInNode(parentElement)); | 1495 VisiblePosition positionInParent = createVisiblePosition(firstPositionIn
Node(parentElement)); |
| 1496 VisiblePosition positionInNode(firstPositionInOrBeforeNode(node.get())); | 1496 VisiblePosition positionInNode = createVisiblePosition(firstPositionInOr
BeforeNode(node.get())); |
| 1497 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) | 1497 if (positionInParent.deepEquivalent() != positionInNode.deepEquivalent()
) |
| 1498 splitElement(parentElement, node); | 1498 splitElement(parentElement, node); |
| 1499 } | 1499 } |
| 1500 | 1500 |
| 1501 return node.release(); | 1501 return node.release(); |
| 1502 } | 1502 } |
| 1503 | 1503 |
| 1504 DEFINE_TRACE(CompositeEditCommand) | 1504 DEFINE_TRACE(CompositeEditCommand) |
| 1505 { | 1505 { |
| 1506 visitor->trace(m_commands); | 1506 visitor->trace(m_commands); |
| 1507 visitor->trace(m_composition); | 1507 visitor->trace(m_composition); |
| 1508 EditCommand::trace(visitor); | 1508 EditCommand::trace(visitor); |
| 1509 } | 1509 } |
| 1510 | 1510 |
| 1511 } // namespace blink | 1511 } // namespace blink |
| OLD | NEW |