OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 } | 192 } |
193 return 0; | 193 return 0; |
194 } | 194 } |
195 | 195 |
196 // FIXME: consolidate with code in previousLinePosition. | 196 // FIXME: consolidate with code in previousLinePosition. |
197 static Position previousRootInlineBoxCandidatePosition(Node* node, const Visible Position& visiblePosition, EditableType editableType) | 197 static Position previousRootInlineBoxCandidatePosition(Node* node, const Visible Position& visiblePosition, EditableType editableType) |
198 { | 198 { |
199 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); | 199 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); |
200 Node* previousNode = previousLeafWithSameEditability(node, editableType); | 200 Node* previousNode = previousLeafWithSameEditability(node, editableType); |
201 | 201 |
202 while (previousNode && (!previousNode->layoutObject() || inSameLine(VisibleP osition(firstPositionInOrBeforeNode(previousNode)), visiblePosition))) | 202 while (previousNode && (!previousNode->layoutObject() || inSameLine(createVi siblePosition(firstPositionInOrBeforeNode(previousNode)), visiblePosition))) |
203 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); | 203 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); |
204 | 204 |
205 while (previousNode && !previousNode->isShadowRoot()) { | 205 while (previousNode && !previousNode->isShadowRoot()) { |
206 if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), edita bleType) != highestRoot) | 206 if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), edita bleType) != highestRoot) |
207 break; | 207 break; |
208 | 208 |
209 Position pos = isHTMLBRElement(*previousNode) ? positionBeforeNode(previ ousNode) : | 209 Position pos = isHTMLBRElement(*previousNode) ? positionBeforeNode(previ ousNode) : |
210 Position::editingPositionOf(previousNode, caretMaxOffset(previousNod e)); | 210 Position::editingPositionOf(previousNode, caretMaxOffset(previousNod e)); |
211 | 211 |
212 if (isVisuallyEquivalentCandidate(pos)) | 212 if (isVisuallyEquivalentCandidate(pos)) |
213 return pos; | 213 return pos; |
214 | 214 |
215 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); | 215 previousNode = previousLeafWithSameEditability(previousNode, editableTyp e); |
216 } | 216 } |
217 return Position(); | 217 return Position(); |
218 } | 218 } |
219 | 219 |
220 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosi tion& visiblePosition, EditableType editableType) | 220 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosi tion& visiblePosition, EditableType editableType) |
221 { | 221 { |
222 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); | 222 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent(), editableType); |
223 Node* nextNode = nextLeafWithSameEditability(node, editableType); | 223 Node* nextNode = nextLeafWithSameEditability(node, editableType); |
224 while (nextNode && (!nextNode->layoutObject() || inSameLine(VisiblePosition( firstPositionInOrBeforeNode(nextNode)), visiblePosition))) | 224 while (nextNode && (!nextNode->layoutObject() || inSameLine(createVisiblePos ition(firstPositionInOrBeforeNode(nextNode)), visiblePosition))) |
225 nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable); | 225 nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable); |
226 | 226 |
227 while (nextNode && !nextNode->isShadowRoot()) { | 227 while (nextNode && !nextNode->isShadowRoot()) { |
228 if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableT ype) != highestRoot) | 228 if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableT ype) != highestRoot) |
229 break; | 229 break; |
230 | 230 |
231 Position pos; | 231 Position pos; |
232 pos = Position::editingPositionOf(nextNode, caretMinOffset(nextNode)); | 232 pos = Position::editingPositionOf(nextNode, caretMinOffset(nextNode)); |
233 | 233 |
234 if (isVisuallyEquivalentCandidate(pos)) | 234 if (isVisuallyEquivalentCandidate(pos)) |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 it.advance(); | 642 it.advance(); |
643 } | 643 } |
644 if (needMoreContext) { | 644 if (needMoreContext) { |
645 // The last search returned the beginning of the buffer and asked for mo re context, | 645 // The last search returned the beginning of the buffer and asked for mo re context, |
646 // but there is no earlier text. Force a search with what's available. | 646 // but there is no earlier text. Force a search with what's available. |
647 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, DontHaveMoreContext, needMoreContext); | 647 next = searchFunction(string.data(), string.size(), string.size() - suff ixLength, DontHaveMoreContext, needMoreContext); |
648 ASSERT(!needMoreContext); | 648 ASSERT(!needMoreContext); |
649 } | 649 } |
650 | 650 |
651 if (!next) | 651 if (!next) |
652 return VisiblePosition(it.atEnd() ? it.startPosition() : pos); | 652 return createVisiblePosition(it.atEnd() ? it.startPosition() : pos); |
653 | 653 |
654 Node* node = it.startContainer(); | 654 Node* node = it.startContainer(); |
655 if (node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset ()) { | 655 if (node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset ()) { |
656 // The next variable contains a usable index into a text node | 656 // The next variable contains a usable index into a text node |
657 return VisiblePosition(Position(node, next)); | 657 return createVisiblePosition(Position(node, next)); |
658 } | 658 } |
659 | 659 |
660 // Use the character iterator to translate the next value into a DOM positio n. | 660 // Use the character iterator to translate the next value into a DOM positio n. |
661 BackwardsCharacterIterator charIt(start, end); | 661 BackwardsCharacterIterator charIt(start, end); |
662 charIt.advance(string.size() - suffixLength - next); | 662 charIt.advance(string.size() - suffixLength - next); |
663 // FIXME: charIt can get out of shadow host. | 663 // FIXME: charIt can get out of shadow host. |
664 return VisiblePosition(charIt.endPosition()); | 664 return createVisiblePosition(charIt.endPosition()); |
665 } | 665 } |
666 | 666 |
667 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc tion searchFunction) | 667 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc tion searchFunction) |
668 { | 668 { |
669 Position pos = c.deepEquivalent(); | 669 Position pos = c.deepEquivalent(); |
670 Node* boundary = parentEditingBoundary(pos); | 670 Node* boundary = parentEditingBoundary(pos); |
671 if (!boundary) | 671 if (!boundary) |
672 return VisiblePosition(); | 672 return VisiblePosition(); |
673 | 673 |
674 Document& d = boundary->document(); | 674 Document& d = boundary->document(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
727 if (it.atEnd() && next == string.size()) { | 727 if (it.atEnd() && next == string.size()) { |
728 pos = it.startPositionInCurrentContainer(); | 728 pos = it.startPositionInCurrentContainer(); |
729 } else if (next != invalidOffset && next != prefixLength) { | 729 } else if (next != invalidOffset && next != prefixLength) { |
730 // Use the character iterator to translate the next value into a DOM pos ition. | 730 // Use the character iterator to translate the next value into a DOM pos ition. |
731 CharacterIterator charIt(searchStart, searchEnd, TextIteratorEmitsCharac tersBetweenAllVisiblePositions); | 731 CharacterIterator charIt(searchStart, searchEnd, TextIteratorEmitsCharac tersBetweenAllVisiblePositions); |
732 charIt.advance(next - prefixLength - 1); | 732 charIt.advance(next - prefixLength - 1); |
733 pos = charIt.endPosition(); | 733 pos = charIt.endPosition(); |
734 | 734 |
735 if (charIt.characterAt(0) == '\n') { | 735 if (charIt.characterAt(0) == '\n') { |
736 // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593) | 736 // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593) |
737 VisiblePosition visPos = VisiblePosition(pos); | 737 VisiblePosition visPos = createVisiblePosition(pos); |
738 if (visPos.deepEquivalent() == VisiblePosition(charIt.startPosition( )).deepEquivalent()) { | 738 if (visPos.deepEquivalent() == createVisiblePosition(charIt.startPos ition()).deepEquivalent()) { |
739 charIt.advance(1); | 739 charIt.advance(1); |
740 pos = charIt.startPosition(); | 740 pos = charIt.startPosition(); |
741 } | 741 } |
742 } | 742 } |
743 } | 743 } |
744 | 744 |
745 // generate VisiblePosition, use TextAffinity::Upstream affinity if possible | 745 // generate VisiblePosition, use TextAffinity::Upstream affinity if possible |
746 return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); | 746 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); |
747 } | 747 } |
748 | 748 |
749 // --------- | 749 // --------- |
750 | 750 |
751 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsi gned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMor eContext) | 751 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsi gned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMor eContext) |
752 { | 752 { |
753 ASSERT(offset); | 753 ASSERT(offset); |
754 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset )) { | 754 if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset )) { |
755 needMoreContext = true; | 755 needMoreContext = true; |
756 return 0; | 756 return 0; |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
965 } else if (endBox->isInlineTextBox() && endNode->isTextNode()) { | 965 } else if (endBox->isInlineTextBox() && endNode->isTextNode()) { |
966 InlineTextBox* endTextBox = toInlineTextBox(endBox); | 966 InlineTextBox* endTextBox = toInlineTextBox(endBox); |
967 int endOffset = endTextBox->start(); | 967 int endOffset = endTextBox->start(); |
968 if (!endTextBox->isLineBreak()) | 968 if (!endTextBox->isLineBreak()) |
969 endOffset += endTextBox->len(); | 969 endOffset += endTextBox->len(); |
970 pos = Position(toText(endNode), endOffset); | 970 pos = Position(toText(endNode), endOffset); |
971 } else { | 971 } else { |
972 pos = positionAfterNode(endNode); | 972 pos = positionAfterNode(endNode); |
973 } | 973 } |
974 | 974 |
975 return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); | 975 return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); |
976 } | 976 } |
977 | 977 |
978 static bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b ) | 978 static bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b ) |
979 { | 979 { |
980 return a.isNotNull() && logicalStartOfLine(a).deepEquivalent() == logicalSta rtOfLine(b).deepEquivalent(); | 980 return a.isNotNull() && logicalStartOfLine(a).deepEquivalent() == logicalSta rtOfLine(b).deepEquivalent(); |
981 } | 981 } |
982 | 982 |
983 static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputati onMode mode) | 983 static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputati onMode mode) |
984 { | 984 { |
985 // TODO: this is the current behavior that might need to be fixed. | 985 // TODO: this is the current behavior that might need to be fixed. |
986 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. | 986 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
987 VisiblePosition visPos = endPositionForLine(c, mode); | 987 VisiblePosition visPos = endPositionForLine(c, mode); |
988 | 988 |
989 if (mode == UseLogicalOrdering) { | 989 if (mode == UseLogicalOrdering) { |
990 // Make sure the end of line is at the same line as the given input posi tion. For a wrapping line, the logical end | 990 // Make sure the end of line is at the same line as the given input posi tion. For a wrapping line, the logical end |
991 // position for the not-last-2-lines might incorrectly hand back the log ical beginning of the next line. | 991 // position for the not-last-2-lines might incorrectly hand back the log ical beginning of the next line. |
992 // For example, <div contenteditable dir="rtl" style="line-break:before- white-space">abcdefg abcdefg abcdefg | 992 // For example, <div contenteditable dir="rtl" style="line-break:before- white-space">abcdefg abcdefg abcdefg |
993 // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abc defg abcdefg </div> | 993 // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abc defg abcdefg </div> |
994 // In this case, use the previous position of the computed logical end p osition. | 994 // In this case, use the previous position of the computed logical end p osition. |
995 if (!inSameLogicalLine(c, visPos)) | 995 if (!inSameLogicalLine(c, visPos)) |
996 visPos = previousPositionOf(visPos); | 996 visPos = previousPositionOf(visPos); |
997 | 997 |
998 if (ContainerNode* editableRoot = highestEditableRoot(c.deepEquivalent() )) { | 998 if (ContainerNode* editableRoot = highestEditableRoot(c.deepEquivalent() )) { |
999 if (!editableRoot->contains(visPos.deepEquivalent().computeContainer Node())) | 999 if (!editableRoot->contains(visPos.deepEquivalent().computeContainer Node())) |
1000 return VisiblePosition(lastPositionInNode(editableRoot)); | 1000 return createVisiblePosition(lastPositionInNode(editableRoot)); |
1001 } | 1001 } |
1002 | 1002 |
1003 return honorEditingBoundaryAtOrAfter(visPos, c.deepEquivalent()); | 1003 return honorEditingBoundaryAtOrAfter(visPos, c.deepEquivalent()); |
1004 } | 1004 } |
1005 | 1005 |
1006 // Make sure the end of line is at the same line as the given input position . Else use the previous position to | 1006 // Make sure the end of line is at the same line as the given input position . Else use the previous position to |
1007 // obtain end of line. This condition happens when the input position is bef ore the space character at the end | 1007 // obtain end of line. This condition happens when the input position is bef ore the space character at the end |
1008 // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position | 1008 // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position |
1009 // in the next line instead. This fix is to account for the discrepancy betw een lines with webkit-line-break:after-white-space style | 1009 // in the next line instead. This fix is to account for the discrepancy betw een lines with webkit-line-break:after-white-space style |
1010 // versus lines without that style, which would break before a space by defa ult. | 1010 // versus lines without that style, which would break before a space by defa ult. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1108 root = box->root().prevRootBox(); | 1108 root = box->root().prevRootBox(); |
1109 // We want to skip zero height boxes. | 1109 // We want to skip zero height boxes. |
1110 // This could happen in case it is a TrailingFloatsRootInlineBox. | 1110 // This could happen in case it is a TrailingFloatsRootInlineBox. |
1111 if (!root || !root->logicalHeight() || !root->firstLeafChild()) | 1111 if (!root || !root->logicalHeight() || !root->firstLeafChild()) |
1112 root = 0; | 1112 root = 0; |
1113 } | 1113 } |
1114 | 1114 |
1115 if (!root) { | 1115 if (!root) { |
1116 Position position = previousRootInlineBoxCandidatePosition(node, visible Position, editableType); | 1116 Position position = previousRootInlineBoxCandidatePosition(node, visible Position, editableType); |
1117 if (position.isNotNull()) { | 1117 if (position.isNotNull()) { |
1118 RenderedPosition renderedPosition((VisiblePosition(position))); | 1118 RenderedPosition renderedPosition((createVisiblePosition(position))) ; |
1119 root = renderedPosition.rootBox(); | 1119 root = renderedPosition.rootBox(); |
1120 if (!root) | 1120 if (!root) |
1121 return VisiblePosition(position); | 1121 return createVisiblePosition(position); |
1122 } | 1122 } |
1123 } | 1123 } |
1124 | 1124 |
1125 if (root) { | 1125 if (root) { |
1126 // FIXME: Can be wrong for multi-column layout and with transforms. | 1126 // FIXME: Can be wrong for multi-column layout and with transforms. |
1127 LayoutPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock( root, lineDirectionPoint); | 1127 LayoutPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock( root, lineDirectionPoint); |
1128 LayoutObject& layoutObject = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->layoutObject(); | 1128 LayoutObject& layoutObject = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->layoutObject(); |
1129 Node* node = layoutObject.node(); | 1129 Node* node = layoutObject.node(); |
1130 if (node && editingIgnoresContent(node)) | 1130 if (node && editingIgnoresContent(node)) |
1131 return VisiblePosition(positionInParentBeforeNode(*node)); | 1131 return createVisiblePosition(positionInParentBeforeNode(*node)); |
1132 return createVisiblePosition(layoutObject.positionForPoint(pointInLine)) ; | 1132 return createVisiblePosition(layoutObject.positionForPoint(pointInLine)) ; |
1133 } | 1133 } |
1134 | 1134 |
1135 // Could not find a previous line. This means we must already be on the firs t line. | 1135 // Could not find a previous line. This means we must already be on the firs t line. |
1136 // Move to the start of the content in this block, which effectively moves u s | 1136 // Move to the start of the content in this block, which effectively moves u s |
1137 // to the start of the line we're on. | 1137 // to the start of the line we're on. |
1138 Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEdit ableElement(editableType) : node->document().documentElement(); | 1138 Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEdit ableElement(editableType) : node->document().documentElement(); |
1139 if (!rootElement) | 1139 if (!rootElement) |
1140 return VisiblePosition(); | 1140 return VisiblePosition(); |
1141 return VisiblePosition(firstPositionInNode(rootElement)); | 1141 return createVisiblePosition(firstPositionInNode(rootElement)); |
1142 } | 1142 } |
1143 | 1143 |
1144 VisiblePosition nextLinePosition(const VisiblePosition& visiblePosition, LayoutU nit lineDirectionPoint, EditableType editableType) | 1144 VisiblePosition nextLinePosition(const VisiblePosition& visiblePosition, LayoutU nit lineDirectionPoint, EditableType editableType) |
1145 { | 1145 { |
1146 Position p = visiblePosition.deepEquivalent(); | 1146 Position p = visiblePosition.deepEquivalent(); |
1147 Node* node = p.anchorNode(); | 1147 Node* node = p.anchorNode(); |
1148 | 1148 |
1149 if (!node) | 1149 if (!node) |
1150 return VisiblePosition(); | 1150 return VisiblePosition(); |
1151 | 1151 |
(...skipping 12 matching lines...) Expand all Loading... | |
1164 if (!root || !root->logicalHeight() || !root->firstLeafChild()) | 1164 if (!root || !root->logicalHeight() || !root->firstLeafChild()) |
1165 root = 0; | 1165 root = 0; |
1166 } | 1166 } |
1167 | 1167 |
1168 if (!root) { | 1168 if (!root) { |
1169 // FIXME: We need do the same in previousLinePosition. | 1169 // FIXME: We need do the same in previousLinePosition. |
1170 Node* child = NodeTraversal::childAt(*node, p.computeEditingOffset()); | 1170 Node* child = NodeTraversal::childAt(*node, p.computeEditingOffset()); |
1171 node = child ? child : &NodeTraversal::lastWithinOrSelf(*node); | 1171 node = child ? child : &NodeTraversal::lastWithinOrSelf(*node); |
1172 Position position = nextRootInlineBoxCandidatePosition(node, visiblePosi tion, editableType); | 1172 Position position = nextRootInlineBoxCandidatePosition(node, visiblePosi tion, editableType); |
1173 if (position.isNotNull()) { | 1173 if (position.isNotNull()) { |
1174 RenderedPosition renderedPosition((VisiblePosition(position))); | 1174 RenderedPosition renderedPosition((createVisiblePosition(position))) ; |
1175 root = renderedPosition.rootBox(); | 1175 root = renderedPosition.rootBox(); |
1176 if (!root) | 1176 if (!root) |
1177 return VisiblePosition(position); | 1177 return createVisiblePosition(position); |
1178 } | 1178 } |
1179 } | 1179 } |
1180 | 1180 |
1181 if (root) { | 1181 if (root) { |
1182 // FIXME: Can be wrong for multi-column layout and with transforms. | 1182 // FIXME: Can be wrong for multi-column layout and with transforms. |
1183 LayoutPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock( root, lineDirectionPoint); | 1183 LayoutPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock( root, lineDirectionPoint); |
1184 LayoutObject& layoutObject = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->layoutObject(); | 1184 LayoutObject& layoutObject = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->layoutObject(); |
1185 Node* node = layoutObject.node(); | 1185 Node* node = layoutObject.node(); |
1186 if (node && editingIgnoresContent(node)) | 1186 if (node && editingIgnoresContent(node)) |
1187 return VisiblePosition(positionInParentBeforeNode(*node)); | 1187 return createVisiblePosition(positionInParentBeforeNode(*node)); |
1188 return createVisiblePosition(layoutObject.positionForPoint(pointInLine)) ; | 1188 return createVisiblePosition(layoutObject.positionForPoint(pointInLine)) ; |
1189 } | 1189 } |
1190 | 1190 |
1191 // Could not find a next line. This means we must already be on the last lin e. | 1191 // Could not find a next line. This means we must already be on the last lin e. |
1192 // Move to the end of the content in this block, which effectively moves us | 1192 // Move to the end of the content in this block, which effectively moves us |
1193 // to the end of the line we're on. | 1193 // to the end of the line we're on. |
1194 Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEdit ableElement(editableType) : node->document().documentElement(); | 1194 Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEdit ableElement(editableType) : node->document().documentElement(); |
1195 if (!rootElement) | 1195 if (!rootElement) |
1196 return VisiblePosition(); | 1196 return VisiblePosition(); |
1197 return VisiblePosition(lastPositionInNode(rootElement)); | 1197 return createVisiblePosition(lastPositionInNode(rootElement)); |
1198 } | 1198 } |
1199 | 1199 |
1200 // --------- | 1200 // --------- |
1201 | 1201 |
1202 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) | 1202 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) |
1203 { | 1203 { |
1204 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); | 1204 TextBreakIterator* iterator = sentenceBreakIterator(characters, length); |
1205 // FIXME: The following function can return -1; we don't handle that. | 1205 // FIXME: The following function can return -1; we don't handle that. |
1206 return iterator->preceding(length); | 1206 return iterator->preceding(length); |
1207 } | 1207 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1253 | 1253 |
1254 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossi ngRule boundaryCrossingRule) | 1254 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossi ngRule boundaryCrossingRule) |
1255 { | 1255 { |
1256 Position p = c.deepEquivalent(); | 1256 Position p = c.deepEquivalent(); |
1257 Node* startNode = p.anchorNode(); | 1257 Node* startNode = p.anchorNode(); |
1258 | 1258 |
1259 if (!startNode) | 1259 if (!startNode) |
1260 return VisiblePosition(); | 1260 return VisiblePosition(); |
1261 | 1261 |
1262 if (isRenderedAsNonInlineTableImageOrHR(startNode)) | 1262 if (isRenderedAsNonInlineTableImageOrHR(startNode)) |
1263 return VisiblePosition(positionBeforeNode(startNode)); | 1263 return createVisiblePosition(positionBeforeNode(startNode)); |
1264 | 1264 |
1265 Element* startBlock = enclosingBlock(startNode); | 1265 Element* startBlock = enclosingBlock(startNode); |
1266 | 1266 |
1267 Node* node = startNode; | 1267 Node* node = startNode; |
1268 ContainerNode* highestRoot = highestEditableRoot(p); | 1268 ContainerNode* highestRoot = highestEditableRoot(p); |
1269 int offset = p.computeEditingOffset(); | 1269 int offset = p.computeEditingOffset(); |
1270 PositionAnchorType type = p.anchorType(); | 1270 PositionAnchorType type = p.anchorType(); |
1271 | 1271 |
1272 Node* n = startNode; | 1272 Node* n = startNode; |
1273 bool startNodeIsEditable = startNode->hasEditableStyle(); | 1273 bool startNodeIsEditable = startNode->hasEditableStyle(); |
(...skipping 24 matching lines...) Expand all Loading... | |
1298 ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode()); | 1298 ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode()); |
1299 type = PositionAnchorType::OffsetInAnchor; | 1299 type = PositionAnchorType::OffsetInAnchor; |
1300 if (style.preserveNewline()) { | 1300 if (style.preserveNewline()) { |
1301 LayoutText* text = toLayoutText(r); | 1301 LayoutText* text = toLayoutText(r); |
1302 int i = text->textLength(); | 1302 int i = text->textLength(); |
1303 int o = offset; | 1303 int o = offset; |
1304 if (n == startNode && o < i) | 1304 if (n == startNode && o < i) |
1305 i = max(0, o); | 1305 i = max(0, o); |
1306 while (--i >= 0) { | 1306 while (--i >= 0) { |
1307 if ((*text)[i] == '\n') | 1307 if ((*text)[i] == '\n') |
1308 return VisiblePosition(Position(toText(n), i + 1)); | 1308 return createVisiblePosition(Position(toText(n), i + 1)) ; |
1309 } | 1309 } |
1310 } | 1310 } |
1311 node = n; | 1311 node = n; |
1312 offset = 0; | 1312 offset = 0; |
1313 n = NodeTraversal::previousPostOrder(*n, startBlock); | 1313 n = NodeTraversal::previousPostOrder(*n, startBlock); |
1314 } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) { | 1314 } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) { |
1315 node = n; | 1315 node = n; |
1316 type = PositionAnchorType::BeforeAnchor; | 1316 type = PositionAnchorType::BeforeAnchor; |
1317 n = n->previousSibling() ? n->previousSibling() : NodeTraversal::pre viousPostOrder(*n, startBlock); | 1317 n = n->previousSibling() ? n->previousSibling() : NodeTraversal::pre viousPostOrder(*n, startBlock); |
1318 } else { | 1318 } else { |
1319 n = NodeTraversal::previousPostOrder(*n, startBlock); | 1319 n = NodeTraversal::previousPostOrder(*n, startBlock); |
1320 } | 1320 } |
1321 } | 1321 } |
1322 | 1322 |
1323 if (type == PositionAnchorType::OffsetInAnchor) | 1323 if (type == PositionAnchorType::OffsetInAnchor) |
1324 return VisiblePosition(Position(node, offset)); | 1324 return createVisiblePosition(Position(node, offset)); |
1325 | 1325 |
1326 return VisiblePosition(Position(node, type)); | 1326 return createVisiblePosition(Position(node, type)); |
1327 } | 1327 } |
1328 | 1328 |
1329 VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossing Rule boundaryCrossingRule) | 1329 VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossing Rule boundaryCrossingRule) |
1330 { | 1330 { |
1331 if (c.isNull()) | 1331 if (c.isNull()) |
1332 return VisiblePosition(); | 1332 return VisiblePosition(); |
1333 | 1333 |
1334 Position p = c.deepEquivalent(); | 1334 Position p = c.deepEquivalent(); |
1335 Node* startNode = p.anchorNode(); | 1335 Node* startNode = p.anchorNode(); |
1336 | 1336 |
1337 if (isRenderedAsNonInlineTableImageOrHR(startNode)) | 1337 if (isRenderedAsNonInlineTableImageOrHR(startNode)) |
1338 return VisiblePosition(positionAfterNode(startNode)); | 1338 return createVisiblePosition(positionAfterNode(startNode)); |
1339 | 1339 |
1340 Element* startBlock = enclosingBlock(startNode); | 1340 Element* startBlock = enclosingBlock(startNode); |
1341 Element* stayInsideBlock = startBlock; | 1341 Element* stayInsideBlock = startBlock; |
1342 | 1342 |
1343 Node* node = startNode; | 1343 Node* node = startNode; |
1344 ContainerNode* highestRoot = highestEditableRoot(p); | 1344 ContainerNode* highestRoot = highestEditableRoot(p); |
1345 int offset = p.computeEditingOffset(); | 1345 int offset = p.computeEditingOffset(); |
1346 PositionAnchorType type = p.anchorType(); | 1346 PositionAnchorType type = p.anchorType(); |
1347 | 1347 |
1348 Node* n = startNode; | 1348 Node* n = startNode; |
(...skipping 25 matching lines...) Expand all Loading... | |
1374 // FIXME: We avoid returning a position where the layoutObject can't acc ept the caret. | 1374 // FIXME: We avoid returning a position where the layoutObject can't acc ept the caret. |
1375 if (r->isText() && toLayoutText(r)->resolvedTextLength()) { | 1375 if (r->isText() && toLayoutText(r)->resolvedTextLength()) { |
1376 ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode()); | 1376 ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode()); |
1377 int length = toLayoutText(r)->textLength(); | 1377 int length = toLayoutText(r)->textLength(); |
1378 type = PositionAnchorType::OffsetInAnchor; | 1378 type = PositionAnchorType::OffsetInAnchor; |
1379 if (style.preserveNewline()) { | 1379 if (style.preserveNewline()) { |
1380 LayoutText* text = toLayoutText(r); | 1380 LayoutText* text = toLayoutText(r); |
1381 int o = n == startNode ? offset : 0; | 1381 int o = n == startNode ? offset : 0; |
1382 for (int i = o; i < length; ++i) { | 1382 for (int i = o; i < length; ++i) { |
1383 if ((*text)[i] == '\n') | 1383 if ((*text)[i] == '\n') |
1384 return VisiblePosition(Position(toText(n), i)); | 1384 return createVisiblePosition(Position(toText(n), i)); |
1385 } | 1385 } |
1386 } | 1386 } |
1387 node = n; | 1387 node = n; |
1388 offset = r->caretMaxOffset(); | 1388 offset = r->caretMaxOffset(); |
1389 n = NodeTraversal::next(*n, stayInsideBlock); | 1389 n = NodeTraversal::next(*n, stayInsideBlock); |
1390 } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) { | 1390 } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) { |
1391 node = n; | 1391 node = n; |
1392 type = PositionAnchorType::AfterAnchor; | 1392 type = PositionAnchorType::AfterAnchor; |
1393 n = NodeTraversal::nextSkippingChildren(*n, stayInsideBlock); | 1393 n = NodeTraversal::nextSkippingChildren(*n, stayInsideBlock); |
1394 } else { | 1394 } else { |
1395 n = NodeTraversal::next(*n, stayInsideBlock); | 1395 n = NodeTraversal::next(*n, stayInsideBlock); |
1396 } | 1396 } |
1397 } | 1397 } |
1398 | 1398 |
1399 if (type == PositionAnchorType::OffsetInAnchor) | 1399 if (type == PositionAnchorType::OffsetInAnchor) |
1400 return VisiblePosition(Position(node, offset)); | 1400 return createVisiblePosition(Position(node, offset)); |
1401 | 1401 |
1402 return VisiblePosition(Position(node, type)); | 1402 return createVisiblePosition(Position(node, type)); |
1403 } | 1403 } |
1404 | 1404 |
1405 // FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true | 1405 // FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true |
1406 VisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition) | 1406 VisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition) |
1407 { | 1407 { |
1408 VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEdit ingBoundary)); | 1408 VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEdit ingBoundary)); |
1409 VisiblePosition afterParagraphEnd(nextPositionOf(paragraphEnd, CannotCrossEd itingBoundary)); | 1409 VisiblePosition afterParagraphEnd(nextPositionOf(paragraphEnd, CannotCrossEd itingBoundary)); |
1410 // The position after the last position in the last cell of a table | 1410 // The position after the last position in the last cell of a table |
1411 // is not the start of the next paragraph. | 1411 // is not the start of the next paragraph. |
1412 if (isFirstPositionAfterTable(afterParagraphEnd)) | 1412 if (isFirstPositionAfterTable(afterParagraphEnd)) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1452 } while (inSameParagraph(p, pos)); | 1452 } while (inSameParagraph(p, pos)); |
1453 return pos; | 1453 return pos; |
1454 } | 1454 } |
1455 | 1455 |
1456 // --------- | 1456 // --------- |
1457 | 1457 |
1458 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoun daryCrossingRule rule) | 1458 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoun daryCrossingRule rule) |
1459 { | 1459 { |
1460 Position position = visiblePosition.deepEquivalent(); | 1460 Position position = visiblePosition.deepEquivalent(); |
1461 Element* startBlock = position.computeContainerNode() ? enclosingBlock(posit ion.computeContainerNode(), rule) : 0; | 1461 Element* startBlock = position.computeContainerNode() ? enclosingBlock(posit ion.computeContainerNode(), rule) : 0; |
1462 return startBlock ? VisiblePosition(firstPositionInNode(startBlock)) : Visib lePosition(); | 1462 return startBlock ? createVisiblePosition(firstPositionInNode(startBlock)) : VisiblePosition(); |
1463 } | 1463 } |
1464 | 1464 |
1465 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBounda ryCrossingRule rule) | 1465 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBounda ryCrossingRule rule) |
1466 { | 1466 { |
1467 Position position = visiblePosition.deepEquivalent(); | 1467 Position position = visiblePosition.deepEquivalent(); |
1468 Element* endBlock = position.computeContainerNode() ? enclosingBlock(positio n.computeContainerNode(), rule) : 0; | 1468 Element* endBlock = position.computeContainerNode() ? enclosingBlock(positio n.computeContainerNode(), rule) : 0; |
1469 return endBlock ? VisiblePosition(lastPositionInNode(endBlock)) : VisiblePos ition(); | 1469 return endBlock ? createVisiblePosition(lastPositionInNode(endBlock)) : Visi blePosition(); |
1470 } | 1470 } |
1471 | 1471 |
1472 bool inSameBlock(const VisiblePosition& a, const VisiblePosition& b) | 1472 bool inSameBlock(const VisiblePosition& a, const VisiblePosition& b) |
1473 { | 1473 { |
1474 return !a.isNull() && enclosingBlock(a.deepEquivalent().computeContainerNode ()) == enclosingBlock(b.deepEquivalent().computeContainerNode()); | 1474 return !a.isNull() && enclosingBlock(a.deepEquivalent().computeContainerNode ()) == enclosingBlock(b.deepEquivalent().computeContainerNode()); |
1475 } | 1475 } |
1476 | 1476 |
1477 bool isStartOfBlock(const VisiblePosition& pos) | 1477 bool isStartOfBlock(const VisiblePosition& pos) |
1478 { | 1478 { |
1479 return pos.isNotNull() && pos.deepEquivalent() == startOfBlock(pos, CanCross EditingBoundary).deepEquivalent(); | 1479 return pos.isNotNull() && pos.deepEquivalent() == startOfBlock(pos, CanCross EditingBoundary).deepEquivalent(); |
1480 } | 1480 } |
1481 | 1481 |
1482 bool isEndOfBlock(const VisiblePosition& pos) | 1482 bool isEndOfBlock(const VisiblePosition& pos) |
1483 { | 1483 { |
1484 return pos.isNotNull() && pos.deepEquivalent() == endOfBlock(pos, CanCrossEd itingBoundary).deepEquivalent(); | 1484 return pos.isNotNull() && pos.deepEquivalent() == endOfBlock(pos, CanCrossEd itingBoundary).deepEquivalent(); |
1485 } | 1485 } |
1486 | 1486 |
1487 // --------- | 1487 // --------- |
1488 | 1488 |
1489 VisiblePosition startOfDocument(const Node* node) | 1489 VisiblePosition startOfDocument(const Node* node) |
1490 { | 1490 { |
1491 if (!node || !node->document().documentElement()) | 1491 if (!node || !node->document().documentElement()) |
1492 return VisiblePosition(); | 1492 return VisiblePosition(); |
1493 | 1493 |
1494 return VisiblePosition(firstPositionInNode(node->document().documentElement( ))); | 1494 return createVisiblePosition(firstPositionInNode(node->document().documentEl ement())); |
1495 } | 1495 } |
1496 | 1496 |
1497 VisiblePosition startOfDocument(const VisiblePosition& c) | 1497 VisiblePosition startOfDocument(const VisiblePosition& c) |
1498 { | 1498 { |
1499 return startOfDocument(c.deepEquivalent().anchorNode()); | 1499 return startOfDocument(c.deepEquivalent().anchorNode()); |
1500 } | 1500 } |
1501 | 1501 |
1502 VisiblePosition endOfDocument(const Node* node) | 1502 VisiblePosition endOfDocument(const Node* node) |
1503 { | 1503 { |
1504 if (!node || !node->document().documentElement()) | 1504 if (!node || !node->document().documentElement()) |
1505 return VisiblePosition(); | 1505 return VisiblePosition(); |
1506 | 1506 |
1507 Element* doc = node->document().documentElement(); | 1507 Element* doc = node->document().documentElement(); |
1508 return VisiblePosition(lastPositionInNode(doc)); | 1508 return createVisiblePosition(lastPositionInNode(doc)); |
1509 } | 1509 } |
1510 | 1510 |
1511 VisiblePosition endOfDocument(const VisiblePosition& c) | 1511 VisiblePosition endOfDocument(const VisiblePosition& c) |
1512 { | 1512 { |
1513 return endOfDocument(c.deepEquivalent().anchorNode()); | 1513 return endOfDocument(c.deepEquivalent().anchorNode()); |
1514 } | 1514 } |
1515 | 1515 |
1516 bool isStartOfDocument(const VisiblePosition& p) | 1516 bool isStartOfDocument(const VisiblePosition& p) |
1517 { | 1517 { |
1518 return p.isNotNull() && previousPositionOf(p, CanCrossEditingBoundary).isNul l(); | 1518 return p.isNotNull() && previousPositionOf(p, CanCrossEditingBoundary).isNul l(); |
1519 } | 1519 } |
1520 | 1520 |
1521 bool isEndOfDocument(const VisiblePosition& p) | 1521 bool isEndOfDocument(const VisiblePosition& p) |
1522 { | 1522 { |
1523 return p.isNotNull() && nextPositionOf(p, CanCrossEditingBoundary).isNull(); | 1523 return p.isNotNull() && nextPositionOf(p, CanCrossEditingBoundary).isNull(); |
1524 } | 1524 } |
1525 | 1525 |
1526 // --------- | 1526 // --------- |
1527 | 1527 |
1528 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition) | 1528 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition) |
1529 { | 1529 { |
1530 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); | 1530 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); |
1531 if (!highestRoot) | 1531 if (!highestRoot) |
1532 return VisiblePosition(); | 1532 return VisiblePosition(); |
1533 | 1533 |
1534 return VisiblePosition(firstPositionInNode(highestRoot)); | 1534 return createVisiblePosition(firstPositionInNode(highestRoot)); |
1535 } | 1535 } |
1536 | 1536 |
1537 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) | 1537 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) |
1538 { | 1538 { |
1539 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); | 1539 ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquival ent()); |
1540 if (!highestRoot) | 1540 if (!highestRoot) |
1541 return VisiblePosition(); | 1541 return VisiblePosition(); |
1542 | 1542 |
1543 return VisiblePosition(lastPositionInNode(highestRoot)); | 1543 return createVisiblePosition(lastPositionInNode(highestRoot)); |
1544 } | 1544 } |
1545 | 1545 |
1546 bool isEndOfEditableOrNonEditableContent(const VisiblePosition& p) | 1546 bool isEndOfEditableOrNonEditableContent(const VisiblePosition& p) |
1547 { | 1547 { |
1548 return p.isNotNull() && nextPositionOf(p).isNull(); | 1548 return p.isNotNull() && nextPositionOf(p).isNull(); |
1549 } | 1549 } |
1550 | 1550 |
1551 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direc tion) | 1551 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direc tion) |
1552 { | 1552 { |
1553 return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c); | 1553 return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1623 int caretOffset = position.computeEditingOffset(); | 1623 int caretOffset = position.computeEditingOffset(); |
1624 Node* const anchorNode = position.anchorNode(); | 1624 Node* const anchorNode = position.anchorNode(); |
1625 LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(ancho rNode)->host()->layoutObject() : anchorNode->layoutObject(); | 1625 LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(ancho rNode)->host()->layoutObject() : anchorNode->layoutObject(); |
1626 | 1626 |
1627 if (!layoutObject->isText()) { | 1627 if (!layoutObject->isText()) { |
1628 inlineBox = 0; | 1628 inlineBox = 0; |
1629 if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlock Flow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { | 1629 if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlock Flow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { |
1630 // Try a visually equivalent position with possibly opposite | 1630 // Try a visually equivalent position with possibly opposite |
1631 // editability. This helps in case |this| is in an editable block | 1631 // editability. This helps in case |this| is in an editable block |
1632 // but surrounded by non-editable positions. It acts to negate the | 1632 // but surrounded by non-editable positions. It acts to negate the |
1633 // logic at the beginning of LayoutObject::createVisiblePosition(). | 1633 // logic at the beginning of LayoutObject::VisiblePosition(). |
tkent
2015/09/01 23:21:17
LayoutObject has neither createVisiblePosition nor
yosin_UTC9
2015/09/02 03:46:20
Good catch. It should be |LayoutObject::createPosi
| |
1634 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo undaries(position); | 1634 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo undaries(position); |
1635 if (equivalent == position) { | 1635 if (equivalent == position) { |
1636 equivalent = upstreamIgnoringEditingBoundaries(position); | 1636 equivalent = upstreamIgnoringEditingBoundaries(position); |
1637 if (equivalent == position || downstreamIgnoringEditingBoundarie s(equivalent) == position) | 1637 if (equivalent == position || downstreamIgnoringEditingBoundarie s(equivalent) == position) |
1638 return InlineBoxPosition(inlineBox, caretOffset); | 1638 return InlineBoxPosition(inlineBox, caretOffset); |
1639 } | 1639 } |
1640 | 1640 |
1641 return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection); | 1641 return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection); |
1642 } | 1642 } |
1643 if (layoutObject->isBox()) { | 1643 if (layoutObject->isBox()) { |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2445 ContainerNode* highestRoot = highestEditableRoot(anchor); | 2445 ContainerNode* highestRoot = highestEditableRoot(anchor); |
2446 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); | 2446 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); |
2447 | 2447 |
2448 // Return |pos| itself if the two are from the very same editable region, or | 2448 // Return |pos| itself if the two are from the very same editable region, or |
2449 // both are non-editable. | 2449 // both are non-editable. |
2450 if (highestRootOfPos == highestRoot) | 2450 if (highestRootOfPos == highestRoot) |
2451 return pos; | 2451 return pos; |
2452 | 2452 |
2453 // If this is not editable but |pos| has an editable root, skip to the end | 2453 // If this is not editable but |pos| has an editable root, skip to the end |
2454 if (!highestRoot && highestRootOfPos) | 2454 if (!highestRoot && highestRootOfPos) |
2455 return VisiblePosition(Position(highestRootOfPos, PositionAnchorType::Af terAnchor).parentAnchoredEquivalent()); | 2455 return createVisiblePosition(Position(highestRootOfPos, PositionAnchorTy pe::AfterAnchor).parentAnchoredEquivalent()); |
2456 | 2456 |
2457 // That must mean that |pos| is not editable. Return the next position after | 2457 // That must mean that |pos| is not editable. Return the next position after |
2458 // |pos| that is in the same editable region as this position | 2458 // |pos| that is in the same editable region as this position |
2459 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); | 2459 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); |
2460 } | 2460 } |
2461 | 2461 |
2462 UChar32 characterAfter(const VisiblePosition& visiblePosition) | 2462 UChar32 characterAfter(const VisiblePosition& visiblePosition) |
2463 { | 2463 { |
2464 // We canonicalize to the first of two equivalent candidates, but the second | 2464 // We canonicalize to the first of two equivalent candidates, but the second |
2465 // of the two candidates is the one that will be inside the text node | 2465 // of the two candidates is the one that will be inside the text node |
(...skipping 13 matching lines...) Expand all Loading... | |
2479 return textNode->data().characterStartingAt(offset); | 2479 return textNode->data().characterStartingAt(offset); |
2480 } | 2480 } |
2481 | 2481 |
2482 UChar32 characterBefore(const VisiblePosition& visiblePosition) | 2482 UChar32 characterBefore(const VisiblePosition& visiblePosition) |
2483 { | 2483 { |
2484 return characterAfter(previousPositionOf(visiblePosition)); | 2484 return characterAfter(previousPositionOf(visiblePosition)); |
2485 } | 2485 } |
2486 | 2486 |
2487 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo undaryCrossingRule rule) | 2487 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo undaryCrossingRule rule) |
2488 { | 2488 { |
2489 VisiblePosition next(nextVisuallyDistinctCandidate(visiblePosition.deepEquiv alent()), visiblePosition.affinity()); | 2489 VisiblePosition next = createVisiblePosition(nextVisuallyDistinctCandidate(v isiblePosition.deepEquivalent()), visiblePosition.affinity()); |
2490 | 2490 |
2491 switch (rule) { | 2491 switch (rule) { |
2492 case CanCrossEditingBoundary: | 2492 case CanCrossEditingBoundary: |
2493 return next; | 2493 return next; |
2494 case CannotCrossEditingBoundary: | 2494 case CannotCrossEditingBoundary: |
2495 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen t()); | 2495 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen t()); |
2496 case CanSkipOverEditingBoundary: | 2496 case CanSkipOverEditingBoundary: |
2497 return skipToEndOfEditingBoundary(next, visiblePosition.deepEquivalent() ); | 2497 return skipToEndOfEditingBoundary(next, visiblePosition.deepEquivalent() ); |
2498 } | 2498 } |
2499 ASSERT_NOT_REACHED(); | 2499 ASSERT_NOT_REACHED(); |
2500 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalent()) ; | 2500 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalent()) ; |
2501 } | 2501 } |
2502 | 2502 |
2503 static VisiblePosition skipToStartOfEditingBoundary(const VisiblePosition& pos, const Position& anchor) | 2503 static VisiblePosition skipToStartOfEditingBoundary(const VisiblePosition& pos, const Position& anchor) |
2504 { | 2504 { |
2505 if (pos.isNull()) | 2505 if (pos.isNull()) |
2506 return pos; | 2506 return pos; |
2507 | 2507 |
2508 ContainerNode* highestRoot = highestEditableRoot(anchor); | 2508 ContainerNode* highestRoot = highestEditableRoot(anchor); |
2509 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); | 2509 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); |
2510 | 2510 |
2511 // Return |pos| itself if the two are from the very same editable region, or | 2511 // Return |pos| itself if the two are from the very same editable region, or |
2512 // both are non-editable. | 2512 // both are non-editable. |
2513 if (highestRootOfPos == highestRoot) | 2513 if (highestRootOfPos == highestRoot) |
2514 return pos; | 2514 return pos; |
2515 | 2515 |
2516 // If this is not editable but |pos| has an editable root, skip to the start | 2516 // If this is not editable but |pos| has an editable root, skip to the start |
2517 if (!highestRoot && highestRootOfPos) | 2517 if (!highestRoot && highestRootOfPos) |
2518 return VisiblePosition(previousVisuallyDistinctCandidate(Position(highes tRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent())); | 2518 return createVisiblePosition(previousVisuallyDistinctCandidate(Position( highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent())) ; |
2519 | 2519 |
2520 // That must mean that |pos| is not editable. Return the last position | 2520 // That must mean that |pos| is not editable. Return the last position |
2521 // before |pos| that is in the same editable region as this position | 2521 // before |pos| that is in the same editable region as this position |
2522 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot); | 2522 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot); |
2523 } | 2523 } |
2524 | 2524 |
2525 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi ngBoundaryCrossingRule rule) | 2525 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi ngBoundaryCrossingRule rule) |
2526 { | 2526 { |
2527 Position pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquival ent()); | 2527 Position pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquival ent()); |
2528 | 2528 |
2529 // return null visible position if there is no previous visible position | 2529 // return null visible position if there is no previous visible position |
2530 if (pos.atStartOfTree()) | 2530 if (pos.atStartOfTree()) |
2531 return VisiblePosition(); | 2531 return VisiblePosition(); |
2532 | 2532 |
2533 VisiblePosition prev = VisiblePosition(pos); | 2533 VisiblePosition prev = createVisiblePosition(pos); |
2534 ASSERT(prev.deepEquivalent() != visiblePosition.deepEquivalent()); | 2534 ASSERT(prev.deepEquivalent() != visiblePosition.deepEquivalent()); |
2535 | 2535 |
2536 #if ENABLE(ASSERT) | 2536 #if ENABLE(ASSERT) |
2537 // we should always be able to make the affinity |TextAffinity::Downstream|, | 2537 // we should always be able to make the affinity |TextAffinity::Downstream|, |
2538 // because going previous from an |TextAffinity::Upstream| position can | 2538 // because going previous from an |TextAffinity::Upstream| position can |
2539 // never yield another |TextAffinity::Upstream position| (unless line wrap | 2539 // never yield another |TextAffinity::Upstream position| (unless line wrap |
2540 // length is 0!). | 2540 // length is 0!). |
2541 if (prev.isNotNull() && visiblePosition.affinity() == TextAffinity::Upstream ) { | 2541 if (prev.isNotNull() && visiblePosition.affinity() == TextAffinity::Upstream ) { |
2542 ASSERT(inSameLine(PositionWithAffinity(prev.deepEquivalent()), PositionW ithAffinity(prev.deepEquivalent(), TextAffinity::Upstream))); | 2542 ASSERT(inSameLine(PositionWithAffinity(prev.deepEquivalent()), PositionW ithAffinity(prev.deepEquivalent(), TextAffinity::Upstream))); |
2543 } | 2543 } |
2544 #endif | 2544 #endif |
2545 | 2545 |
2546 switch (rule) { | 2546 switch (rule) { |
2547 case CanCrossEditingBoundary: | 2547 case CanCrossEditingBoundary: |
2548 return prev; | 2548 return prev; |
2549 case CannotCrossEditingBoundary: | 2549 case CannotCrossEditingBoundary: |
2550 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale nt()); | 2550 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale nt()); |
2551 case CanSkipOverEditingBoundary: | 2551 case CanSkipOverEditingBoundary: |
2552 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent ()); | 2552 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent ()); |
2553 } | 2553 } |
2554 | 2554 |
2555 ASSERT_NOT_REACHED(); | 2555 ASSERT_NOT_REACHED(); |
2556 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent() ); | 2556 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent() ); |
2557 } | 2557 } |
2558 | 2558 |
2559 } // namespace blink | 2559 } // namespace blink |
OLD | NEW |