OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/editing/Position.h" | 27 #include "core/editing/Position.h" |
28 | 28 |
29 #include "core/HTMLNames.h" | 29 #include "core/HTMLNames.h" |
30 #include "core/css/CSSComputedStyleDeclaration.h" | 30 #include "core/css/CSSComputedStyleDeclaration.h" |
31 #include "core/dom/Text.h" | 31 #include "core/dom/Text.h" |
32 #include "core/dom/shadow/ElementShadow.h" | 32 #include "core/dom/shadow/ElementShadow.h" |
33 #include "core/editing/EditingUtilities.h" | 33 #include "core/editing/EditingUtilities.h" |
34 #include "core/editing/PositionIterator.h" | 34 #include "core/editing/PositionIterator.h" |
| 35 #include "core/editing/TextAffinity.h" |
35 #include "core/editing/VisiblePosition.h" | 36 #include "core/editing/VisiblePosition.h" |
36 #include "core/editing/VisibleUnits.h" | 37 #include "core/editing/VisibleUnits.h" |
37 #include "core/editing/iterators/TextIterator.h" | 38 #include "core/editing/iterators/TextIterator.h" |
38 #include "core/frame/LocalFrame.h" | 39 #include "core/frame/LocalFrame.h" |
39 #include "core/frame/Settings.h" | 40 #include "core/frame/Settings.h" |
40 #include "core/html/HTMLTableElement.h" | 41 #include "core/html/HTMLTableElement.h" |
41 #include "core/layout/LayoutBlock.h" | 42 #include "core/layout/LayoutBlock.h" |
42 #include "core/layout/LayoutInline.h" | 43 #include "core/layout/LayoutInline.h" |
43 #include "core/layout/LayoutText.h" | 44 #include "core/layout/LayoutText.h" |
44 #include "core/layout/line/InlineIterator.h" | 45 #include "core/layout/line/InlineIterator.h" |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
940 return false; | 941 return false; |
941 | 942 |
942 LayoutObject* layoutObject = position.anchorNode()->layoutObject(); | 943 LayoutObject* layoutObject = position.anchorNode()->layoutObject(); |
943 if (!layoutObject) | 944 if (!layoutObject) |
944 return false; | 945 return false; |
945 | 946 |
946 return toLayoutText(layoutObject)->isRenderedCharacter(position.offsetInCont
ainerNode()); | 947 return toLayoutText(layoutObject)->isRenderedCharacter(position.offsetInCont
ainerNode()); |
947 } | 948 } |
948 | 949 |
949 template <typename Strategy> | 950 template <typename Strategy> |
950 InlineBoxPosition PositionAlgorithm<Strategy>::computeInlineBoxPosition(EAffinit
y affinity) const | 951 InlineBoxPosition PositionAlgorithm<Strategy>::computeInlineBoxPosition(TextAffi
nity affinity) const |
951 { | 952 { |
952 return computeInlineBoxPosition(affinity, primaryDirectionOf(*anchorNode()))
; | 953 return computeInlineBoxPosition(affinity, primaryDirectionOf(*anchorNode()))
; |
953 } | 954 } |
954 | 955 |
955 static bool isNonTextLeafChild(LayoutObject* object) | 956 static bool isNonTextLeafChild(LayoutObject* object) |
956 { | 957 { |
957 if (object->slowFirstChild()) | 958 if (object->slowFirstChild()) |
958 return false; | 959 return false; |
959 if (object->isText()) | 960 if (object->isText()) |
960 return false; | 961 return false; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 { | 1005 { |
1005 PositionAlgorithm<Strategy> lastPosition; | 1006 PositionAlgorithm<Strategy> lastPosition; |
1006 while (position != lastPosition) { | 1007 while (position != lastPosition) { |
1007 lastPosition = position; | 1008 lastPosition = position; |
1008 position = position.upstream(CanCrossEditingBoundary); | 1009 position = position.upstream(CanCrossEditingBoundary); |
1009 } | 1010 } |
1010 return position; | 1011 return position; |
1011 } | 1012 } |
1012 | 1013 |
1013 template <typename Strategy> | 1014 template <typename Strategy> |
1014 InlineBoxPosition PositionAlgorithm<Strategy>::computeInlineBoxPosition(EAffinit
y affinity, TextDirection primaryDirection) const | 1015 InlineBoxPosition PositionAlgorithm<Strategy>::computeInlineBoxPosition(TextAffi
nity affinity, TextDirection primaryDirection) const |
1015 { | 1016 { |
1016 InlineBox* inlineBox = nullptr; | 1017 InlineBox* inlineBox = nullptr; |
1017 int caretOffset = computeEditingOffset(); | 1018 int caretOffset = computeEditingOffset(); |
1018 LayoutObject* layoutObject = m_anchorNode->isShadowRoot() ? toShadowRoot(m_a
nchorNode)->host()->layoutObject() : m_anchorNode->layoutObject(); | 1019 LayoutObject* layoutObject = m_anchorNode->isShadowRoot() ? toShadowRoot(m_a
nchorNode)->host()->layoutObject() : m_anchorNode->layoutObject(); |
1019 | 1020 |
1020 if (!layoutObject->isText()) { | 1021 if (!layoutObject->isText()) { |
1021 inlineBox = 0; | 1022 inlineBox = 0; |
1022 if (canHaveChildrenForEditing(anchorNode()) && layoutObject->isLayoutBlo
ckFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { | 1023 if (canHaveChildrenForEditing(anchorNode()) && layoutObject->isLayoutBlo
ckFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { |
1023 // Try a visually equivalent position with possibly opposite | 1024 // Try a visually equivalent position with possibly opposite |
1024 // editability. This helps in case |this| is in an editable block | 1025 // editability. This helps in case |this| is in an editable block |
1025 // but surrounded by non-editable positions. It acts to negate the | 1026 // but surrounded by non-editable positions. It acts to negate the |
1026 // logic at the beginning of LayoutObject::createVisiblePosition(). | 1027 // logic at the beginning of LayoutObject::createVisiblePosition(). |
1027 PositionAlgorithm<Strategy> thisPosition = PositionAlgorithm<Strateg
y>(*this); | 1028 PositionAlgorithm<Strategy> thisPosition = PositionAlgorithm<Strateg
y>(*this); |
1028 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo
undaries(thisPosition); | 1029 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo
undaries(thisPosition); |
1029 if (equivalent == thisPosition) { | 1030 if (equivalent == thisPosition) { |
1030 equivalent = upstreamIgnoringEditingBoundaries(thisPosition); | 1031 equivalent = upstreamIgnoringEditingBoundaries(thisPosition); |
1031 if (equivalent == thisPosition || downstreamIgnoringEditingBound
aries(equivalent) == thisPosition) | 1032 if (equivalent == thisPosition || downstreamIgnoringEditingBound
aries(equivalent) == thisPosition) |
1032 return InlineBoxPosition(inlineBox, caretOffset); | 1033 return InlineBoxPosition(inlineBox, caretOffset); |
1033 } | 1034 } |
1034 | 1035 |
1035 return equivalent.computeInlineBoxPosition(UPSTREAM, primaryDirectio
n); | 1036 return equivalent.computeInlineBoxPosition(TextAffinity::Upstream, p
rimaryDirection); |
1036 } | 1037 } |
1037 if (layoutObject->isBox()) { | 1038 if (layoutObject->isBox()) { |
1038 inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper(); | 1039 inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper(); |
1039 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care
tOffset < inlineBox->caretMaxOffset())) | 1040 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care
tOffset < inlineBox->caretMaxOffset())) |
1040 return InlineBoxPosition(inlineBox, caretOffset); | 1041 return InlineBoxPosition(inlineBox, caretOffset); |
1041 } | 1042 } |
1042 } else { | 1043 } else { |
1043 LayoutText* textLayoutObject = toLayoutText(layoutObject); | 1044 LayoutText* textLayoutObject = toLayoutText(layoutObject); |
1044 | 1045 |
1045 InlineTextBox* box; | 1046 InlineTextBox* box; |
1046 InlineTextBox* candidate = 0; | 1047 InlineTextBox* candidate = 0; |
1047 | 1048 |
1048 for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox
()) { | 1049 for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox
()) { |
1049 int caretMinOffset = box->caretMinOffset(); | 1050 int caretMinOffset = box->caretMinOffset(); |
1050 int caretMaxOffset = box->caretMaxOffset(); | 1051 int caretMaxOffset = box->caretMaxOffset(); |
1051 | 1052 |
1052 if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset ||
(caretOffset == caretMaxOffset && box->isLineBreak())) | 1053 if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset ||
(caretOffset == caretMaxOffset && box->isLineBreak())) |
1053 continue; | 1054 continue; |
1054 | 1055 |
1055 if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) | 1056 if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) |
1056 return InlineBoxPosition(box, caretOffset); | 1057 return InlineBoxPosition(box, caretOffset); |
1057 | 1058 |
1058 if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM)) | 1059 if (((caretOffset == caretMaxOffset) ^ (affinity == TextAffinity::Do
wnstream)) |
1059 || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM)) | 1060 || ((caretOffset == caretMinOffset) ^ (affinity == TextAffinity:
:Upstream)) |
1060 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box
->nextLeafChild()->isLineBreak())) | 1061 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box
->nextLeafChild()->isLineBreak())) |
1061 break; | 1062 break; |
1062 | 1063 |
1063 candidate = box; | 1064 candidate = box; |
1064 } | 1065 } |
1065 if (candidate && candidate == textLayoutObject->lastTextBox() && affinit
y == DOWNSTREAM) { | 1066 if (candidate && candidate == textLayoutObject->lastTextBox() && affinit
y == TextAffinity::Downstream) { |
1066 box = searchAheadForBetterMatch(textLayoutObject); | 1067 box = searchAheadForBetterMatch(textLayoutObject); |
1067 if (box) | 1068 if (box) |
1068 caretOffset = box->caretMinOffset(); | 1069 caretOffset = box->caretMinOffset(); |
1069 } | 1070 } |
1070 inlineBox = box ? box : candidate; | 1071 inlineBox = box ? box : candidate; |
1071 } | 1072 } |
1072 | 1073 |
1073 if (!inlineBox) | 1074 if (!inlineBox) |
1074 return InlineBoxPosition(inlineBox, caretOffset); | 1075 return InlineBoxPosition(inlineBox, caretOffset); |
1075 | 1076 |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 | 1353 |
1353 void showTree(const blink::Position* pos) | 1354 void showTree(const blink::Position* pos) |
1354 { | 1355 { |
1355 if (pos) | 1356 if (pos) |
1356 pos->showTreeForThis(); | 1357 pos->showTreeForThis(); |
1357 else | 1358 else |
1358 fprintf(stderr, "Cannot showTree for (nil)\n"); | 1359 fprintf(stderr, "Cannot showTree for (nil)\n"); |
1359 } | 1360 } |
1360 | 1361 |
1361 #endif | 1362 #endif |
OLD | NEW |