Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/dom/Position.h"
     28 
     29 #include "core/HTMLNames.h"
     30 #include "core/css/CSSComputedStyleDeclaration.h"
     31 #include "core/dom/PositionIterator.h"
     32 #include "core/dom/Text.h"
     33 #include "core/editing/TextIterator.h"
     34 #include "core/editing/VisiblePosition.h"
     35 #include "core/editing/VisibleUnits.h"
     36 #include "core/editing/htmlediting.h"
     37 #include "core/frame/LocalFrame.h"
     38 #include "core/frame/Settings.h"
     39 #include "core/html/HTMLTableElement.h"
     40 #include "core/rendering/InlineIterator.h"
     41 #include "core/rendering/InlineTextBox.h"
     42 #include "core/rendering/RenderBlock.h"
     43 #include "core/rendering/RenderInline.h"
     44 #include "core/rendering/RenderText.h"
     45 #include "platform/Logging.h"
     46 #include "wtf/text/CString.h"
     47 #include "wtf/unicode/CharacterNames.h"
     48 #include <stdio.h>
     49 
     50 namespace blink {
     51 
     52 using namespace HTMLNames;
     53 
     54 static Node* nextRenderedEditable(Node* node)
     55 {
     56     for (node = node->nextLeafNode(); node; node = node->nextLeafNode()) {
     57         RenderObject* renderer = node->renderer();
     58         if (!renderer)
     59             continue;
     60         if (!node->hasEditableStyle())
     61             continue;
     62         if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
     63             return node;
     64     }
     65     return 0;
     66 }
     67 
     68 static Node* previousRenderedEditable(Node* node)
     69 {
     70     for (node = node->previousLeafNode(); node; node = node->previousLeafNode()) {
     71         RenderObject* renderer = node->renderer();
     72         if (!renderer)
     73             continue;
     74         if (!node->hasEditableStyle())
     75             continue;
     76         if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
     77             return node;
     78     }
     79     return 0;
     80 }
     81 
     82 Position::Position(PassRefPtrWillBeRawPtr<Node> anchorNode, LegacyEditingOffset offset)
     83     : m_anchorNode(anchorNode)
     84     , m_offset(offset.value())
     85     , m_anchorType(anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset))
     86     , m_isLegacyEditingPosition(true)
     87 {
     88     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
     89 }
     90 
     91 Position::Position(PassRefPtrWillBeRawPtr<Node> anchorNode, AnchorType anchorType)
     92     : m_anchorNode(anchorNode)
     93     , m_offset(0)
     94     , m_anchorType(anchorType)
     95     , m_isLegacyEditingPosition(false)
     96 {
     97     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
     98 
     99     ASSERT(anchorType != PositionIsOffsetInAnchor);
    100     ASSERT(!((anchorType == PositionIsBeforeChildren || anchorType == PositionIsAfterChildren)
    101         && (m_anchorNode->isTextNode() || editingIgnoresContent(m_anchorNode.get()))));
    102 }
    103 
    104 Position::Position(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset, AnchorType anchorType)
    105     : m_anchorNode(anchorNode)
    106     , m_offset(offset)
    107     , m_anchorType(anchorType)
    108     , m_isLegacyEditingPosition(false)
    109 {
    110     ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement());
    111 
    112     ASSERT(anchorType == PositionIsOffsetInAnchor);
    113 }
    114 
    115 Position::Position(PassRefPtrWillBeRawPtr<Text> textNode, unsigned offset)
    116     : m_anchorNode(textNode)
    117     , m_offset(static_cast<int>(offset))
    118     , m_anchorType(PositionIsOffsetInAnchor)
    119     , m_isLegacyEditingPosition(false)
    120 {
    121     ASSERT(m_anchorNode);
    122 }
    123 
    124 void Position::moveToPosition(PassRefPtrWillBeRawPtr<Node> node, int offset)
    125 {
    126     ASSERT(!editingIgnoresContent(node.get()));
    127     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
    128     m_anchorNode = node;
    129     m_offset = offset;
    130     if (m_isLegacyEditingPosition)
    131         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
    132 }
    133 void Position::moveToOffset(int offset)
    134 {
    135     ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
    136     m_offset = offset;
    137     if (m_isLegacyEditingPosition)
    138         m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
    139 }
    140 
    141 Node* Position::containerNode() const
    142 {
    143     if (!m_anchorNode)
    144         return 0;
    145 
    146     switch (anchorType()) {
    147     case PositionIsBeforeChildren:
    148     case PositionIsAfterChildren:
    149     case PositionIsOffsetInAnchor:
    150         return m_anchorNode.get();
    151     case PositionIsBeforeAnchor:
    152     case PositionIsAfterAnchor:
    153         return m_anchorNode->parentNode();
    154     }
    155     ASSERT_NOT_REACHED();
    156     return 0;
    157 }
    158 
    159 Text* Position::containerText() const
    160 {
    161     switch (anchorType()) {
    162     case PositionIsOffsetInAnchor:
    163         return m_anchorNode && m_anchorNode->isTextNode() ? toText(m_anchorNode) : 0;
    164     case PositionIsBeforeAnchor:
    165     case PositionIsAfterAnchor:
    166         return 0;
    167     case PositionIsBeforeChildren:
    168     case PositionIsAfterChildren:
    169         ASSERT(!m_anchorNode || !m_anchorNode->isTextNode());
    170         return 0;
    171     }
    172     ASSERT_NOT_REACHED();
    173     return 0;
    174 }
    175 
    176 int Position::computeOffsetInContainerNode() const
    177 {
    178     if (!m_anchorNode)
    179         return 0;
    180 
    181     switch (anchorType()) {
    182     case PositionIsBeforeChildren:
    183         return 0;
    184     case PositionIsAfterChildren:
    185         return lastOffsetInNode(m_anchorNode.get());
    186     case PositionIsOffsetInAnchor:
    187         return minOffsetForNode(m_anchorNode.get(), m_offset);
    188     case PositionIsBeforeAnchor:
    189         return m_anchorNode->nodeIndex();
    190     case PositionIsAfterAnchor:
    191         return m_anchorNode->nodeIndex() + 1;
    192     }
    193     ASSERT_NOT_REACHED();
    194     return 0;
    195 }
    196 
    197 int Position::offsetForPositionAfterAnchor() const
    198 {
    199     ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren);
    200     ASSERT(!m_isLegacyEditingPosition);
    201     return lastOffsetForEditing(m_anchorNode.get());
    202 }
    203 
    204 // Neighbor-anchored positions are invalid DOM positions, so they need to be
    205 // fixed up before handing them off to the Range object.
    206 Position Position::parentAnchoredEquivalent() const
    207 {
    208     if (!m_anchorNode)
    209         return Position();
    210 
    211     // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
    212     if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) {
    213         if (m_anchorNode->parentNode() && (editingIgnoresContent(m_anchorNode.get()) || isRenderedHTMLTableElement(m_anchorNode.get())))
    214             return positionInParentBeforeNode(*m_anchorNode);
    215         return Position(m_anchorNode.get(), 0, PositionIsOffsetInAnchor);
    216     }
    217     if (!m_anchorNode->offsetInCharacters()
    218         && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->countChildren())
    219         && (editingIgnoresContent(m_anchorNode.get()) || isRenderedHTMLTableElement(m_anchorNode.get()))
    220         && containerNode()) {
    221         return positionInParentAfterNode(*m_anchorNode);
    222     }
    223 
    224     return Position(containerNode(), computeOffsetInContainerNode(), PositionIsOffsetInAnchor);
    225 }
    226 
    227 Node* Position::computeNodeBeforePosition() const
    228 {
    229     if (!m_anchorNode)
    230         return 0;
    231     switch (anchorType()) {
    232     case PositionIsBeforeChildren:
    233         return 0;
    234     case PositionIsAfterChildren:
    235         return m_anchorNode->lastChild();
    236     case PositionIsOffsetInAnchor:
    237         return m_offset ? NodeTraversal::childAt(*m_anchorNode, m_offset - 1) : 0;
    238     case PositionIsBeforeAnchor:
    239         return m_anchorNode->previousSibling();
    240     case PositionIsAfterAnchor:
    241         return m_anchorNode.get();
    242     }
    243     ASSERT_NOT_REACHED();
    244     return 0;
    245 }
    246 
    247 Node* Position::computeNodeAfterPosition() const
    248 {
    249     if (!m_anchorNode)
    250         return 0;
    251 
    252     switch (anchorType()) {
    253     case PositionIsBeforeChildren:
    254         return m_anchorNode->firstChild();
    255     case PositionIsAfterChildren:
    256         return 0;
    257     case PositionIsOffsetInAnchor:
    258         return NodeTraversal::childAt(*m_anchorNode, m_offset);
    259     case PositionIsBeforeAnchor:
    260         return m_anchorNode.get();
    261     case PositionIsAfterAnchor:
    262         return m_anchorNode->nextSibling();
    263     }
    264     ASSERT_NOT_REACHED();
    265     return 0;
    266 }
    267 
    268 Position::AnchorType Position::anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset)
    269 {
    270     if (anchorNode && editingIgnoresContent(anchorNode)) {
    271         if (offset == 0)
    272             return Position::PositionIsBeforeAnchor;
    273         return Position::PositionIsAfterAnchor;
    274     }
    275     return Position::PositionIsOffsetInAnchor;
    276 }
    277 
    278 // FIXME: This method is confusing (does it return anchorNode() or containerNode()?) and should be renamed or removed
    279 Element* Position::element() const
    280 {
    281     Node* node = anchorNode();
    282     if (!node || node->isElementNode())
    283         return toElement(node);
    284     return node->parentElement();
    285 }
    286 
    287 PassRefPtrWillBeRawPtr<CSSComputedStyleDeclaration> Position::computedStyle() const
    288 {
    289     Element* elem = element();
    290     if (!elem)
    291         return nullptr;
    292     return CSSComputedStyleDeclaration::create(elem);
    293 }
    294 
    295 Position Position::previous(PositionMoveType moveType) const
    296 {
    297     Node* node = deprecatedNode();
    298     if (!node)
    299         return *this;
    300 
    301     int offset = deprecatedEditingOffset();
    302     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
    303     ASSERT(offset >= 0);
    304 
    305     if (offset > 0) {
    306         if (Node* child = NodeTraversal::childAt(*node, offset - 1))
    307             return lastPositionInOrAfterNode(child);
    308 
    309         // There are two reasons child might be 0:
    310         //   1) The node is node like a text node that is not an element, and therefore has no children.
    311         //      Going backward one character at a time is correct.
    312         //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.
    313         //      Going from 1 to 0 is correct.
    314         switch (moveType) {
    315         case CodePoint:
    316             return createLegacyEditingPosition(node, offset - 1);
    317         case Character:
    318             return createLegacyEditingPosition(node, uncheckedPreviousOffset(node, offset));
    319         case BackwardDeletion:
    320             return createLegacyEditingPosition(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
    321         }
    322     }
    323 
    324     if (ContainerNode* parent = node->parentNode())
    325         return createLegacyEditingPosition(parent, node->nodeIndex());
    326     return *this;
    327 }
    328 
    329 Position Position::next(PositionMoveType moveType) const
    330 {
    331     ASSERT(moveType != BackwardDeletion);
    332 
    333     Node* node = deprecatedNode();
    334     if (!node)
    335         return *this;
    336 
    337     int offset = deprecatedEditingOffset();
    338     // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
    339     ASSERT(offset >= 0);
    340 
    341     if (Node* child = NodeTraversal::childAt(*node, offset))
    342         return firstPositionInOrBeforeNode(child);
    343 
    344     if (!node->hasChildren() && offset < lastOffsetForEditing(node)) {
    345         // There are two reasons child might be 0:
    346         //   1) The node is node like a text node that is not an element, and therefore has no children.
    347         //      Going forward one character at a time is correct.
    348         //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
    349         //      Going from 0 to 1 is correct.
    350         return createLegacyEditingPosition(node, (moveType == Character) ? uncheckedNextOffset(node, offset) : offset + 1);
    351     }
    352 
    353     if (ContainerNode* parent = node->parentNode())
    354         return createLegacyEditingPosition(parent, node->nodeIndex() + 1);
    355     return *this;
    356 }
    357 
    358 int Position::uncheckedPreviousOffset(const Node* n, int current)
    359 {
    360     return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
    361 }
    362 
    363 int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
    364 {
    365     return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
    366 }
    367 
    368 int Position::uncheckedNextOffset(const Node* n, int current)
    369 {
    370     return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
    371 }
    372 
    373 bool Position::atFirstEditingPositionForNode() const
    374 {
    375     if (isNull())
    376         return true;
    377     // FIXME: Position before anchor shouldn't be considered as at the first editing position for node
    378     // since that position resides outside of the node.
    379     switch (m_anchorType) {
    380     case PositionIsOffsetInAnchor:
    381         return m_offset <= 0;
    382     case PositionIsBeforeChildren:
    383     case PositionIsBeforeAnchor:
    384         return true;
    385     case PositionIsAfterChildren:
    386     case PositionIsAfterAnchor:
    387         return !lastOffsetForEditing(deprecatedNode());
    388     }
    389     ASSERT_NOT_REACHED();
    390     return false;
    391 }
    392 
    393 bool Position::atLastEditingPositionForNode() const
    394 {
    395     if (isNull())
    396         return true;
    397     // FIXME: Position after anchor shouldn't be considered as at the first editing position for node
    398     // since that position resides outside of the node.
    399     return m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAfterChildren || m_offset >= lastOffsetForEditing(deprecatedNode());
    400 }
    401 
    402 // A position is considered at editing boundary if one of the following is true:
    403 // 1. It is the first position in the node and the next visually equivalent position
    404 //    is non editable.
    405 // 2. It is the last position in the node and the previous visually equivalent position
    406 //    is non editable.
    407 // 3. It is an editable position and both the next and previous visually equivalent
    408 //    positions are both non editable.
    409 bool Position::atEditingBoundary() const
    410 {
    411     Position nextPosition = downstream(CanCrossEditingBoundary);
    412     if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditableStyle())
    413         return true;
    414 
    415     Position prevPosition = upstream(CanCrossEditingBoundary);
    416     if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditableStyle())
    417         return true;
    418 
    419     return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditableStyle()
    420         && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditableStyle();
    421 }
    422 
    423 Node* Position::parentEditingBoundary() const
    424 {
    425     if (!m_anchorNode)
    426         return 0;
    427 
    428     Node* documentElement = m_anchorNode->document().documentElement();
    429     if (!documentElement)
    430         return 0;
    431 
    432     Node* boundary = m_anchorNode.get();
    433     while (boundary != documentElement && boundary->nonShadowBoundaryParentNode() && m_anchorNode->hasEditableStyle() == boundary->parentNode()->hasEditableStyle())
    434         boundary = boundary->nonShadowBoundaryParentNode();
    435 
    436     return boundary;
    437 }
    438 
    439 
    440 bool Position::atStartOfTree() const
    441 {
    442     if (isNull())
    443         return true;
    444     return !deprecatedNode()->parentNode() && m_offset <= 0;
    445 }
    446 
    447 bool Position::atEndOfTree() const
    448 {
    449     if (isNull())
    450         return true;
    451     return !deprecatedNode()->parentNode() && m_offset >= lastOffsetForEditing(deprecatedNode());
    452 }
    453 
    454 int Position::renderedOffset() const
    455 {
    456     if (!deprecatedNode()->isTextNode())
    457         return m_offset;
    458 
    459     if (!deprecatedNode()->renderer())
    460         return m_offset;
    461 
    462     int result = 0;
    463     RenderText* textRenderer = toRenderText(deprecatedNode()->renderer());
    464     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    465         int start = box->start();
    466         int end = box->start() + box->len();
    467         if (m_offset < start)
    468             return result;
    469         if (m_offset <= end) {
    470             result += m_offset - start;
    471             return result;
    472         }
    473         result += box->len();
    474     }
    475     return result;
    476 }
    477 
    478 // Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
    479 // If true, adjacent candidates are visually distinct.
    480 // FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
    481 // FIXME: Share code with isCandidate, if possible.
    482 static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
    483 {
    484     if (!node || !node->renderer())
    485         return false;
    486 
    487     if (!node->renderer()->isInline())
    488         return true;
    489 
    490     // Don't include inline tables.
    491     if (isHTMLTableElement(*node))
    492         return false;
    493 
    494     // A Marquee elements are moving so we should assume their ends are always
    495     // visibily distinct.
    496     if (isHTMLMarqueeElement(*node))
    497         return true;
    498 
    499     // There is a VisiblePosition inside an empty inline-block container.
    500     return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->hasChildren();
    501 }
    502 
    503 static Node* enclosingVisualBoundary(Node* node)
    504 {
    505     while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
    506         node = node->parentNode();
    507 
    508     return node;
    509 }
    510 
    511 // upstream() and downstream() want to return positions that are either in a
    512 // text node or at just before a non-text node.  This method checks for that.
    513 static bool isStreamer(const PositionIterator& pos)
    514 {
    515     if (!pos.node())
    516         return true;
    517 
    518     if (isAtomicNode(pos.node()))
    519         return true;
    520 
    521     return pos.atStartOfNode();
    522 }
    523 
    524 // This function and downstream() are used for moving back and forth between visually equivalent candidates.
    525 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
    526 // that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate
    527 // and downstream() will return the right one.
    528 // Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
    529 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
    530 Position Position::upstream(EditingBoundaryCrossingRule rule) const
    531 {
    532     Node* startNode = deprecatedNode();
    533     if (!startNode)
    534         return Position();
    535 
    536     // iterate backward from there, looking for a qualified position
    537     Node* boundary = enclosingVisualBoundary(startNode);
    538     // FIXME: PositionIterator should respect Before and After positions.
    539     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
    540     PositionIterator currentPos = lastVisible;
    541     bool startEditable = startNode->hasEditableStyle();
    542     Node* lastNode = startNode;
    543     bool boundaryCrossed = false;
    544     for (; !currentPos.atStart(); currentPos.decrement()) {
    545         Node* currentNode = currentPos.node();
    546 
    547         // Don't check for an editability change if we haven't moved to a different node,
    548         // to avoid the expense of computing hasEditableStyle().
    549         if (currentNode != lastNode) {
    550             // Don't change editability.
    551             bool currentEditable = currentNode->hasEditableStyle();
    552             if (startEditable != currentEditable) {
    553                 if (rule == CannotCrossEditingBoundary)
    554                     break;
    555                 boundaryCrossed = true;
    556             }
    557             lastNode = currentNode;
    558         }
    559 
    560         // If we've moved to a position that is visually distinct, return the last saved position. There
    561         // is code below that terminates early if we're *about* to move to a visually distinct position.
    562         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
    563             return lastVisible;
    564 
    565         // skip position in unrendered or invisible node
    566         RenderObject* renderer = currentNode->renderer();
    567         if (!renderer || renderer->style()->visibility() != VISIBLE)
    568             continue;
    569 
    570         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
    571             lastVisible = currentPos;
    572             break;
    573         }
    574 
    575         // track last visible streamer position
    576         if (isStreamer(currentPos))
    577             lastVisible = currentPos;
    578 
    579         // Don't move past a position that is visually distinct.  We could rely on code above to terminate and
    580         // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
    581         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
    582             return lastVisible;
    583 
    584         // Return position after tables and nodes which have content that can be ignored.
    585         if (editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
    586             if (currentPos.atEndOfNode())
    587                 return positionAfterNode(currentNode);
    588             continue;
    589         }
    590 
    591         // return current position if it is in rendered text
    592         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
    593             if (currentNode != startNode) {
    594                 // This assertion fires in layout tests in the case-transform.html test because
    595                 // of a mix-up between offsets in the text in the DOM tree with text in the
    596                 // render tree which can have a different length due to case transformation.
    597                 // Until we resolve that, disable this so we can run the layout tests!
    598                 //ASSERT(currentOffset >= renderer->caretMaxOffset());
    599                 return createLegacyEditingPosition(currentNode, renderer->caretMaxOffset());
    600             }
    601 
    602             unsigned textOffset = currentPos.offsetInLeafNode();
    603             RenderText* textRenderer = toRenderText(renderer);
    604             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
    605             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    606                 if (textOffset <= box->start() + box->len()) {
    607                     if (textOffset > box->start())
    608                         return currentPos;
    609                     continue;
    610                 }
    611 
    612                 if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
    613                     continue;
    614 
    615                 // The text continues on the next line only if the last text box is not on this line and
    616                 // none of the boxes on this line have a larger start offset.
    617 
    618                 bool continuesOnNextLine = true;
    619                 InlineBox* otherBox = box;
    620                 while (continuesOnNextLine) {
    621                     otherBox = otherBox->nextLeafChild();
    622                     if (!otherBox)
    623                         break;
    624                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
    625                         continuesOnNextLine = false;
    626                 }
    627 
    628                 otherBox = box;
    629                 while (continuesOnNextLine) {
    630                     otherBox = otherBox->prevLeafChild();
    631                     if (!otherBox)
    632                         break;
    633                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
    634                         continuesOnNextLine = false;
    635                 }
    636 
    637                 if (continuesOnNextLine)
    638                     return currentPos;
    639             }
    640         }
    641     }
    642 
    643     return lastVisible;
    644 }
    645 
    646 // This function and upstream() are used for moving back and forth between visually equivalent candidates.
    647 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
    648 // that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate
    649 // and upstream() will return the left one.
    650 // Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
    651 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
    652 // FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264
    653 Position Position::downstream(EditingBoundaryCrossingRule rule) const
    654 {
    655     Node* startNode = deprecatedNode();
    656     if (!startNode)
    657         return Position();
    658 
    659     // iterate forward from there, looking for a qualified position
    660     Node* boundary = enclosingVisualBoundary(startNode);
    661     // FIXME: PositionIterator should respect Before and After positions.
    662     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
    663     PositionIterator currentPos = lastVisible;
    664     bool startEditable = startNode->hasEditableStyle();
    665     Node* lastNode = startNode;
    666     bool boundaryCrossed = false;
    667     for (; !currentPos.atEnd(); currentPos.increment()) {
    668         Node* currentNode = currentPos.node();
    669 
    670         // Don't check for an editability change if we haven't moved to a different node,
    671         // to avoid the expense of computing hasEditableStyle().
    672         if (currentNode != lastNode) {
    673             // Don't change editability.
    674             bool currentEditable = currentNode->hasEditableStyle();
    675             if (startEditable != currentEditable) {
    676                 if (rule == CannotCrossEditingBoundary)
    677                     break;
    678                 boundaryCrossed = true;
    679             }
    680 
    681             lastNode = currentNode;
    682         }
    683 
    684         // stop before going above the body, up into the head
    685         // return the last visible streamer position
    686         if (isHTMLBodyElement(*currentNode) && currentPos.atEndOfNode())
    687             break;
    688 
    689         // Do not move to a visually distinct position.
    690         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
    691             return lastVisible;
    692         // Do not move past a visually disinct position.
    693         // Note: The first position after the last in a node whose ends are visually distinct
    694         // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
    695         if (boundary && boundary->parentNode() == currentNode)
    696             return lastVisible;
    697 
    698         // skip position in unrendered or invisible node
    699         RenderObject* renderer = currentNode->renderer();
    700         if (!renderer || renderer->style()->visibility() != VISIBLE)
    701             continue;
    702 
    703         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
    704             lastVisible = currentPos;
    705             break;
    706         }
    707 
    708         // track last visible streamer position
    709         if (isStreamer(currentPos))
    710             lastVisible = currentPos;
    711 
    712         // Return position before tables and nodes which have content that can be ignored.
    713         if (editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
    714             if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
    715                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
    716             continue;
    717         }
    718 
    719         // return current position if it is in rendered text
    720         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
    721             if (currentNode != startNode) {
    722                 ASSERT(currentPos.atStartOfNode());
    723                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
    724             }
    725 
    726             unsigned textOffset = currentPos.offsetInLeafNode();
    727             RenderText* textRenderer = toRenderText(renderer);
    728             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
    729             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    730                 if (textOffset <= box->end()) {
    731                     if (textOffset >= box->start())
    732                         return currentPos;
    733                     continue;
    734                 }
    735 
    736                 if (box == lastTextBox || textOffset != box->start() + box->len())
    737                     continue;
    738 
    739                 // The text continues on the next line only if the last text box is not on this line and
    740                 // none of the boxes on this line have a larger start offset.
    741 
    742                 bool continuesOnNextLine = true;
    743                 InlineBox* otherBox = box;
    744                 while (continuesOnNextLine) {
    745                     otherBox = otherBox->nextLeafChild();
    746                     if (!otherBox)
    747                         break;
    748                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
    749                         continuesOnNextLine = false;
    750                 }
    751 
    752                 otherBox = box;
    753                 while (continuesOnNextLine) {
    754                     otherBox = otherBox->prevLeafChild();
    755                     if (!otherBox)
    756                         break;
    757                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
    758                         continuesOnNextLine = false;
    759                 }
    760 
    761                 if (continuesOnNextLine)
    762                     return currentPos;
    763             }
    764         }
    765     }
    766 
    767     return lastVisible;
    768 }
    769 
    770 static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect)
    771 {
    772     return o->style()->isHorizontalWritingMode() ? rect.height() : rect.width();
    773 }
    774 
    775 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
    776 {
    777     RenderObject* stop = renderer->nextInPreOrderAfterChildren();
    778     for (RenderObject *o = renderer->slowFirstChild(); o && o != stop; o = o->nextInPreOrder())
    779         if (o->nonPseudoNode()) {
    780             if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->linesBoundingBox()))
    781                 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight())
    782                 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogicalHeight(o, toRenderInline(o)->linesBoundingBox())))
    783                 return true;
    784         }
    785     return false;
    786 }
    787 
    788 bool Position::nodeIsUserSelectNone(Node* node)
    789 {
    790     return node && node->renderer() && !node->renderer()->isSelectable();
    791 }
    792 
    793 bool Position::nodeIsUserSelectAll(const Node* node)
    794 {
    795     return RuntimeEnabledFeatures::userSelectAllEnabled() && node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_ALL;
    796 }
    797 
    798 Node* Position::rootUserSelectAllForNode(Node* node)
    799 {
    800     if (!node || !nodeIsUserSelectAll(node))
    801         return 0;
    802     Node* parent = node->parentNode();
    803     if (!parent)
    804         return node;
    805 
    806     Node* candidateRoot = node;
    807     while (parent) {
    808         if (!parent->renderer()) {
    809             parent = parent->parentNode();
    810             continue;
    811         }
    812         if (!nodeIsUserSelectAll(parent))
    813             break;
    814         candidateRoot = parent;
    815         parent = candidateRoot->parentNode();
    816     }
    817     return candidateRoot;
    818 }
    819 
    820 bool Position::isCandidate() const
    821 {
    822     if (isNull())
    823         return false;
    824 
    825     RenderObject* renderer = deprecatedNode()->renderer();
    826     if (!renderer)
    827         return false;
    828 
    829     if (renderer->style()->visibility() != VISIBLE)
    830         return false;
    831 
    832     if (renderer->isBR())
    833         // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
    834         return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
    835 
    836     if (renderer->isText())
    837         return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText();
    838 
    839     if (renderer->isSVG()) {
    840         // We don't consider SVG elements are contenteditable except for
    841         // associated renderer returns isText() true, e.g. RenderSVGInlineText.
    842         return false;
    843     }
    844 
    845     if (isRenderedHTMLTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
    846         return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
    847 
    848     if (isHTMLHtmlElement(*m_anchorNode))
    849         return false;
    850 
    851     if (renderer->isRenderBlockFlow()) {
    852         if (toRenderBlock(renderer)->logicalHeight() || isHTMLBodyElement(*m_anchorNode)) {
    853             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
    854                 return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
    855             return m_anchorNode->hasEditableStyle() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
    856         }
    857     } else {
    858         LocalFrame* frame = m_anchorNode->document().frame();
    859         bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
    860         return (caretBrowsing || m_anchorNode->hasEditableStyle()) && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
    861     }
    862 
    863     return false;
    864 }
    865 
    866 bool Position::inRenderedText() const
    867 {
    868     if (isNull() || !deprecatedNode()->isTextNode())
    869         return false;
    870 
    871     RenderObject* renderer = deprecatedNode()->renderer();
    872     if (!renderer)
    873         return false;
    874 
    875     RenderText *textRenderer = toRenderText(renderer);
    876     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    877         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
    878             // The offset we're looking for is before this node
    879             // this means the offset must be in content that is
    880             // not rendered. Return false.
    881             return false;
    882         }
    883         if (box->containsCaretOffset(m_offset))
    884             // Return false for offsets inside composed characters.
    885             return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset));
    886     }
    887 
    888     return false;
    889 }
    890 
    891 bool Position::isRenderedCharacter() const
    892 {
    893     if (isNull() || !deprecatedNode()->isTextNode())
    894         return false;
    895 
    896     RenderObject* renderer = deprecatedNode()->renderer();
    897     if (!renderer)
    898         return false;
    899 
    900     RenderText* textRenderer = toRenderText(renderer);
    901     for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    902         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
    903             // The offset we're looking for is before this node
    904             // this means the offset must be in content that is
    905             // not rendered. Return false.
    906             return false;
    907         }
    908         if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len()))
    909             return true;
    910     }
    911 
    912     return false;
    913 }
    914 
    915 bool Position::rendersInDifferentPosition(const Position &pos) const
    916 {
    917     if (isNull() || pos.isNull())
    918         return false;
    919 
    920     RenderObject* renderer = deprecatedNode()->renderer();
    921     if (!renderer)
    922         return false;
    923 
    924     RenderObject* posRenderer = pos.deprecatedNode()->renderer();
    925     if (!posRenderer)
    926         return false;
    927 
    928     if (renderer->style()->visibility() != VISIBLE ||
    929         posRenderer->style()->visibility() != VISIBLE)
    930         return false;
    931 
    932     if (deprecatedNode() == pos.deprecatedNode()) {
    933         if (isHTMLBRElement(*deprecatedNode()))
    934             return false;
    935 
    936         if (m_offset == pos.deprecatedEditingOffset())
    937             return false;
    938 
    939         if (!deprecatedNode()->isTextNode() && !pos.deprecatedNode()->isTextNode()) {
    940             if (m_offset != pos.deprecatedEditingOffset())
    941                 return true;
    942         }
    943     }
    944 
    945     if (isHTMLBRElement(*deprecatedNode()) && pos.isCandidate())
    946         return true;
    947 
    948     if (isHTMLBRElement(*pos.deprecatedNode()) && isCandidate())
    949         return true;
    950 
    951     if (!inSameContainingBlockFlowElement(deprecatedNode(), pos.deprecatedNode()))
    952         return true;
    953 
    954     if (deprecatedNode()->isTextNode() && !inRenderedText())
    955         return false;
    956 
    957     if (pos.deprecatedNode()->isTextNode() && !pos.inRenderedText())
    958         return false;
    959 
    960     int thisRenderedOffset = renderedOffset();
    961     int posRenderedOffset = pos.renderedOffset();
    962 
    963     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
    964         return false;
    965 
    966     int ignoredCaretOffset;
    967     InlineBox* b1;
    968     getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
    969     InlineBox* b2;
    970     pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
    971 
    972     WTF_LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
    973     WTF_LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
    974     WTF_LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
    975     WTF_LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
    976     WTF_LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxOffset(deprecatedNode()));
    977     WTF_LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxOffset(pos.deprecatedNode()));
    978     WTF_LOG(Editing, "----------------------------------------------------------------------\n");
    979 
    980     if (!b1 || !b2) {
    981         return false;
    982     }
    983 
    984     if (b1->root() != b2->root()) {
    985         return true;
    986     }
    987 
    988     if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
    989         && thisRenderedOffset == caretMaxOffset(deprecatedNode()) && !posRenderedOffset) {
    990         return false;
    991     }
    992 
    993     if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
    994         && !thisRenderedOffset && posRenderedOffset == caretMaxOffset(pos.deprecatedNode())) {
    995         return false;
    996     }
    997 
    998     return true;
    999 }
   1000 
   1001 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
   1002 {
   1003     getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
   1004 }
   1005 
   1006 static bool isNonTextLeafChild(RenderObject* object)
   1007 {
   1008     if (object->slowFirstChild())
   1009         return false;
   1010     if (object->isText())
   1011         return false;
   1012     return true;
   1013 }
   1014 
   1015 static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
   1016 {
   1017     RenderBlock* container = renderer->containingBlock();
   1018     for (RenderObject* next = renderer->nextInPreOrder(container); next; next = next->nextInPreOrder(container)) {
   1019         if (next->isRenderBlock())
   1020             return 0;
   1021         if (next->isBR())
   1022             return 0;
   1023         if (isNonTextLeafChild(next))
   1024             return 0;
   1025         if (next->isText()) {
   1026             InlineTextBox* match = 0;
   1027             int minOffset = INT_MAX;
   1028             for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
   1029                 int caretMinOffset = box->caretMinOffset();
   1030                 if (caretMinOffset < minOffset) {
   1031                     match = box;
   1032                     minOffset = caretMinOffset;
   1033                 }
   1034             }
   1035             if (match)
   1036                 return match;
   1037         }
   1038     }
   1039     return 0;
   1040 }
   1041 
   1042 static Position downstreamIgnoringEditingBoundaries(Position position)
   1043 {
   1044     Position lastPosition;
   1045     while (position != lastPosition) {
   1046         lastPosition = position;
   1047         position = position.downstream(CanCrossEditingBoundary);
   1048     }
   1049     return position;
   1050 }
   1051 
   1052 static Position upstreamIgnoringEditingBoundaries(Position position)
   1053 {
   1054     Position lastPosition;
   1055     while (position != lastPosition) {
   1056         lastPosition = position;
   1057         position = position.upstream(CanCrossEditingBoundary);
   1058     }
   1059     return position;
   1060 }
   1061 
   1062 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
   1063 {
   1064     caretOffset = deprecatedEditingOffset();
   1065     RenderObject* renderer = deprecatedNode()->renderer();
   1066 
   1067     if (!renderer->isText()) {
   1068         inlineBox = 0;
   1069         if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isRenderBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
   1070             // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
   1071             // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
   1072             // of RenderObject::createVisiblePosition().
   1073             Position equivalent = downstreamIgnoringEditingBoundaries(*this);
   1074             if (equivalent == *this) {
   1075                 equivalent = upstreamIgnoringEditingBoundaries(*this);
   1076                 if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this)
   1077                     return;
   1078             }
   1079 
   1080             equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
   1081             return;
   1082         }
   1083         if (renderer->isBox()) {
   1084             inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
   1085             if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
   1086                 return;
   1087         }
   1088     } else {
   1089         RenderText* textRenderer = toRenderText(renderer);
   1090 
   1091         InlineTextBox* box;
   1092         InlineTextBox* candidate = 0;
   1093 
   1094         for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
   1095             int caretMinOffset = box->caretMinOffset();
   1096             int caretMaxOffset = box->caretMaxOffset();
   1097 
   1098             if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
   1099                 continue;
   1100 
   1101             if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
   1102                 inlineBox = box;
   1103                 return;
   1104             }
   1105 
   1106             if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
   1107                 || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
   1108                 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
   1109                 break;
   1110 
   1111             candidate = box;
   1112         }
   1113         if (candidate && candidate == textRenderer->lastTextBox() && affinity == DOWNSTREAM) {
   1114             box = searchAheadForBetterMatch(textRenderer);
   1115             if (box)
   1116                 caretOffset = box->caretMinOffset();
   1117         }
   1118         inlineBox = box ? box : candidate;
   1119     }
   1120 
   1121     if (!inlineBox)
   1122         return;
   1123 
   1124     unsigned char level = inlineBox->bidiLevel();
   1125 
   1126     if (inlineBox->direction() == primaryDirection) {
   1127         if (caretOffset == inlineBox->caretRightmostOffset()) {
   1128             InlineBox* nextBox = inlineBox->nextLeafChild();
   1129             if (!nextBox || nextBox->bidiLevel() >= level)
   1130                 return;
   1131 
   1132             level = nextBox->bidiLevel();
   1133             InlineBox* prevBox = inlineBox;
   1134             do {
   1135                 prevBox = prevBox->prevLeafChild();
   1136             } while (prevBox && prevBox->bidiLevel() > level);
   1137 
   1138             if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
   1139                 return;
   1140 
   1141             // For example, abc 123 ^ CBA
   1142             while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
   1143                 if (nextBox->bidiLevel() < level)
   1144                     break;
   1145                 inlineBox = nextBox;
   1146             }
   1147             caretOffset = inlineBox->caretRightmostOffset();
   1148         } else {
   1149             InlineBox* prevBox = inlineBox->prevLeafChild();
   1150             if (!prevBox || prevBox->bidiLevel() >= level)
   1151                 return;
   1152 
   1153             level = prevBox->bidiLevel();
   1154             InlineBox* nextBox = inlineBox;
   1155             do {
   1156                 nextBox = nextBox->nextLeafChild();
   1157             } while (nextBox && nextBox->bidiLevel() > level);
   1158 
   1159             if (nextBox && nextBox->bidiLevel() == level)
   1160                 return;
   1161 
   1162             while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
   1163                 if (prevBox->bidiLevel() < level)
   1164                     break;
   1165                 inlineBox = prevBox;
   1166             }
   1167             caretOffset = inlineBox->caretLeftmostOffset();
   1168         }
   1169         return;
   1170     }
   1171 
   1172     if (caretOffset == inlineBox->caretLeftmostOffset()) {
   1173         InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
   1174         if (!prevBox || prevBox->bidiLevel() < level) {
   1175             // Left edge of a secondary run. Set to the right edge of the entire run.
   1176             while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
   1177                 if (nextBox->bidiLevel() < level)
   1178                     break;
   1179                 inlineBox = nextBox;
   1180             }
   1181             caretOffset = inlineBox->caretRightmostOffset();
   1182         } else if (prevBox->bidiLevel() > level) {
   1183             // Right edge of a "tertiary" run. Set to the left edge of that run.
   1184             while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
   1185                 if (tertiaryBox->bidiLevel() <= level)
   1186                     break;
   1187                 inlineBox = tertiaryBox;
   1188             }
   1189             caretOffset = inlineBox->caretLeftmostOffset();
   1190         }
   1191     } else if (m_anchorNode->selfOrAncestorHasDirAutoAttribute()) {
   1192         if (inlineBox->bidiLevel() < level)
   1193             caretOffset = inlineBox->caretLeftmostOffset();
   1194         else
   1195             caretOffset = inlineBox->caretRightmostOffset();
   1196     } else {
   1197         InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
   1198         if (!nextBox || nextBox->bidiLevel() < level) {
   1199             // Right edge of a secondary run. Set to the left edge of the entire run.
   1200             while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
   1201                 if (prevBox->bidiLevel() < level)
   1202                     break;
   1203                 inlineBox = prevBox;
   1204             }
   1205             caretOffset = inlineBox->caretLeftmostOffset();
   1206         } else if (nextBox->bidiLevel() > level) {
   1207             // Left edge of a "tertiary" run. Set to the right edge of that run.
   1208             while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
   1209                 if (tertiaryBox->bidiLevel() <= level)
   1210                     break;
   1211                 inlineBox = tertiaryBox;
   1212             }
   1213             caretOffset = inlineBox->caretRightmostOffset();
   1214         }
   1215     }
   1216 }
   1217 
   1218 TextDirection Position::primaryDirection() const
   1219 {
   1220     TextDirection primaryDirection = LTR;
   1221     for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) {
   1222         if (r->isRenderBlockFlow()) {
   1223             primaryDirection = r->style()->direction();
   1224             break;
   1225         }
   1226     }
   1227 
   1228     return primaryDirection;
   1229 }
   1230 
   1231 void Position::trace(Visitor* visitor)
   1232 {
   1233     visitor->trace(m_anchorNode);
   1234 }
   1235 
   1236 void Position::debugPosition(const char* msg) const
   1237 {
   1238     if (isNull())
   1239         fprintf(stderr, "Position [%s]: null\n", msg);
   1240     else
   1241         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, deprecatedNode()->nodeName().utf8().data(), deprecatedNode(), m_offset);
   1242 }
   1243 
   1244 #ifndef NDEBUG
   1245 
   1246 void Position::formatForDebugger(char* buffer, unsigned length) const
   1247 {
   1248     StringBuilder result;
   1249 
   1250     if (isNull())
   1251         result.appendLiteral("<null>");
   1252     else {
   1253         char s[1024];
   1254         result.appendLiteral("offset ");
   1255         result.appendNumber(m_offset);
   1256         result.appendLiteral(" of ");
   1257         deprecatedNode()->formatForDebugger(s, sizeof(s));
   1258         result.append(s);
   1259     }
   1260 
   1261     strncpy(buffer, result.toString().utf8().data(), length - 1);
   1262 }
   1263 
   1264 void Position::showAnchorTypeAndOffset() const
   1265 {
   1266     if (m_isLegacyEditingPosition)
   1267         fputs("legacy, ", stderr);
   1268     switch (anchorType()) {
   1269     case PositionIsOffsetInAnchor:
   1270         fputs("offset", stderr);
   1271         break;
   1272     case PositionIsBeforeChildren:
   1273         fputs("beforeChildren", stderr);
   1274         break;
   1275     case PositionIsAfterChildren:
   1276         fputs("afterChildren", stderr);
   1277         break;
   1278     case PositionIsBeforeAnchor:
   1279         fputs("before", stderr);
   1280         break;
   1281     case PositionIsAfterAnchor:
   1282         fputs("after", stderr);
   1283         break;
   1284     }
   1285     fprintf(stderr, ", offset:%d\n", m_offset);
   1286 }
   1287 
   1288 void Position::showTreeForThis() const
   1289 {
   1290     if (anchorNode()) {
   1291         anchorNode()->showTreeForThis();
   1292         showAnchorTypeAndOffset();
   1293     }
   1294 }
   1295 
   1296 #endif
   1297 
   1298 
   1299 
   1300 } // namespace blink
   1301 
   1302 #ifndef NDEBUG
   1303 
   1304 void showTree(const blink::Position& pos)
   1305 {
   1306     pos.showTreeForThis();
   1307 }
   1308 
   1309 void showTree(const blink::Position* pos)
   1310 {
   1311     if (pos)
   1312         pos->showTreeForThis();
   1313 }
   1314 
   1315 #endif
   1316