Chromium Code Reviews| 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 |