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 |