Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/PositionIterator.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/PositionIterator.cpp b/third_party/WebKit/Source/core/editing/PositionIterator.cpp |
| index 2e875770f473ac2bafb167e19bdfbb81f1de3e8f..93f899053d54068b6ebc6161e16019a6eb04ba12 100644 |
| --- a/third_party/WebKit/Source/core/editing/PositionIterator.cpp |
| +++ b/third_party/WebKit/Source/core/editing/PositionIterator.cpp |
| @@ -25,8 +25,29 @@ |
| #include "core/editing/PositionIterator.h" |
| +#include "core/editing/EditingUtilities.h" |
| + |
| namespace blink { |
| +namespace { |
| + |
| +// TODO(editing-dev): We should replace usages of |hasChildren()| in |
| +// |PositionIterator| to |shouldTraverseChildren()|. |
| +template <typename Strategy> |
| +bool shouldTraverseChildren(const Node& node) { |
| + return Strategy::hasChildren(node) && !isUserSelectContain(node); |
| +} |
| + |
| +// TODO(editing-dev): We should replace usages of |parent()| in |
| +// |PositionIterator| to |selectableParentOf()|. |
| +template <typename Strategy> |
| +ContainerNode* selectableParentOf(const Node& node) { |
| + ContainerNode* const parent = Strategy::parent(node); |
| + return parent && !isUserSelectContain(*parent) ? parent : nullptr; |
| +} |
| + |
| +} // namespace |
| + |
| static const int kInvalidOffset = -1; |
| template <typename Strategy> |
| @@ -39,8 +60,8 @@ PositionIteratorAlgorithm<Strategy>::PositionIteratorAlgorithm( |
| m_offsetInAnchor(m_nodeAfterPositionInAnchor ? 0 : offsetInAnchor), |
| m_depthToAnchorNode(0), |
| m_domTreeVersion(anchorNode->document().domTreeVersion()) { |
| - for (Node* node = Strategy::parent(*anchorNode); node; |
| - node = Strategy::parent(*node)) { |
| + for (Node* node = selectableParentOf<Strategy>(*anchorNode); node; |
| + node = selectableParentOf<Strategy>(*node)) { |
| // Each m_offsetsInAnchorNode[offset] should be an index of node in |
| // parent, but delay to calculate the index until it is needed for |
| // performance. |
| @@ -108,7 +129,7 @@ PositionIteratorAlgorithm<Strategy>::computePosition() const { |
| return PositionTemplate<Strategy>( |
| m_anchorNode, m_offsetsInAnchorNode[m_depthToAnchorNode]); |
| } |
| - if (Strategy::hasChildren(*m_anchorNode)) |
| + if (shouldTraverseChildren<Strategy>(*m_anchorNode)) |
| // For example, position is the end of B. |
| return PositionTemplate<Strategy>::lastPositionInOrAfterNode(m_anchorNode); |
| if (m_anchorNode->isTextNode()) |
| @@ -147,7 +168,10 @@ void PositionIteratorAlgorithm<Strategy>::increment() { |
| // Let |anchor| is A and |child| is B, |
| // then next |anchor| is B and |child| is E. |
| m_anchorNode = m_nodeAfterPositionInAnchor; |
| - m_nodeAfterPositionInAnchor = Strategy::firstChild(*m_anchorNode); |
| + m_nodeAfterPositionInAnchor = |
| + shouldTraverseChildren<Strategy>(*m_anchorNode) |
| + ? Strategy::firstChild(*m_anchorNode) |
| + : nullptr; |
| m_offsetInAnchor = 0; |
| // Increment depth intializing with 0. |
| ++m_depthToAnchorNode; |
| @@ -158,7 +182,9 @@ void PositionIteratorAlgorithm<Strategy>::increment() { |
| return; |
| } |
| - if (m_anchorNode->layoutObject() && !Strategy::hasChildren(*m_anchorNode) && |
| + if (m_anchorNode->layoutObject() && |
| + (!Strategy::hasChildren(*m_anchorNode) || |
| + isUserSelectContain(*m_anchorNode)) && |
|
yoichio
2017/03/02 08:49:11
This must be |!shouldTraverseChildren(*m_anchorNod
yosin_UTC9
2017/03/02 09:17:17
Good catch!
Done.
|
| m_offsetInAnchor < Strategy::lastOffsetForEditing(m_anchorNode)) { |
| // Case #2. This is the next of Case #1 or #2 itself. |
| // Position is (|anchor|, |m_offsetInAchor|). |
| @@ -174,7 +200,7 @@ void PositionIteratorAlgorithm<Strategy>::increment() { |
| // 3-b. If |anchor| doesn't have next sibling (let F), |
| // next |anchor| is B and |child| is null. (next is Case #3.) |
| m_nodeAfterPositionInAnchor = m_anchorNode; |
| - m_anchorNode = Strategy::parent(*m_nodeAfterPositionInAnchor); |
| + m_anchorNode = selectableParentOf<Strategy>(*m_nodeAfterPositionInAnchor); |
| if (!m_anchorNode) |
| return; |
| DCHECK_GT(m_depthToAnchorNode, 0u); |
| @@ -219,7 +245,7 @@ void PositionIteratorAlgorithm<Strategy>::decrement() { |
| // Let |anchor| is B and |child| is F, |
| // next |anchor| is E and |child| is null. |
| m_nodeAfterPositionInAnchor = nullptr; |
| - m_offsetInAnchor = Strategy::hasChildren(*m_anchorNode) |
| + m_offsetInAnchor = shouldTraverseChildren<Strategy>(*m_anchorNode) |
| ? 0 |
| : Strategy::lastOffsetForEditing(m_anchorNode); |
| // Decrement offset of |child| or initialize if it have never been |
| @@ -244,7 +270,7 @@ void PositionIteratorAlgorithm<Strategy>::decrement() { |
| // next |anchor| is A and |child| is B. |
| m_nodeAfterPositionInAnchor = |
| Strategy::parent(*m_nodeAfterPositionInAnchor); |
| - m_anchorNode = Strategy::parent(*m_nodeAfterPositionInAnchor); |
| + m_anchorNode = selectableParentOf<Strategy>(*m_nodeAfterPositionInAnchor); |
| if (!m_anchorNode) |
| return; |
| m_offsetInAnchor = 0; |
| @@ -258,11 +284,11 @@ void PositionIteratorAlgorithm<Strategy>::decrement() { |
| return; |
| } |
| - if (Strategy::hasChildren(*m_anchorNode)) { |
| + if (shouldTraverseChildren<Strategy>(*m_anchorNode)) { |
| // Case #2. This is a reverse of increment()::Case3-b. |
| // Let |anchor| is B, next |anchor| is F. |
| m_anchorNode = Strategy::lastChild(*m_anchorNode); |
| - m_offsetInAnchor = Strategy::hasChildren(*m_anchorNode) |
| + m_offsetInAnchor = shouldTraverseChildren<Strategy>(*m_anchorNode) |
| ? 0 |
| : Strategy::lastOffsetForEditing(m_anchorNode); |
| // Decrement depth initializing with -1 because |
| @@ -274,7 +300,6 @@ void PositionIteratorAlgorithm<Strategy>::decrement() { |
| ++m_depthToAnchorNode; |
| return; |
| } |
| - |
| if (m_offsetInAnchor && m_anchorNode->layoutObject()) { |
| // Case #3-a. This is a reverse of increment()::Case#2. |
| // In this case |anchor| is a leaf(E,F,C,G or H) and |
| @@ -290,7 +315,7 @@ void PositionIteratorAlgorithm<Strategy>::decrement() { |
| // Let |anchor| is E, |
| // next |anchor| is B and |child| is E. |
| m_nodeAfterPositionInAnchor = m_anchorNode; |
| - m_anchorNode = Strategy::parent(*m_anchorNode); |
| + m_anchorNode = selectableParentOf<Strategy>(*m_anchorNode); |
| if (!m_anchorNode) |
| return; |
| DCHECK_GT(m_depthToAnchorNode, 0u); |