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 |
| 1634 // |LayoutObject::createPositionWithAffinity()|. |
1634 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo
undaries(position); | 1635 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo
undaries(position); |
1635 if (equivalent == position) { | 1636 if (equivalent == position) { |
1636 equivalent = upstreamIgnoringEditingBoundaries(position); | 1637 equivalent = upstreamIgnoringEditingBoundaries(position); |
1637 if (equivalent == position || downstreamIgnoringEditingBoundarie
s(equivalent) == position) | 1638 if (equivalent == position || downstreamIgnoringEditingBoundarie
s(equivalent) == position) |
1638 return InlineBoxPosition(inlineBox, caretOffset); | 1639 return InlineBoxPosition(inlineBox, caretOffset); |
1639 } | 1640 } |
1640 | 1641 |
1641 return computeInlineBoxPosition(equivalent, TextAffinity::Upstream,
primaryDirection); | 1642 return computeInlineBoxPosition(equivalent, TextAffinity::Upstream,
primaryDirection); |
1642 } | 1643 } |
1643 if (layoutObject->isBox()) { | 1644 if (layoutObject->isBox()) { |
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2455 ContainerNode* highestRoot = highestEditableRoot(anchor); | 2456 ContainerNode* highestRoot = highestEditableRoot(anchor); |
2456 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); | 2457 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); |
2457 | 2458 |
2458 // Return |pos| itself if the two are from the very same editable region, or | 2459 // Return |pos| itself if the two are from the very same editable region, or |
2459 // both are non-editable. | 2460 // both are non-editable. |
2460 if (highestRootOfPos == highestRoot) | 2461 if (highestRootOfPos == highestRoot) |
2461 return pos; | 2462 return pos; |
2462 | 2463 |
2463 // If this is not editable but |pos| has an editable root, skip to the end | 2464 // If this is not editable but |pos| has an editable root, skip to the end |
2464 if (!highestRoot && highestRootOfPos) | 2465 if (!highestRoot && highestRootOfPos) |
2465 return VisiblePosition(Position(highestRootOfPos, PositionAnchorType::Af
terAnchor).parentAnchoredEquivalent()); | 2466 return createVisiblePosition(Position(highestRootOfPos, PositionAnchorTy
pe::AfterAnchor).parentAnchoredEquivalent()); |
2466 | 2467 |
2467 // That must mean that |pos| is not editable. Return the next position after | 2468 // That must mean that |pos| is not editable. Return the next position after |
2468 // |pos| that is in the same editable region as this position | 2469 // |pos| that is in the same editable region as this position |
2469 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
highestRoot); | 2470 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(),
highestRoot); |
2470 } | 2471 } |
2471 | 2472 |
2472 UChar32 characterAfter(const VisiblePosition& visiblePosition) | 2473 UChar32 characterAfter(const VisiblePosition& visiblePosition) |
2473 { | 2474 { |
2474 // We canonicalize to the first of two equivalent candidates, but the second | 2475 // We canonicalize to the first of two equivalent candidates, but the second |
2475 // of the two candidates is the one that will be inside the text node | 2476 // of the two candidates is the one that will be inside the text node |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2818 return VisiblePosition(); | 2819 return VisiblePosition(); |
2819 | 2820 |
2820 VisiblePosition right = createVisiblePosition(pos); | 2821 VisiblePosition right = createVisiblePosition(pos); |
2821 ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent()); | 2822 ASSERT(right.deepEquivalent() != visiblePosition.deepEquivalent()); |
2822 | 2823 |
2823 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi
ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound
aryAtOrBefore(right, visiblePosition.deepEquivalent()); | 2824 return directionOfEnclosingBlock(right.deepEquivalent()) == LTR ? honorEditi
ngBoundaryAtOrAfter(right, visiblePosition.deepEquivalent()) : honorEditingBound
aryAtOrBefore(right, visiblePosition.deepEquivalent()); |
2824 } | 2825 } |
2825 | 2826 |
2826 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo
undaryCrossingRule rule) | 2827 VisiblePosition nextPositionOf(const VisiblePosition& visiblePosition, EditingBo
undaryCrossingRule rule) |
2827 { | 2828 { |
2828 VisiblePosition next(nextVisuallyDistinctCandidate(visiblePosition.deepEquiv
alent()), visiblePosition.affinity()); | 2829 VisiblePosition next = createVisiblePosition(nextVisuallyDistinctCandidate(v
isiblePosition.deepEquivalent()), visiblePosition.affinity()); |
2829 | 2830 |
2830 switch (rule) { | 2831 switch (rule) { |
2831 case CanCrossEditingBoundary: | 2832 case CanCrossEditingBoundary: |
2832 return next; | 2833 return next; |
2833 case CannotCrossEditingBoundary: | 2834 case CannotCrossEditingBoundary: |
2834 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen
t()); | 2835 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalen
t()); |
2835 case CanSkipOverEditingBoundary: | 2836 case CanSkipOverEditingBoundary: |
2836 return skipToEndOfEditingBoundary(next, visiblePosition.deepEquivalent()
); | 2837 return skipToEndOfEditingBoundary(next, visiblePosition.deepEquivalent()
); |
2837 } | 2838 } |
2838 ASSERT_NOT_REACHED(); | 2839 ASSERT_NOT_REACHED(); |
2839 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalent())
; | 2840 return honorEditingBoundaryAtOrAfter(next, visiblePosition.deepEquivalent())
; |
2840 } | 2841 } |
2841 | 2842 |
2842 static VisiblePosition skipToStartOfEditingBoundary(const VisiblePosition& pos,
const Position& anchor) | 2843 static VisiblePosition skipToStartOfEditingBoundary(const VisiblePosition& pos,
const Position& anchor) |
2843 { | 2844 { |
2844 if (pos.isNull()) | 2845 if (pos.isNull()) |
2845 return pos; | 2846 return pos; |
2846 | 2847 |
2847 ContainerNode* highestRoot = highestEditableRoot(anchor); | 2848 ContainerNode* highestRoot = highestEditableRoot(anchor); |
2848 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); | 2849 ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); |
2849 | 2850 |
2850 // Return |pos| itself if the two are from the very same editable region, or | 2851 // Return |pos| itself if the two are from the very same editable region, or |
2851 // both are non-editable. | 2852 // both are non-editable. |
2852 if (highestRootOfPos == highestRoot) | 2853 if (highestRootOfPos == highestRoot) |
2853 return pos; | 2854 return pos; |
2854 | 2855 |
2855 // If this is not editable but |pos| has an editable root, skip to the start | 2856 // If this is not editable but |pos| has an editable root, skip to the start |
2856 if (!highestRoot && highestRootOfPos) | 2857 if (!highestRoot && highestRootOfPos) |
2857 return VisiblePosition(previousVisuallyDistinctCandidate(Position(highes
tRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent())); | 2858 return createVisiblePosition(previousVisuallyDistinctCandidate(Position(
highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent()))
; |
2858 | 2859 |
2859 // That must mean that |pos| is not editable. Return the last position | 2860 // That must mean that |pos| is not editable. Return the last position |
2860 // before |pos| that is in the same editable region as this position | 2861 // before |pos| that is in the same editable region as this position |
2861 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(),
highestRoot); | 2862 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(),
highestRoot); |
2862 } | 2863 } |
2863 | 2864 |
2864 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi
ngBoundaryCrossingRule rule) | 2865 VisiblePosition previousPositionOf(const VisiblePosition& visiblePosition, Editi
ngBoundaryCrossingRule rule) |
2865 { | 2866 { |
2866 Position pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquival
ent()); | 2867 Position pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquival
ent()); |
2867 | 2868 |
2868 // return null visible position if there is no previous visible position | 2869 // return null visible position if there is no previous visible position |
2869 if (pos.atStartOfTree()) | 2870 if (pos.atStartOfTree()) |
2870 return VisiblePosition(); | 2871 return VisiblePosition(); |
2871 | 2872 |
2872 VisiblePosition prev = VisiblePosition(pos); | 2873 VisiblePosition prev = createVisiblePosition(pos); |
2873 ASSERT(prev.deepEquivalent() != visiblePosition.deepEquivalent()); | 2874 ASSERT(prev.deepEquivalent() != visiblePosition.deepEquivalent()); |
2874 | 2875 |
2875 #if ENABLE(ASSERT) | 2876 #if ENABLE(ASSERT) |
2876 // we should always be able to make the affinity |TextAffinity::Downstream|, | 2877 // we should always be able to make the affinity |TextAffinity::Downstream|, |
2877 // because going previous from an |TextAffinity::Upstream| position can | 2878 // because going previous from an |TextAffinity::Upstream| position can |
2878 // never yield another |TextAffinity::Upstream position| (unless line wrap | 2879 // never yield another |TextAffinity::Upstream position| (unless line wrap |
2879 // length is 0!). | 2880 // length is 0!). |
2880 if (prev.isNotNull() && visiblePosition.affinity() == TextAffinity::Upstream
) { | 2881 if (prev.isNotNull() && visiblePosition.affinity() == TextAffinity::Upstream
) { |
2881 ASSERT(inSameLine(PositionWithAffinity(prev.deepEquivalent()), PositionW
ithAffinity(prev.deepEquivalent(), TextAffinity::Upstream))); | 2882 ASSERT(inSameLine(PositionWithAffinity(prev.deepEquivalent()), PositionW
ithAffinity(prev.deepEquivalent(), TextAffinity::Upstream))); |
2882 } | 2883 } |
2883 #endif | 2884 #endif |
2884 | 2885 |
2885 switch (rule) { | 2886 switch (rule) { |
2886 case CanCrossEditingBoundary: | 2887 case CanCrossEditingBoundary: |
2887 return prev; | 2888 return prev; |
2888 case CannotCrossEditingBoundary: | 2889 case CannotCrossEditingBoundary: |
2889 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); | 2890 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivale
nt()); |
2890 case CanSkipOverEditingBoundary: | 2891 case CanSkipOverEditingBoundary: |
2891 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); | 2892 return skipToStartOfEditingBoundary(prev, visiblePosition.deepEquivalent
()); |
2892 } | 2893 } |
2893 | 2894 |
2894 ASSERT_NOT_REACHED(); | 2895 ASSERT_NOT_REACHED(); |
2895 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); | 2896 return honorEditingBoundaryAtOrBefore(prev, visiblePosition.deepEquivalent()
); |
2896 } | 2897 } |
2897 | 2898 |
2898 } // namespace blink | 2899 } // namespace blink |
OLD | NEW |