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 WebCore {
     51 
     52 using namespace HTMLNames;
     53 
     54 static Node* nextRenderedEditable(Node* node)
     55 {
     56     while ((node = node->nextLeafNode())) {
     57         RenderObject* renderer = node->renderer();
     58         if (!renderer)
     59             continue;
     60         if (!node->rendererIsEditable())
     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     while ((node = node->previousLeafNode())) {
     71         RenderObject* renderer = node->renderer();
     72         if (!renderer)
     73             continue;
     74         if (!node->rendererIsEditable())
     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()) || isRenderedTableElement(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()) || isRenderedTableElement(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_anchorNode->traverseToChildAt(m_offset - 1); // -1 converts to traverseToChildAt((unsigned)-1) and returns null.
    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 m_anchorNode->traverseToChildAt(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* n = anchorNode();
    282     while (n && !n->isElementNode())
    283         n = n->parentNode();
    284     return toElement(n);
    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 = node->traverseToChildAt(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 = node->traverseToChildAt(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()->rendererIsEditable())
    413         return true;
    414 
    415     Position prevPosition = upstream(CanCrossEditingBoundary);
    416     if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable())
    417         return true;
    418 
    419     return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable()
    420         && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable();
    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->rendererIsEditable() == boundary->parentNode()->rendererIsEditable())
    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 // return first preceding DOM position rendered at a different location, or "this"
    479 Position Position::previousCharacterPosition(EAffinity affinity) const
    480 {
    481     if (isNull())
    482         return Position();
    483 
    484     Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
    485 
    486     bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));
    487     bool rendered = isCandidate();
    488 
    489     Position currentPos = *this;
    490     while (!currentPos.atStartOfTree()) {
    491         currentPos = currentPos.previous();
    492 
    493         if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
    494             return *this;
    495 
    496         if (atStartOfLine || !rendered) {
    497             if (currentPos.isCandidate())
    498                 return currentPos;
    499         } else if (rendersInDifferentPosition(currentPos))
    500             return currentPos;
    501     }
    502 
    503     return *this;
    504 }
    505 
    506 // Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
    507 // If true, adjacent candidates are visually distinct.
    508 // FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
    509 // FIXME: Share code with isCandidate, if possible.
    510 static bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
    511 {
    512     if (!node || !node->renderer())
    513         return false;
    514 
    515     if (!node->renderer()->isInline())
    516         return true;
    517 
    518     // Don't include inline tables.
    519     if (isHTMLTableElement(*node))
    520         return false;
    521 
    522     // A Marquee elements are moving so we should assume their ends are always
    523     // visibily distinct.
    524     if (isHTMLMarqueeElement(*node))
    525         return true;
    526 
    527     // There is a VisiblePosition inside an empty inline-block container.
    528     return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
    529 }
    530 
    531 static Node* enclosingVisualBoundary(Node* node)
    532 {
    533     while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
    534         node = node->parentNode();
    535 
    536     return node;
    537 }
    538 
    539 // upstream() and downstream() want to return positions that are either in a
    540 // text node or at just before a non-text node.  This method checks for that.
    541 static bool isStreamer(const PositionIterator& pos)
    542 {
    543     if (!pos.node())
    544         return true;
    545 
    546     if (isAtomicNode(pos.node()))
    547         return true;
    548 
    549     return pos.atStartOfNode();
    550 }
    551 
    552 // This function and downstream() are used for moving back and forth between visually equivalent candidates.
    553 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
    554 // that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate
    555 // and downstream() will return the right one.
    556 // Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
    557 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
    558 Position Position::upstream(EditingBoundaryCrossingRule rule) const
    559 {
    560     Node* startNode = deprecatedNode();
    561     if (!startNode)
    562         return Position();
    563 
    564     // iterate backward from there, looking for a qualified position
    565     Node* boundary = enclosingVisualBoundary(startNode);
    566     // FIXME: PositionIterator should respect Before and After positions.
    567     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
    568     PositionIterator currentPos = lastVisible;
    569     bool startEditable = startNode->rendererIsEditable();
    570     Node* lastNode = startNode;
    571     bool boundaryCrossed = false;
    572     for (; !currentPos.atStart(); currentPos.decrement()) {
    573         Node* currentNode = currentPos.node();
    574 
    575         // Don't check for an editability change if we haven't moved to a different node,
    576         // to avoid the expense of computing rendererIsEditable().
    577         if (currentNode != lastNode) {
    578             // Don't change editability.
    579             bool currentEditable = currentNode->rendererIsEditable();
    580             if (startEditable != currentEditable) {
    581                 if (rule == CannotCrossEditingBoundary)
    582                     break;
    583                 boundaryCrossed = true;
    584             }
    585             lastNode = currentNode;
    586         }
    587 
    588         // If we've moved to a position that is visually distinct, return the last saved position. There
    589         // is code below that terminates early if we're *about* to move to a visually distinct position.
    590         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
    591             return lastVisible;
    592 
    593         // skip position in unrendered or invisible node
    594         RenderObject* renderer = currentNode->renderer();
    595         if (!renderer || renderer->style()->visibility() != VISIBLE)
    596             continue;
    597 
    598         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
    599             lastVisible = currentPos;
    600             break;
    601         }
    602 
    603         // track last visible streamer position
    604         if (isStreamer(currentPos))
    605             lastVisible = currentPos;
    606 
    607         // Don't move past a position that is visually distinct.  We could rely on code above to terminate and
    608         // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
    609         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
    610             return lastVisible;
    611 
    612         // Return position after tables and nodes which have content that can be ignored.
    613         if (editingIgnoresContent(currentNode) || isRenderedTableElement(currentNode)) {
    614             if (currentPos.atEndOfNode())
    615                 return positionAfterNode(currentNode);
    616             continue;
    617         }
    618 
    619         // return current position if it is in rendered text
    620         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
    621             if (currentNode != startNode) {
    622                 // This assertion fires in layout tests in the case-transform.html test because
    623                 // of a mix-up between offsets in the text in the DOM tree with text in the
    624                 // render tree which can have a different length due to case transformation.
    625                 // Until we resolve that, disable this so we can run the layout tests!
    626                 //ASSERT(currentOffset >= renderer->caretMaxOffset());
    627                 return createLegacyEditingPosition(currentNode, renderer->caretMaxOffset());
    628             }
    629 
    630             unsigned textOffset = currentPos.offsetInLeafNode();
    631             RenderText* textRenderer = toRenderText(renderer);
    632             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
    633             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    634                 if (textOffset <= box->start() + box->len()) {
    635                     if (textOffset > box->start())
    636                         return currentPos;
    637                     continue;
    638                 }
    639 
    640                 if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
    641                     continue;
    642 
    643                 // The text continues on the next line only if the last text box is not on this line and
    644                 // none of the boxes on this line have a larger start offset.
    645 
    646                 bool continuesOnNextLine = true;
    647                 InlineBox* otherBox = box;
    648                 while (continuesOnNextLine) {
    649                     otherBox = otherBox->nextLeafChild();
    650                     if (!otherBox)
    651                         break;
    652                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
    653                         continuesOnNextLine = false;
    654                 }
    655 
    656                 otherBox = box;
    657                 while (continuesOnNextLine) {
    658                     otherBox = otherBox->prevLeafChild();
    659                     if (!otherBox)
    660                         break;
    661                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() > textOffset))
    662                         continuesOnNextLine = false;
    663                 }
    664 
    665                 if (continuesOnNextLine)
    666                     return currentPos;
    667             }
    668         }
    669     }
    670 
    671     return lastVisible;
    672 }
    673 
    674 // This function and upstream() are used for moving back and forth between visually equivalent candidates.
    675 // For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
    676 // that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate
    677 // and upstream() will return the left one.
    678 // Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
    679 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
    680 // FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264
    681 Position Position::downstream(EditingBoundaryCrossingRule rule) const
    682 {
    683     Node* startNode = deprecatedNode();
    684     if (!startNode)
    685         return Position();
    686 
    687     // iterate forward from there, looking for a qualified position
    688     Node* boundary = enclosingVisualBoundary(startNode);
    689     // FIXME: PositionIterator should respect Before and After positions.
    690     PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m_anchorNode.get())) : *this;
    691     PositionIterator currentPos = lastVisible;
    692     bool startEditable = startNode->rendererIsEditable();
    693     Node* lastNode = startNode;
    694     bool boundaryCrossed = false;
    695     for (; !currentPos.atEnd(); currentPos.increment()) {
    696         Node* currentNode = currentPos.node();
    697 
    698         // Don't check for an editability change if we haven't moved to a different node,
    699         // to avoid the expense of computing rendererIsEditable().
    700         if (currentNode != lastNode) {
    701             // Don't change editability.
    702             bool currentEditable = currentNode->rendererIsEditable();
    703             if (startEditable != currentEditable) {
    704                 if (rule == CannotCrossEditingBoundary)
    705                     break;
    706                 boundaryCrossed = true;
    707             }
    708 
    709             lastNode = currentNode;
    710         }
    711 
    712         // stop before going above the body, up into the head
    713         // return the last visible streamer position
    714         if (isHTMLBodyElement(*currentNode) && currentPos.atEndOfNode())
    715             break;
    716 
    717         // Do not move to a visually distinct position.
    718         if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
    719             return lastVisible;
    720         // Do not move past a visually disinct position.
    721         // Note: The first position after the last in a node whose ends are visually distinct
    722         // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
    723         if (boundary && boundary->parentNode() == currentNode)
    724             return lastVisible;
    725 
    726         // skip position in unrendered or invisible node
    727         RenderObject* renderer = currentNode->renderer();
    728         if (!renderer || renderer->style()->visibility() != VISIBLE)
    729             continue;
    730 
    731         if (rule == CanCrossEditingBoundary && boundaryCrossed) {
    732             lastVisible = currentPos;
    733             break;
    734         }
    735 
    736         // track last visible streamer position
    737         if (isStreamer(currentPos))
    738             lastVisible = currentPos;
    739 
    740         // Return position before tables and nodes which have content that can be ignored.
    741         if (editingIgnoresContent(currentNode) || isRenderedTableElement(currentNode)) {
    742             if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
    743                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
    744             continue;
    745         }
    746 
    747         // return current position if it is in rendered text
    748         if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
    749             if (currentNode != startNode) {
    750                 ASSERT(currentPos.atStartOfNode());
    751                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
    752             }
    753 
    754             unsigned textOffset = currentPos.offsetInLeafNode();
    755             RenderText* textRenderer = toRenderText(renderer);
    756             InlineTextBox* lastTextBox = textRenderer->lastTextBox();
    757             for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    758                 if (textOffset <= box->end()) {
    759                     if (textOffset >= box->start())
    760                         return currentPos;
    761                     continue;
    762                 }
    763 
    764                 if (box == lastTextBox || textOffset != box->start() + box->len())
    765                     continue;
    766 
    767                 // The text continues on the next line only if the last text box is not on this line and
    768                 // none of the boxes on this line have a larger start offset.
    769 
    770                 bool continuesOnNextLine = true;
    771                 InlineBox* otherBox = box;
    772                 while (continuesOnNextLine) {
    773                     otherBox = otherBox->nextLeafChild();
    774                     if (!otherBox)
    775                         break;
    776                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
    777                         continuesOnNextLine = false;
    778                 }
    779 
    780                 otherBox = box;
    781                 while (continuesOnNextLine) {
    782                     otherBox = otherBox->prevLeafChild();
    783                     if (!otherBox)
    784                         break;
    785                     if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && toInlineTextBox(otherBox)->start() >= textOffset))
    786                         continuesOnNextLine = false;
    787                 }
    788 
    789                 if (continuesOnNextLine)
    790                     return currentPos;
    791             }
    792         }
    793     }
    794 
    795     return lastVisible;
    796 }
    797 
    798 static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect)
    799 {
    800     return o->style()->isHorizontalWritingMode() ? rect.height() : rect.width();
    801 }
    802 
    803 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
    804 {
    805     RenderObject* stop = renderer->nextInPreOrderAfterChildren();
    806     for (RenderObject *o = renderer->slowFirstChild(); o && o != stop; o = o->nextInPreOrder())
    807         if (o->nonPseudoNode()) {
    808             if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->linesBoundingBox()))
    809                 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight())
    810                 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogicalHeight(o, toRenderInline(o)->linesBoundingBox())))
    811                 return true;
    812         }
    813     return false;
    814 }
    815 
    816 bool Position::nodeIsUserSelectNone(Node* node)
    817 {
    818     return node && node->renderer() && !node->renderer()->isSelectable();
    819 }
    820 
    821 bool Position::nodeIsUserSelectAll(const Node* node)
    822 {
    823     return RuntimeEnabledFeatures::userSelectAllEnabled() && node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_ALL;
    824 }
    825 
    826 Node* Position::rootUserSelectAllForNode(Node* node)
    827 {
    828     if (!node || !nodeIsUserSelectAll(node))
    829         return 0;
    830     Node* parent = node->parentNode();
    831     if (!parent)
    832         return node;
    833 
    834     Node* candidateRoot = node;
    835     while (parent) {
    836         if (!parent->renderer()) {
    837             parent = parent->parentNode();
    838             continue;
    839         }
    840         if (!nodeIsUserSelectAll(parent))
    841             break;
    842         candidateRoot = parent;
    843         parent = candidateRoot->parentNode();
    844     }
    845     return candidateRoot;
    846 }
    847 
    848 bool Position::isCandidate() const
    849 {
    850     if (isNull())
    851         return false;
    852 
    853     RenderObject* renderer = deprecatedNode()->renderer();
    854     if (!renderer)
    855         return false;
    856 
    857     if (renderer->style()->visibility() != VISIBLE)
    858         return false;
    859 
    860     if (renderer->isBR())
    861         // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
    862         return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
    863 
    864     if (renderer->isText())
    865         return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText();
    866 
    867     if (renderer->isSVG()) {
    868         // We don't consider SVG elements are contenteditable except for
    869         // associated renderer returns isText() true, e.g. RenderSVGInlineText.
    870         return false;
    871     }
    872 
    873     if (isRenderedTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
    874         return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
    875 
    876     if (isHTMLHtmlElement(*m_anchorNode))
    877         return false;
    878 
    879     if (renderer->isRenderBlockFlow()) {
    880         if (toRenderBlock(renderer)->logicalHeight() || isHTMLBodyElement(*m_anchorNode)) {
    881             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
    882                 return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
    883             return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
    884         }
    885     } else {
    886         LocalFrame* frame = m_anchorNode->document().frame();
    887         bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
    888         return (caretBrowsing || m_anchorNode->rendererIsEditable()) && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
    889     }
    890 
    891     return false;
    892 }
    893 
    894 bool Position::inRenderedText() const
    895 {
    896     if (isNull() || !deprecatedNode()->isTextNode())
    897         return false;
    898 
    899     RenderObject* renderer = deprecatedNode()->renderer();
    900     if (!renderer)
    901         return false;
    902 
    903     RenderText *textRenderer = toRenderText(renderer);
    904     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    905         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
    906             // The offset we're looking for is before this node
    907             // this means the offset must be in content that is
    908             // not rendered. Return false.
    909             return false;
    910         }
    911         if (box->containsCaretOffset(m_offset))
    912             // Return false for offsets inside composed characters.
    913             return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset));
    914     }
    915 
    916     return false;
    917 }
    918 
    919 bool Position::isRenderedCharacter() const
    920 {
    921     if (isNull() || !deprecatedNode()->isTextNode())
    922         return false;
    923 
    924     RenderObject* renderer = deprecatedNode()->renderer();
    925     if (!renderer)
    926         return false;
    927 
    928     RenderText* textRenderer = toRenderText(renderer);
    929     for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    930         if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
    931             // The offset we're looking for is before this node
    932             // this means the offset must be in content that is
    933             // not rendered. Return false.
    934             return false;
    935         }
    936         if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len()))
    937             return true;
    938     }
    939 
    940     return false;
    941 }
    942 
    943 bool Position::rendersInDifferentPosition(const Position &pos) const
    944 {
    945     if (isNull() || pos.isNull())
    946         return false;
    947 
    948     RenderObject* renderer = deprecatedNode()->renderer();
    949     if (!renderer)
    950         return false;
    951 
    952     RenderObject* posRenderer = pos.deprecatedNode()->renderer();
    953     if (!posRenderer)
    954         return false;
    955 
    956     if (renderer->style()->visibility() != VISIBLE ||
    957         posRenderer->style()->visibility() != VISIBLE)
    958         return false;
    959 
    960     if (deprecatedNode() == pos.deprecatedNode()) {
    961         if (isHTMLBRElement(*deprecatedNode()))
    962             return false;
    963 
    964         if (m_offset == pos.deprecatedEditingOffset())
    965             return false;
    966 
    967         if (!deprecatedNode()->isTextNode() && !pos.deprecatedNode()->isTextNode()) {
    968             if (m_offset != pos.deprecatedEditingOffset())
    969                 return true;
    970         }
    971     }
    972 
    973     if (isHTMLBRElement(*deprecatedNode()) && pos.isCandidate())
    974         return true;
    975 
    976     if (isHTMLBRElement(*pos.deprecatedNode()) && isCandidate())
    977         return true;
    978 
    979     if (deprecatedNode()->enclosingBlockFlowElement() != pos.deprecatedNode()->enclosingBlockFlowElement())
    980         return true;
    981 
    982     if (deprecatedNode()->isTextNode() && !inRenderedText())
    983         return false;
    984 
    985     if (pos.deprecatedNode()->isTextNode() && !pos.inRenderedText())
    986         return false;
    987 
    988     int thisRenderedOffset = renderedOffset();
    989     int posRenderedOffset = pos.renderedOffset();
    990 
    991     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
    992         return false;
    993 
    994     int ignoredCaretOffset;
    995     InlineBox* b1;
    996     getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
    997     InlineBox* b2;
    998     pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
    999 
   1000     WTF_LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
   1001     WTF_LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
   1002     WTF_LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
   1003     WTF_LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
   1004     WTF_LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxOffset(deprecatedNode()));
   1005     WTF_LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxOffset(pos.deprecatedNode()));
   1006     WTF_LOG(Editing, "----------------------------------------------------------------------\n");
   1007 
   1008     if (!b1 || !b2) {
   1009         return false;
   1010     }
   1011 
   1012     if (b1->root() != b2->root()) {
   1013         return true;
   1014     }
   1015 
   1016     if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
   1017         && thisRenderedOffset == caretMaxOffset(deprecatedNode()) && !posRenderedOffset) {
   1018         return false;
   1019     }
   1020 
   1021     if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
   1022         && !thisRenderedOffset && posRenderedOffset == caretMaxOffset(pos.deprecatedNode())) {
   1023         return false;
   1024     }
   1025 
   1026     return true;
   1027 }
   1028 
   1029 // This assumes that it starts in editable content.
   1030 Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const
   1031 {
   1032     ASSERT(isEditablePosition(*this, ContentIsEditable, DoNotUpdateStyle));
   1033     if (isNull())
   1034         return Position();
   1035 
   1036     if (isHTMLBRElement(*upstream().deprecatedNode()))
   1037         return Position();
   1038 
   1039     Position prev = previousCharacterPosition(affinity);
   1040     if (prev != *this && prev.deprecatedNode()->inSameContainingBlockFlowElement(deprecatedNode()) && prev.deprecatedNode()->isTextNode()) {
   1041         String string = toText(prev.deprecatedNode())->data();
   1042         UChar c = string[prev.deprecatedEditingOffset()];
   1043         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
   1044             if (isEditablePosition(prev))
   1045                 return prev;
   1046     }
   1047 
   1048     return Position();
   1049 }
   1050 
   1051 // This assumes that it starts in editable content.
   1052 Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const
   1053 {
   1054     ASSERT(isEditablePosition(*this, ContentIsEditable, DoNotUpdateStyle));
   1055     if (isNull())
   1056         return Position();
   1057 
   1058     VisiblePosition v(*this);
   1059     UChar c = v.characterAfter();
   1060     // The space must not be in another paragraph and it must be editable.
   1061     if (!isEndOfParagraph(v) && v.next(CannotCrossEditingBoundary).isNotNull())
   1062         if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
   1063             return *this;
   1064 
   1065     return Position();
   1066 }
   1067 
   1068 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
   1069 {
   1070     getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
   1071 }
   1072 
   1073 static bool isNonTextLeafChild(RenderObject* object)
   1074 {
   1075     if (object->slowFirstChild())
   1076         return false;
   1077     if (object->isText())
   1078         return false;
   1079     return true;
   1080 }
   1081 
   1082 static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
   1083 {
   1084     RenderBlock* container = renderer->containingBlock();
   1085     RenderObject* next = renderer;
   1086     while ((next = next->nextInPreOrder(container))) {
   1087         if (next->isRenderBlock())
   1088             return 0;
   1089         if (next->isBR())
   1090             return 0;
   1091         if (isNonTextLeafChild(next))
   1092             return 0;
   1093         if (next->isText()) {
   1094             InlineTextBox* match = 0;
   1095             int minOffset = INT_MAX;
   1096             for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
   1097                 int caretMinOffset = box->caretMinOffset();
   1098                 if (caretMinOffset < minOffset) {
   1099                     match = box;
   1100                     minOffset = caretMinOffset;
   1101                 }
   1102             }
   1103             if (match)
   1104                 return match;
   1105         }
   1106     }
   1107     return 0;
   1108 }
   1109 
   1110 static Position downstreamIgnoringEditingBoundaries(Position position)
   1111 {
   1112     Position lastPosition;
   1113     while (position != lastPosition) {
   1114         lastPosition = position;
   1115         position = position.downstream(CanCrossEditingBoundary);
   1116     }
   1117     return position;
   1118 }
   1119 
   1120 static Position upstreamIgnoringEditingBoundaries(Position position)
   1121 {
   1122     Position lastPosition;
   1123     while (position != lastPosition) {
   1124         lastPosition = position;
   1125         position = position.upstream(CanCrossEditingBoundary);
   1126     }
   1127     return position;
   1128 }
   1129 
   1130 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
   1131 {
   1132     caretOffset = deprecatedEditingOffset();
   1133     RenderObject* renderer = deprecatedNode()->renderer();
   1134 
   1135     if (!renderer->isText()) {
   1136         inlineBox = 0;
   1137         if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isRenderBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
   1138             // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
   1139             // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
   1140             // of RenderObject::createVisiblePosition().
   1141             Position equivalent = downstreamIgnoringEditingBoundaries(*this);
   1142             if (equivalent == *this) {
   1143                 equivalent = upstreamIgnoringEditingBoundaries(*this);
   1144                 if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this)
   1145                     return;
   1146             }
   1147 
   1148             equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
   1149             return;
   1150         }
   1151         if (renderer->isBox()) {
   1152             inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
   1153             if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
   1154                 return;
   1155         }
   1156     } else {
   1157         RenderText* textRenderer = toRenderText(renderer);
   1158 
   1159         InlineTextBox* box;
   1160         InlineTextBox* candidate = 0;
   1161 
   1162         for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
   1163             int caretMinOffset = box->caretMinOffset();
   1164             int caretMaxOffset = box->caretMaxOffset();
   1165 
   1166             if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
   1167                 continue;
   1168 
   1169             if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
   1170                 inlineBox = box;
   1171                 return;
   1172             }
   1173 
   1174             if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
   1175                 || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
   1176                 || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
   1177                 break;
   1178 
   1179             candidate = box;
   1180         }
   1181         if (candidate && candidate == textRenderer->lastTextBox() && affinity == DOWNSTREAM) {
   1182             box = searchAheadForBetterMatch(textRenderer);
   1183             if (box)
   1184                 caretOffset = box->caretMinOffset();
   1185         }
   1186         inlineBox = box ? box : candidate;
   1187     }
   1188 
   1189     if (!inlineBox)
   1190         return;
   1191 
   1192     unsigned char level = inlineBox->bidiLevel();
   1193 
   1194     if (inlineBox->direction() == primaryDirection) {
   1195         if (caretOffset == inlineBox->caretRightmostOffset()) {
   1196             InlineBox* nextBox = inlineBox->nextLeafChild();
   1197             if (!nextBox || nextBox->bidiLevel() >= level)
   1198                 return;
   1199 
   1200             level = nextBox->bidiLevel();
   1201             InlineBox* prevBox = inlineBox;
   1202             do {
   1203                 prevBox = prevBox->prevLeafChild();
   1204             } while (prevBox && prevBox->bidiLevel() > level);
   1205 
   1206             if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
   1207                 return;
   1208 
   1209             // For example, abc 123 ^ CBA
   1210             while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
   1211                 if (nextBox->bidiLevel() < level)
   1212                     break;
   1213                 inlineBox = nextBox;
   1214             }
   1215             caretOffset = inlineBox->caretRightmostOffset();
   1216         } else {
   1217             InlineBox* prevBox = inlineBox->prevLeafChild();
   1218             if (!prevBox || prevBox->bidiLevel() >= level)
   1219                 return;
   1220 
   1221             level = prevBox->bidiLevel();
   1222             InlineBox* nextBox = inlineBox;
   1223             do {
   1224                 nextBox = nextBox->nextLeafChild();
   1225             } while (nextBox && nextBox->bidiLevel() > level);
   1226 
   1227             if (nextBox && nextBox->bidiLevel() == level)
   1228                 return;
   1229 
   1230             while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
   1231                 if (prevBox->bidiLevel() < level)
   1232                     break;
   1233                 inlineBox = prevBox;
   1234             }
   1235             caretOffset = inlineBox->caretLeftmostOffset();
   1236         }
   1237         return;
   1238     }
   1239 
   1240     if (caretOffset == inlineBox->caretLeftmostOffset()) {
   1241         InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
   1242         if (!prevBox || prevBox->bidiLevel() < level) {
   1243             // Left edge of a secondary run. Set to the right edge of the entire run.
   1244             while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
   1245                 if (nextBox->bidiLevel() < level)
   1246                     break;
   1247                 inlineBox = nextBox;
   1248             }
   1249             caretOffset = inlineBox->caretRightmostOffset();
   1250         } else if (prevBox->bidiLevel() > level) {
   1251             // Right edge of a "tertiary" run. Set to the left edge of that run.
   1252             while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
   1253                 if (tertiaryBox->bidiLevel() <= level)
   1254                     break;
   1255                 inlineBox = tertiaryBox;
   1256             }
   1257             caretOffset = inlineBox->caretLeftmostOffset();
   1258         }
   1259     } else {
   1260         InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
   1261         if (!nextBox || nextBox->bidiLevel() < level) {
   1262             // Right edge of a secondary run. Set to the left edge of the entire run.
   1263             while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
   1264                 if (prevBox->bidiLevel() < level)
   1265                     break;
   1266                 inlineBox = prevBox;
   1267             }
   1268             if (m_anchorNode->selfOrAncestorHasDirAutoAttribute())
   1269                 caretOffset = inlineBox->bidiLevel() < level ? inlineBox->caretLeftmostOffset() : inlineBox->caretRightmostOffset();
   1270             else
   1271                 caretOffset = inlineBox->caretLeftmostOffset();
   1272         } else if (nextBox->bidiLevel() > level) {
   1273             // Left edge of a "tertiary" run. Set to the right edge of that run.
   1274             while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
   1275                 if (tertiaryBox->bidiLevel() <= level)
   1276                     break;
   1277                 inlineBox = tertiaryBox;
   1278             }
   1279             caretOffset = inlineBox->caretRightmostOffset();
   1280         }
   1281     }
   1282 }
   1283 
   1284 TextDirection Position::primaryDirection() const
   1285 {
   1286     TextDirection primaryDirection = LTR;
   1287     for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) {
   1288         if (r->isRenderBlockFlow()) {
   1289             primaryDirection = r->style()->direction();
   1290             break;
   1291         }
   1292     }
   1293 
   1294     return primaryDirection;
   1295 }
   1296 
   1297 void Position::trace(Visitor* visitor)
   1298 {
   1299     visitor->trace(m_anchorNode);
   1300 }
   1301 
   1302 void Position::debugPosition(const char* msg) const
   1303 {
   1304     if (isNull())
   1305         fprintf(stderr, "Position [%s]: null\n", msg);
   1306     else
   1307         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, deprecatedNode()->nodeName().utf8().data(), deprecatedNode(), m_offset);
   1308 }
   1309 
   1310 #ifndef NDEBUG
   1311 
   1312 void Position::formatForDebugger(char* buffer, unsigned length) const
   1313 {
   1314     StringBuilder result;
   1315 
   1316     if (isNull())
   1317         result.appendLiteral("<null>");
   1318     else {
   1319         char s[1024];
   1320         result.appendLiteral("offset ");
   1321         result.appendNumber(m_offset);
   1322         result.appendLiteral(" of ");
   1323         deprecatedNode()->formatForDebugger(s, sizeof(s));
   1324         result.append(s);
   1325     }
   1326 
   1327     strncpy(buffer, result.toString().utf8().data(), length - 1);
   1328 }
   1329 
   1330 void Position::showAnchorTypeAndOffset() const
   1331 {
   1332     if (m_isLegacyEditingPosition)
   1333         fputs("legacy, ", stderr);
   1334     switch (anchorType()) {
   1335     case PositionIsOffsetInAnchor:
   1336         fputs("offset", stderr);
   1337         break;
   1338     case PositionIsBeforeChildren:
   1339         fputs("beforeChildren", stderr);
   1340         break;
   1341     case PositionIsAfterChildren:
   1342         fputs("afterChildren", stderr);
   1343         break;
   1344     case PositionIsBeforeAnchor:
   1345         fputs("before", stderr);
   1346         break;
   1347     case PositionIsAfterAnchor:
   1348         fputs("after", stderr);
   1349         break;
   1350     }
   1351     fprintf(stderr, ", offset:%d\n", m_offset);
   1352 }
   1353 
   1354 void Position::showTreeForThis() const
   1355 {
   1356     if (anchorNode()) {
   1357         anchorNode()->showTreeForThis();
   1358         showAnchorTypeAndOffset();
   1359     }
   1360 }
   1361 
   1362 #endif
   1363 
   1364 
   1365 
   1366 } // namespace WebCore
   1367 
   1368 #ifndef NDEBUG
   1369 
   1370 void showTree(const WebCore::Position& pos)
   1371 {
   1372     pos.showTreeForThis();
   1373 }
   1374 
   1375 void showTree(const WebCore::Position* pos)
   1376 {
   1377     if (pos)
   1378         pos->showTreeForThis();
   1379 }
   1380 
   1381 #endif
   1382