| 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..e26609b91f04e2d0c5cd788d000da7e7154dd0a0 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,8 @@ void PositionIteratorAlgorithm<Strategy>::increment() {
|
| return;
|
| }
|
|
|
| - if (m_anchorNode->layoutObject() && !Strategy::hasChildren(*m_anchorNode) &&
|
| + if (m_anchorNode->layoutObject() &&
|
| + !shouldTraverseChildren<Strategy>(*m_anchorNode) &&
|
| 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 +199,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 +244,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 +269,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 +283,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 +299,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 +314,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);
|
|
|