Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 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/editing/VisibleUnits.h"
     28 
     29 #include "bindings/v8/ExceptionState.h"
     30 #include "bindings/v8/ExceptionStatePlaceholder.h"
     31 #include "core/HTMLNames.h"
     32 #include "core/dom/Document.h"
     33 #include "core/dom/Element.h"
     34 #include "core/dom/NodeTraversal.h"
     35 #include "core/dom/Position.h"
     36 #include "core/dom/Text.h"
     37 #include "core/editing/RenderedPosition.h"
     38 #include "core/editing/TextIterator.h"
     39 #include "core/editing/VisiblePosition.h"
     40 #include "core/editing/htmlediting.h"
     41 #include "core/html/HTMLBRElement.h"
     42 #include "core/rendering/InlineTextBox.h"
     43 #include "core/rendering/RenderBlockFlow.h"
     44 #include "core/rendering/RenderObject.h"
     45 #include "platform/RuntimeEnabledFeatures.h"
     46 #include "platform/heap/Handle.h"
     47 #include "platform/text/TextBoundaries.h"
     48 
     49 namespace WebCore {
     50 
     51 using namespace HTMLNames;
     52 using namespace WTF::Unicode;
     53 
     54 static Node* previousLeafWithSameEditability(Node* node, EditableType editableType)
     55 {
     56     bool editable = node->rendererIsEditable(editableType);
     57     node = node->previousLeafNode();
     58     while (node) {
     59         if (editable == node->rendererIsEditable(editableType))
     60             return node;
     61         node = node->previousLeafNode();
     62     }
     63     return 0;
     64 }
     65 
     66 static Node* nextLeafWithSameEditability(Node* node, EditableType editableType = ContentIsEditable)
     67 {
     68     if (!node)
     69         return 0;
     70 
     71     bool editable = node->rendererIsEditable(editableType);
     72     node = node->nextLeafNode();
     73     while (node) {
     74         if (editable == node->rendererIsEditable(editableType))
     75             return node;
     76         node = node->nextLeafNode();
     77     }
     78     return 0;
     79 }
     80 
     81 // FIXME: consolidate with code in previousLinePosition.
     82 static Position previousRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
     83 {
     84     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
     85     Node* previousNode = previousLeafWithSameEditability(node, editableType);
     86 
     87     while (previousNode && (!previousNode->renderer() || inSameLine(VisiblePosition(firstPositionInOrBeforeNode(previousNode)), visiblePosition)))
     88         previousNode = previousLeafWithSameEditability(previousNode, editableType);
     89 
     90     while (previousNode && !previousNode->isShadowRoot()) {
     91         if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), editableType) != highestRoot)
     92             break;
     93 
     94         Position pos = isHTMLBRElement(*previousNode) ? positionBeforeNode(previousNode) :
     95             createLegacyEditingPosition(previousNode, caretMaxOffset(previousNode));
     96 
     97         if (pos.isCandidate())
     98             return pos;
     99 
    100         previousNode = previousLeafWithSameEditability(previousNode, editableType);
    101     }
    102     return Position();
    103 }
    104 
    105 static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
    106 {
    107     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
    108     Node* nextNode = nextLeafWithSameEditability(node, editableType);
    109     while (nextNode && (!nextNode->renderer() || inSameLine(VisiblePosition(firstPositionInOrBeforeNode(nextNode)), visiblePosition)))
    110         nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable);
    111 
    112     while (nextNode && !nextNode->isShadowRoot()) {
    113         if (highestEditableRoot(firstPositionInOrBeforeNode(nextNode), editableType) != highestRoot)
    114             break;
    115 
    116         Position pos;
    117         pos = createLegacyEditingPosition(nextNode, caretMinOffset(nextNode));
    118 
    119         if (pos.isCandidate())
    120             return pos;
    121 
    122         nextNode = nextLeafWithSameEditability(nextNode, editableType);
    123     }
    124     return Position();
    125 }
    126 
    127 class CachedLogicallyOrderedLeafBoxes {
    128 public:
    129     CachedLogicallyOrderedLeafBoxes();
    130 
    131     const InlineTextBox* previousTextBox(const RootInlineBox*, const InlineTextBox*);
    132     const InlineTextBox* nextTextBox(const RootInlineBox*, const InlineTextBox*);
    133 
    134     size_t size() const { return m_leafBoxes.size(); }
    135     const InlineBox* firstBox() const { return m_leafBoxes[0]; }
    136 
    137 private:
    138     const Vector<InlineBox*>& collectBoxes(const RootInlineBox*);
    139     int boxIndexInLeaves(const InlineTextBox*) const;
    140 
    141     const RootInlineBox* m_rootInlineBox;
    142     Vector<InlineBox*> m_leafBoxes;
    143 };
    144 
    145 CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes() : m_rootInlineBox(0) { };
    146 
    147 const InlineTextBox* CachedLogicallyOrderedLeafBoxes::previousTextBox(const RootInlineBox* root, const InlineTextBox* box)
    148 {
    149     if (!root)
    150         return 0;
    151 
    152     collectBoxes(root);
    153 
    154     // If box is null, root is box's previous RootInlineBox, and previousBox is the last logical box in root.
    155     int boxIndex = m_leafBoxes.size() - 1;
    156     if (box)
    157         boxIndex = boxIndexInLeaves(box) - 1;
    158 
    159     for (int i = boxIndex; i >= 0; --i) {
    160         if (m_leafBoxes[i]->isInlineTextBox())
    161             return toInlineTextBox(m_leafBoxes[i]);
    162     }
    163 
    164     return 0;
    165 }
    166 
    167 const InlineTextBox* CachedLogicallyOrderedLeafBoxes::nextTextBox(const RootInlineBox* root, const InlineTextBox* box)
    168 {
    169     if (!root)
    170         return 0;
    171 
    172     collectBoxes(root);
    173 
    174     // If box is null, root is box's next RootInlineBox, and nextBox is the first logical box in root.
    175     // Otherwise, root is box's RootInlineBox, and nextBox is the next logical box in the same line.
    176     size_t nextBoxIndex = 0;
    177     if (box)
    178         nextBoxIndex = boxIndexInLeaves(box) + 1;
    179 
    180     for (size_t i = nextBoxIndex; i < m_leafBoxes.size(); ++i) {
    181         if (m_leafBoxes[i]->isInlineTextBox())
    182             return toInlineTextBox(m_leafBoxes[i]);
    183     }
    184 
    185     return 0;
    186 }
    187 
    188 const Vector<InlineBox*>& CachedLogicallyOrderedLeafBoxes::collectBoxes(const RootInlineBox* root)
    189 {
    190     if (m_rootInlineBox != root) {
    191         m_rootInlineBox = root;
    192         m_leafBoxes.clear();
    193         root->collectLeafBoxesInLogicalOrder(m_leafBoxes);
    194     }
    195     return m_leafBoxes;
    196 }
    197 
    198 int CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves(const InlineTextBox* box) const
    199 {
    200     for (size_t i = 0; i < m_leafBoxes.size(); ++i) {
    201         if (box == m_leafBoxes[i])
    202             return i;
    203     }
    204     return 0;
    205 }
    206 
    207 static const InlineTextBox* logicallyPreviousBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    208     bool& previousBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    209 {
    210     const InlineBox* startBox = textBox;
    211 
    212     const InlineTextBox* previousBox = leafBoxes.previousTextBox(&startBox->root(), textBox);
    213     if (previousBox)
    214         return previousBox;
    215 
    216     previousBox = leafBoxes.previousTextBox(startBox->root().prevRootBox(), 0);
    217     if (previousBox)
    218         return previousBox;
    219 
    220     while (1) {
    221         Node* startNode = startBox->renderer().nonPseudoNode();
    222         if (!startNode)
    223             break;
    224 
    225         Position position = previousRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
    226         if (position.isNull())
    227             break;
    228 
    229         RenderedPosition renderedPosition(position, DOWNSTREAM);
    230         RootInlineBox* previousRoot = renderedPosition.rootBox();
    231         if (!previousRoot)
    232             break;
    233 
    234         previousBox = leafBoxes.previousTextBox(previousRoot, 0);
    235         if (previousBox) {
    236             previousBoxInDifferentBlock = true;
    237             return previousBox;
    238         }
    239 
    240         if (!leafBoxes.size())
    241             break;
    242         startBox = leafBoxes.firstBox();
    243     }
    244     return 0;
    245 }
    246 
    247 
    248 static const InlineTextBox* logicallyNextBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    249     bool& nextBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    250 {
    251     const InlineBox* startBox = textBox;
    252 
    253     const InlineTextBox* nextBox = leafBoxes.nextTextBox(&startBox->root(), textBox);
    254     if (nextBox)
    255         return nextBox;
    256 
    257     nextBox = leafBoxes.nextTextBox(startBox->root().nextRootBox(), 0);
    258     if (nextBox)
    259         return nextBox;
    260 
    261     while (1) {
    262         Node* startNode =startBox->renderer().nonPseudoNode();
    263         if (!startNode)
    264             break;
    265 
    266         Position position = nextRootInlineBoxCandidatePosition(startNode, visiblePosition, ContentIsEditable);
    267         if (position.isNull())
    268             break;
    269 
    270         RenderedPosition renderedPosition(position, DOWNSTREAM);
    271         RootInlineBox* nextRoot = renderedPosition.rootBox();
    272         if (!nextRoot)
    273             break;
    274 
    275         nextBox = leafBoxes.nextTextBox(nextRoot, 0);
    276         if (nextBox) {
    277             nextBoxInDifferentBlock = true;
    278             return nextBox;
    279         }
    280 
    281         if (!leafBoxes.size())
    282             break;
    283         startBox = leafBoxes.firstBox();
    284     }
    285     return 0;
    286 }
    287 
    288 static TextBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    289     int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    290 {
    291     previousBoxInDifferentBlock = false;
    292 
    293     // FIXME: Handle the case when we don't have an inline text box.
    294     const InlineTextBox* previousBox = logicallyPreviousBox(visiblePosition, textBox, previousBoxInDifferentBlock, leafBoxes);
    295 
    296     int len = 0;
    297     string.clear();
    298     if (previousBox) {
    299         previousBoxLength = previousBox->len();
    300         previousBox->textRenderer().text().appendTo(string, previousBox->start(), previousBoxLength);
    301         len += previousBoxLength;
    302     }
    303     textBox->textRenderer().text().appendTo(string, textBox->start(), textBox->len());
    304     len += textBox->len();
    305 
    306     return wordBreakIterator(string.data(), len);
    307 }
    308 
    309 static TextBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
    310     bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
    311 {
    312     nextBoxInDifferentBlock = false;
    313 
    314     // FIXME: Handle the case when we don't have an inline text box.
    315     const InlineTextBox* nextBox = logicallyNextBox(visiblePosition, textBox, nextBoxInDifferentBlock, leafBoxes);
    316 
    317     int len = 0;
    318     string.clear();
    319     textBox->textRenderer().text().appendTo(string, textBox->start(), textBox->len());
    320     len += textBox->len();
    321     if (nextBox) {
    322         nextBox->textRenderer().text().appendTo(string, nextBox->start(), nextBox->len());
    323         len += nextBox->len();
    324     }
    325 
    326     return wordBreakIterator(string.data(), len);
    327 }
    328 
    329 static bool isLogicalStartOfWord(TextBreakIterator* iter, int position, bool hardLineBreak)
    330 {
    331     bool boundary = hardLineBreak ? true : iter->isBoundary(position);
    332     if (!boundary)
    333         return false;
    334 
    335     iter->following(position);
    336     // isWordTextBreak returns true after moving across a word and false after moving across a punctuation/space.
    337     return isWordTextBreak(iter);
    338 }
    339 
    340 static bool islogicalEndOfWord(TextBreakIterator* iter, int position, bool hardLineBreak)
    341 {
    342     bool boundary = iter->isBoundary(position);
    343     return (hardLineBreak || boundary) && isWordTextBreak(iter);
    344 }
    345 
    346 enum CursorMovementDirection { MoveLeft, MoveRight };
    347 
    348 static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition, CursorMovementDirection direction,
    349     bool skipsSpaceWhenMovingRight)
    350 {
    351     if (visiblePosition.isNull())
    352         return VisiblePosition();
    353 
    354     TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
    355     InlineBox* previouslyVisitedBox = 0;
    356     VisiblePosition current = visiblePosition;
    357     TextBreakIterator* iter = 0;
    358 
    359     CachedLogicallyOrderedLeafBoxes leafBoxes;
    360     Vector<UChar, 1024> string;
    361 
    362     while (1) {
    363         VisiblePosition adjacentCharacterPosition = direction == MoveRight ? current.right(true) : current.left(true);
    364         if (adjacentCharacterPosition == current || adjacentCharacterPosition.isNull())
    365             return VisiblePosition();
    366 
    367         InlineBox* box;
    368         int offsetInBox;
    369         adjacentCharacterPosition.deepEquivalent().getInlineBoxAndOffset(UPSTREAM, box, offsetInBox);
    370 
    371         if (!box)
    372             break;
    373         if (!box->isInlineTextBox()) {
    374             current = adjacentCharacterPosition;
    375             continue;
    376         }
    377 
    378         InlineTextBox* textBox = toInlineTextBox(box);
    379         int previousBoxLength = 0;
    380         bool previousBoxInDifferentBlock = false;
    381         bool nextBoxInDifferentBlock = false;
    382         bool movingIntoNewBox = previouslyVisitedBox != box;
    383 
    384         if (offsetInBox == box->caretMinOffset())
    385             iter = wordBreakIteratorForMinOffsetBoundary(visiblePosition, textBox, previousBoxLength, previousBoxInDifferentBlock, string, leafBoxes);
    386         else if (offsetInBox == box->caretMaxOffset())
    387             iter = wordBreakIteratorForMaxOffsetBoundary(visiblePosition, textBox, nextBoxInDifferentBlock, string, leafBoxes);
    388         else if (movingIntoNewBox) {
    389             iter = wordBreakIterator(textBox->textRenderer().text(), textBox->start(), textBox->len());
    390             previouslyVisitedBox = box;
    391         }
    392 
    393         if (!iter)
    394             break;
    395 
    396         iter->first();
    397         int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength;
    398 
    399         bool isWordBreak;
    400         bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection;
    401         bool movingBackward = (direction == MoveLeft && box->direction() == LTR) || (direction == MoveRight && box->direction() == RTL);
    402         if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock)
    403             || (!skipsSpaceWhenMovingRight && movingBackward)) {
    404             bool logicalStartInRenderer = offsetInBox == static_cast<int>(textBox->start()) && previousBoxInDifferentBlock;
    405             isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, logicalStartInRenderer);
    406         } else {
    407             bool logicalEndInRenderer = offsetInBox == static_cast<int>(textBox->start() + textBox->len()) && nextBoxInDifferentBlock;
    408             isWordBreak = islogicalEndOfWord(iter, offsetInIterator, logicalEndInRenderer);
    409         }
    410 
    411         if (isWordBreak)
    412             return adjacentCharacterPosition;
    413 
    414         current = adjacentCharacterPosition;
    415     }
    416     return VisiblePosition();
    417 }
    418 
    419 VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
    420 {
    421     VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight);
    422     leftWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(leftWordBreak);
    423 
    424     // FIXME: How should we handle a non-editable position?
    425     if (leftWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquivalent())) {
    426         TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
    427         leftWordBreak = blockDirection == LTR ? startOfEditableContent(visiblePosition) : endOfEditableContent(visiblePosition);
    428     }
    429     return leftWordBreak;
    430 }
    431 
    432 VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
    433 {
    434     VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight);
    435     rightWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(rightWordBreak);
    436 
    437     // FIXME: How should we handle a non-editable position?
    438     if (rightWordBreak.isNull() && isEditablePosition(visiblePosition.deepEquivalent())) {
    439         TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
    440         rightWordBreak = blockDirection == LTR ? endOfEditableContent(visiblePosition) : startOfEditableContent(visiblePosition);
    441     }
    442     return rightWordBreak;
    443 }
    444 
    445 
    446 enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
    447 
    448 typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsigned offset, BoundarySearchContextAvailability, bool& needMoreContext);
    449 
    450 static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
    451 {
    452     Position pos = c.deepEquivalent();
    453     Node* boundary = pos.parentEditingBoundary();
    454     if (!boundary)
    455         return VisiblePosition();
    456 
    457     Document& d = boundary->document();
    458     Position start = createLegacyEditingPosition(boundary, 0).parentAnchoredEquivalent();
    459     Position end = pos.parentAnchoredEquivalent();
    460     RefPtrWillBeRawPtr<Range> searchRange = Range::create(d);
    461 
    462     Vector<UChar, 1024> string;
    463     unsigned suffixLength = 0;
    464 
    465     TrackExceptionState exceptionState;
    466     if (requiresContextForWordBoundary(c.characterBefore())) {
    467         RefPtrWillBeRawPtr<Range> forwardsScanRange(d.createRange());
    468         forwardsScanRange->setEndAfter(boundary, exceptionState);
    469         forwardsScanRange->setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), exceptionState);
    470         TextIterator forwardsIterator(forwardsScanRange.get());
    471         while (!forwardsIterator.atEnd()) {
    472             Vector<UChar, 1024> characters;
    473             forwardsIterator.appendTextTo(characters);
    474             int i = endOfFirstWordBoundaryContext(characters.data(), characters.size());
    475             string.append(characters.data(), i);
    476             suffixLength += i;
    477             if (static_cast<unsigned>(i) < characters.size())
    478                 break;
    479             forwardsIterator.advance();
    480         }
    481     }
    482 
    483     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), exceptionState);
    484     searchRange->setEnd(end.deprecatedNode(), end.deprecatedEditingOffset(), exceptionState);
    485 
    486     ASSERT(!exceptionState.hadException());
    487     if (exceptionState.hadException())
    488         return VisiblePosition();
    489 
    490     SimplifiedBackwardsTextIterator it(searchRange.get());
    491     unsigned next = 0;
    492     bool needMoreContext = false;
    493     while (!it.atEnd()) {
    494         bool inTextSecurityMode = it.node() && it.node()->renderer() && it.node()->renderer()->style()->textSecurity() != TSNONE;
    495         // iterate to get chunks until the searchFunction returns a non-zero value.
    496         if (!inTextSecurityMode)
    497             it.prependTextTo(string);
    498         else {
    499             // Treat bullets used in the text security mode as regular characters when looking for boundaries
    500             Vector<UChar, 1024> iteratorString;
    501             iteratorString.fill('x', it.length());
    502             string.prepend(iteratorString.data(), iteratorString.size());
    503         }
    504         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
    505         if (next)
    506             break;
    507         it.advance();
    508     }
    509     if (needMoreContext) {
    510         // The last search returned the beginning of the buffer and asked for more context,
    511         // but there is no earlier text. Force a search with what's available.
    512         next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
    513         ASSERT(!needMoreContext);
    514     }
    515 
    516     if (!next)
    517         return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM);
    518 
    519     Node* node = it.range()->startContainer();
    520     if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
    521         // The next variable contains a usable index into a text node
    522         return VisiblePosition(createLegacyEditingPosition(node, next), DOWNSTREAM);
    523 
    524     // Use the character iterator to translate the next value into a DOM position.
    525     BackwardsCharacterIterator charIt(searchRange.get());
    526     charIt.advance(string.size() - suffixLength - next);
    527     // FIXME: charIt can get out of shadow host.
    528     return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM);
    529 }
    530 
    531 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
    532 {
    533     Position pos = c.deepEquivalent();
    534     Node* boundary = pos.parentEditingBoundary();
    535     if (!boundary)
    536         return VisiblePosition();
    537 
    538     Document& d = boundary->document();
    539     RefPtrWillBeRawPtr<Range> searchRange(d.createRange());
    540     Position start(pos.parentAnchoredEquivalent());
    541 
    542     Vector<UChar, 1024> string;
    543     unsigned prefixLength = 0;
    544 
    545     if (requiresContextForWordBoundary(c.characterAfter())) {
    546         RefPtrWillBeRawPtr<Range> backwardsScanRange(d.createRange());
    547         backwardsScanRange->setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
    548         SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get());
    549         while (!backwardsIterator.atEnd()) {
    550             Vector<UChar, 1024> characters;
    551             backwardsIterator.prependTextTo(characters);
    552             int length = characters.size();
    553             int i = startOfLastWordBoundaryContext(characters.data(), length);
    554             string.prepend(characters.data() + i, length - i);
    555             prefixLength += length - i;
    556             if (i > 0)
    557                 break;
    558             backwardsIterator.advance();
    559         }
    560     }
    561 
    562     searchRange->selectNodeContents(boundary, IGNORE_EXCEPTION);
    563     searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
    564     TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
    565     const unsigned invalidOffset = static_cast<unsigned>(-1);
    566     unsigned next = invalidOffset;
    567     bool needMoreContext = false;
    568     while (!it.atEnd()) {
    569         // Keep asking the iterator for chunks until the search function
    570         // returns an end value not equal to the length of the string passed to it.
    571         bool inTextSecurityMode = it.node() && it.node()->renderer() && it.node()->renderer()->style()->textSecurity() != TSNONE;
    572         if (!inTextSecurityMode)
    573             it.appendTextTo(string);
    574         else {
    575             // Treat bullets used in the text security mode as regular characters when looking for boundaries
    576             Vector<UChar, 1024> iteratorString;
    577             iteratorString.fill('x', it.length());
    578             string.append(iteratorString.data(), iteratorString.size());
    579         }
    580         next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext);
    581         if (next != string.size())
    582             break;
    583         it.advance();
    584     }
    585     if (needMoreContext) {
    586         // The last search returned the end of the buffer and asked for more context,
    587         // but there is no further text. Force a search with what's available.
    588         next = searchFunction(string.data(), string.size(), prefixLength, DontHaveMoreContext, needMoreContext);
    589         ASSERT(!needMoreContext);
    590     }
    591 
    592     if (it.atEnd() && next == string.size()) {
    593         pos = it.range()->startPosition();
    594     } else if (next != invalidOffset && next != prefixLength) {
    595         // Use the character iterator to translate the next value into a DOM position.
    596         CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
    597         charIt.advance(next - prefixLength - 1);
    598         RefPtrWillBeRawPtr<Range> characterRange = charIt.range();
    599         pos = characterRange->endPosition();
    600 
    601         if (charIt.characterAt(0) == '\n') {
    602             // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
    603             VisiblePosition visPos = VisiblePosition(pos);
    604             if (visPos == VisiblePosition(characterRange->startPosition())) {
    605                 charIt.advance(1);
    606                 pos = charIt.range()->startPosition();
    607             }
    608         }
    609     }
    610 
    611     // generate VisiblePosition, use UPSTREAM affinity if possible
    612     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
    613 }
    614 
    615 // ---------
    616 
    617 static unsigned startWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
    618 {
    619     ASSERT(offset);
    620     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
    621         needMoreContext = true;
    622         return 0;
    623     }
    624     needMoreContext = false;
    625     int start, end;
    626     U16_BACK_1(characters, 0, offset);
    627     findWordBoundary(characters, length, offset, &start, &end);
    628     return start;
    629 }
    630 
    631 VisiblePosition startOfWord(const VisiblePosition &c, EWordSide side)
    632 {
    633     // FIXME: This returns a null VP for c at the start of the document
    634     // and side == LeftWordIfOnBoundary
    635     VisiblePosition p = c;
    636     if (side == RightWordIfOnBoundary) {
    637         // at paragraph end, the startofWord is the current position
    638         if (isEndOfParagraph(c))
    639             return c;
    640 
    641         p = c.next();
    642         if (p.isNull())
    643             return c;
    644     }
    645     return previousBoundary(p, startWordBoundary);
    646 }
    647 
    648 static unsigned endWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
    649 {
    650     ASSERT(offset <= length);
    651     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
    652         needMoreContext = true;
    653         return length;
    654     }
    655     needMoreContext = false;
    656     int start, end;
    657     findWordBoundary(characters, length, offset, &start, &end);
    658     return end;
    659 }
    660 
    661 VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
    662 {
    663     VisiblePosition p = c;
    664     if (side == LeftWordIfOnBoundary) {
    665         if (isStartOfParagraph(c))
    666             return c;
    667 
    668         p = c.previous();
    669         if (p.isNull())
    670             return c;
    671     } else if (isEndOfParagraph(c))
    672         return c;
    673 
    674     return nextBoundary(p, endWordBoundary);
    675 }
    676 
    677 static unsigned previousWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
    678 {
    679     if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
    680         needMoreContext = true;
    681         return 0;
    682     }
    683     needMoreContext = false;
    684     return findNextWordFromIndex(characters, length, offset, false);
    685 }
    686 
    687 VisiblePosition previousWordPosition(const VisiblePosition &c)
    688 {
    689     VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
    690     return c.honorEditingBoundaryAtOrBefore(prev);
    691 }
    692 
    693 static unsigned nextWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
    694 {
    695     if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
    696         needMoreContext = true;
    697         return length;
    698     }
    699     needMoreContext = false;
    700     return findNextWordFromIndex(characters, length, offset, true);
    701 }
    702 
    703 VisiblePosition nextWordPosition(const VisiblePosition &c)
    704 {
    705     VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);
    706     return c.honorEditingBoundaryAtOrAfter(next);
    707 }
    708 
    709 // ---------
    710 
    711 enum LineEndpointComputationMode { UseLogicalOrdering, UseInlineBoxOrdering };
    712 static VisiblePosition startPositionForLine(const VisiblePosition& c, LineEndpointComputationMode mode)
    713 {
    714     if (c.isNull())
    715         return VisiblePosition();
    716 
    717     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
    718     if (!rootBox) {
    719         // There are VisiblePositions at offset 0 in blocks without
    720         // RootInlineBoxes, like empty editable blocks and bordered blocks.
    721         Position p = c.deepEquivalent();
    722         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
    723             return c;
    724 
    725         return VisiblePosition();
    726     }
    727 
    728     Node* startNode;
    729     InlineBox* startBox;
    730     if (mode == UseLogicalOrdering) {
    731         startNode = rootBox->getLogicalStartBoxWithNode(startBox);
    732         if (!startNode)
    733             return VisiblePosition();
    734     } else {
    735         // Generated content (e.g. list markers and CSS :before and :after pseudoelements) have no corresponding DOM element,
    736         // and so cannot be represented by a VisiblePosition. Use whatever follows instead.
    737         startBox = rootBox->firstLeafChild();
    738         while (true) {
    739             if (!startBox)
    740                 return VisiblePosition();
    741 
    742             startNode = startBox->renderer().nonPseudoNode();
    743             if (startNode)
    744                 break;
    745 
    746             startBox = startBox->nextLeafChild();
    747         }
    748     }
    749 
    750     return VisiblePosition(startNode->isTextNode() ? Position(toText(startNode), toInlineTextBox(startBox)->start()) : positionBeforeNode(startNode));
    751 }
    752 
    753 static VisiblePosition startOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
    754 {
    755     // TODO: this is the current behavior that might need to be fixed.
    756     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
    757     VisiblePosition visPos = startPositionForLine(c, mode);
    758 
    759     if (mode == UseLogicalOrdering) {
    760         if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
    761             if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
    762                 return VisiblePosition(firstPositionInNode(editableRoot));
    763         }
    764     }
    765 
    766     return c.honorEditingBoundaryAtOrBefore(visPos);
    767 }
    768 
    769 // FIXME: Rename this function to reflect the fact it ignores bidi levels.
    770 VisiblePosition startOfLine(const VisiblePosition& currentPosition)
    771 {
    772     return startOfLine(currentPosition, UseInlineBoxOrdering);
    773 }
    774 
    775 VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition)
    776 {
    777     return startOfLine(currentPosition, UseLogicalOrdering);
    778 }
    779 
    780 static VisiblePosition endPositionForLine(const VisiblePosition& c, LineEndpointComputationMode mode)
    781 {
    782     if (c.isNull())
    783         return VisiblePosition();
    784 
    785     RootInlineBox* rootBox = RenderedPosition(c).rootBox();
    786     if (!rootBox) {
    787         // There are VisiblePositions at offset 0 in blocks without
    788         // RootInlineBoxes, like empty editable blocks and bordered blocks.
    789         Position p = c.deepEquivalent();
    790         if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
    791             return c;
    792         return VisiblePosition();
    793     }
    794 
    795     Node* endNode;
    796     InlineBox* endBox;
    797     if (mode == UseLogicalOrdering) {
    798         endNode = rootBox->getLogicalEndBoxWithNode(endBox);
    799         if (!endNode)
    800             return VisiblePosition();
    801     } else {
    802         // Generated content (e.g. list markers and CSS :before and :after pseudoelements) have no corresponding DOM element,
    803         // and so cannot be represented by a VisiblePosition. Use whatever precedes instead.
    804         endBox = rootBox->lastLeafChild();
    805         while (true) {
    806             if (!endBox)
    807                 return VisiblePosition();
    808 
    809             endNode = endBox->renderer().nonPseudoNode();
    810             if (endNode)
    811                 break;
    812 
    813             endBox = endBox->prevLeafChild();
    814         }
    815     }
    816 
    817     Position pos;
    818     if (isHTMLBRElement(*endNode))
    819         pos = positionBeforeNode(endNode);
    820     else if (endBox->isInlineTextBox() && endNode->isTextNode()) {
    821         InlineTextBox* endTextBox = toInlineTextBox(endBox);
    822         int endOffset = endTextBox->start();
    823         if (!endTextBox->isLineBreak())
    824             endOffset += endTextBox->len();
    825         pos = Position(toText(endNode), endOffset);
    826     } else
    827         pos = positionAfterNode(endNode);
    828 
    829     return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
    830 }
    831 
    832 static bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b)
    833 {
    834     return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
    835 }
    836 
    837 static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
    838 {
    839     // TODO: this is the current behavior that might need to be fixed.
    840     // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
    841     VisiblePosition visPos = endPositionForLine(c, mode);
    842 
    843     if (mode == UseLogicalOrdering) {
    844         // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end
    845         // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line.
    846         // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg
    847         // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
    848         // In this case, use the previous position of the computed logical end position.
    849         if (!inSameLogicalLine(c, visPos))
    850             visPos = visPos.previous();
    851 
    852         if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
    853             if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
    854                 return VisiblePosition(lastPositionInNode(editableRoot));
    855         }
    856 
    857         return c.honorEditingBoundaryAtOrAfter(visPos);
    858     }
    859 
    860     // Make sure the end of line is at the same line as the given input position. Else use the previous position to
    861     // obtain end of line. This condition happens when the input position is before the space character at the end
    862     // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position
    863     // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style
    864     // versus lines without that style, which would break before a space by default.
    865     if (!inSameLine(c, visPos)) {
    866         visPos = c.previous();
    867         if (visPos.isNull())
    868             return VisiblePosition();
    869         visPos = endPositionForLine(visPos, UseInlineBoxOrdering);
    870     }
    871 
    872     return c.honorEditingBoundaryAtOrAfter(visPos);
    873 }
    874 
    875 // FIXME: Rename this function to reflect the fact it ignores bidi levels.
    876 VisiblePosition endOfLine(const VisiblePosition& currentPosition)
    877 {
    878     return endOfLine(currentPosition, UseInlineBoxOrdering);
    879 }
    880 
    881 VisiblePosition logicalEndOfLine(const VisiblePosition& currentPosition)
    882 {
    883     return endOfLine(currentPosition, UseLogicalOrdering);
    884 }
    885 
    886 bool inSameLine(const VisiblePosition &a, const VisiblePosition &b)
    887 {
    888     return a.isNotNull() && startOfLine(a) == startOfLine(b);
    889 }
    890 
    891 bool isStartOfLine(const VisiblePosition &p)
    892 {
    893     return p.isNotNull() && p == startOfLine(p);
    894 }
    895 
    896 bool isEndOfLine(const VisiblePosition &p)
    897 {
    898     return p.isNotNull() && p == endOfLine(p);
    899 }
    900 
    901 static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineBox* root, int lineDirectionPoint)
    902 {
    903     ASSERT(root);
    904     RenderBlockFlow& containingBlock = root->block();
    905     FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint());
    906     if (containingBlock.hasOverflowClip())
    907         absoluteBlockPoint -= containingBlock.scrolledContentOffset();
    908 
    909     if (root->block().isHorizontalWritingMode())
    910         return IntPoint(lineDirectionPoint - absoluteBlockPoint.x(), root->blockDirectionPointInLine());
    911 
    912     return IntPoint(root->blockDirectionPointInLine(), lineDirectionPoint - absoluteBlockPoint.y());
    913 }
    914 
    915 VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint, EditableType editableType)
    916 {
    917     Position p = visiblePosition.deepEquivalent();
    918     Node* node = p.deprecatedNode();
    919 
    920     if (!node)
    921         return VisiblePosition();
    922 
    923     node->document().updateLayoutIgnorePendingStylesheets();
    924 
    925     RenderObject* renderer = node->renderer();
    926     if (!renderer)
    927         return VisiblePosition();
    928 
    929     RootInlineBox* root = 0;
    930     InlineBox* box;
    931     int ignoredCaretOffset;
    932     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
    933     if (box) {
    934         root = box->root().prevRootBox();
    935         // We want to skip zero height boxes.
    936         // This could happen in case it is a TrailingFloatsRootInlineBox.
    937         if (!root || !root->logicalHeight() || !root->firstLeafChild())
    938             root = 0;
    939     }
    940 
    941     if (!root) {
    942         Position position = previousRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
    943         if (position.isNotNull()) {
    944             RenderedPosition renderedPosition((VisiblePosition(position)));
    945             root = renderedPosition.rootBox();
    946             if (!root)
    947                 return VisiblePosition(position);
    948         }
    949     }
    950 
    951     if (root) {
    952         // FIXME: Can be wrong for multi-column layout and with transforms.
    953         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
    954         RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
    955         Node* node = renderer.node();
    956         if (node && editingIgnoresContent(node))
    957             return VisiblePosition(positionInParentBeforeNode(*node));
    958         return VisiblePosition(renderer.positionForPoint(pointInLine));
    959     }
    960 
    961     // Could not find a previous line. This means we must already be on the first line.
    962     // Move to the start of the content in this block, which effectively moves us
    963     // to the start of the line we're on.
    964     Element* rootElement = node->rendererIsEditable(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
    965     if (!rootElement)
    966         return VisiblePosition();
    967     return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
    968 }
    969 
    970 VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int lineDirectionPoint, EditableType editableType)
    971 {
    972     Position p = visiblePosition.deepEquivalent();
    973     Node* node = p.deprecatedNode();
    974 
    975     if (!node)
    976         return VisiblePosition();
    977 
    978     node->document().updateLayoutIgnorePendingStylesheets();
    979 
    980     RenderObject* renderer = node->renderer();
    981     if (!renderer)
    982         return VisiblePosition();
    983 
    984     RootInlineBox* root = 0;
    985     InlineBox* box;
    986     int ignoredCaretOffset;
    987     visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
    988     if (box) {
    989         root = box->root().nextRootBox();
    990         // We want to skip zero height boxes.
    991         // This could happen in case it is a TrailingFloatsRootInlineBox.
    992         if (!root || !root->logicalHeight() || !root->firstLeafChild())
    993             root = 0;
    994     }
    995 
    996     if (!root) {
    997         // FIXME: We need do the same in previousLinePosition.
    998         Node* child = node->traverseToChildAt(p.deprecatedEditingOffset());
    999         node = child ? child : &node->lastDescendantOrSelf();
   1000         Position position = nextRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
   1001         if (position.isNotNull()) {
   1002             RenderedPosition renderedPosition((VisiblePosition(position)));
   1003             root = renderedPosition.rootBox();
   1004             if (!root)
   1005                 return VisiblePosition(position);
   1006         }
   1007     }
   1008 
   1009     if (root) {
   1010         // FIXME: Can be wrong for multi-column layout and with transforms.
   1011         IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
   1012         RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
   1013         Node* node = renderer.node();
   1014         if (node && editingIgnoresContent(node))
   1015             return VisiblePosition(positionInParentBeforeNode(*node));
   1016         return VisiblePosition(renderer.positionForPoint(pointInLine));
   1017     }
   1018 
   1019     // Could not find a next line. This means we must already be on the last line.
   1020     // Move to the end of the content in this block, which effectively moves us
   1021     // to the end of the line we're on.
   1022     Element* rootElement = node->rendererIsEditable(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
   1023     if (!rootElement)
   1024         return VisiblePosition();
   1025     return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
   1026 }
   1027 
   1028 // ---------
   1029 
   1030 static unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
   1031 {
   1032     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
   1033     // FIXME: The following function can return -1; we don't handle that.
   1034     return iterator->preceding(length);
   1035 }
   1036 
   1037 VisiblePosition startOfSentence(const VisiblePosition &c)
   1038 {
   1039     return previousBoundary(c, startSentenceBoundary);
   1040 }
   1041 
   1042 static unsigned endSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
   1043 {
   1044     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
   1045     return iterator->next();
   1046 }
   1047 
   1048 // FIXME: This includes the space after the punctuation that marks the end of the sentence.
   1049 VisiblePosition endOfSentence(const VisiblePosition &c)
   1050 {
   1051     return nextBoundary(c, endSentenceBoundary);
   1052 }
   1053 
   1054 static unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
   1055 {
   1056     // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
   1057     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
   1058     // FIXME: The following function can return -1; we don't handle that.
   1059     return iterator->preceding(length);
   1060 }
   1061 
   1062 VisiblePosition previousSentencePosition(const VisiblePosition &c)
   1063 {
   1064     VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary);
   1065     return c.honorEditingBoundaryAtOrBefore(prev);
   1066 }
   1067 
   1068 static unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
   1069 {
   1070     // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs to
   1071     // move to the equivlant position in the following sentence.
   1072     TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
   1073     return iterator->following(0);
   1074 }
   1075 
   1076 VisiblePosition nextSentencePosition(const VisiblePosition &c)
   1077 {
   1078     VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);
   1079     return c.honorEditingBoundaryAtOrAfter(next);
   1080 }
   1081 
   1082 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
   1083 {
   1084     Position p = c.deepEquivalent();
   1085     Node* startNode = p.deprecatedNode();
   1086 
   1087     if (!startNode)
   1088         return VisiblePosition();
   1089 
   1090     if (isRenderedAsNonInlineTableImageOrHR(startNode))
   1091         return VisiblePosition(positionBeforeNode(startNode));
   1092 
   1093     Node* startBlock = enclosingBlock(startNode);
   1094 
   1095     Node* node = startNode;
   1096     Node* highestRoot = highestEditableRoot(p);
   1097     int offset = p.deprecatedEditingOffset();
   1098     Position::AnchorType type = p.anchorType();
   1099 
   1100     Node* n = startNode;
   1101     bool startNodeIsEditable = startNode->rendererIsEditable();
   1102     while (n) {
   1103         if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->rendererIsEditable() != startNodeIsEditable)
   1104             break;
   1105         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
   1106             while (n && n->rendererIsEditable() != startNodeIsEditable)
   1107                 n = NodeTraversal::previousPostOrder(*n, startBlock);
   1108             if (!n || !n->isDescendantOf(highestRoot))
   1109                 break;
   1110         }
   1111         RenderObject* r = n->renderer();
   1112         if (!r) {
   1113             n = NodeTraversal::previousPostOrder(*n, startBlock);
   1114             continue;
   1115         }
   1116         RenderStyle* style = r->style();
   1117         if (style->visibility() != VISIBLE) {
   1118             n = NodeTraversal::previousPostOrder(*n, startBlock);
   1119             continue;
   1120         }
   1121 
   1122         if (r->isBR() || isBlock(n))
   1123             break;
   1124 
   1125         if (r->isText() && toRenderText(r)->renderedTextLength()) {
   1126             ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode());
   1127             type = Position::PositionIsOffsetInAnchor;
   1128             if (style->preserveNewline()) {
   1129                 RenderText* text = toRenderText(r);
   1130                 int i = text->textLength();
   1131                 int o = offset;
   1132                 if (n == startNode && o < i)
   1133                     i = max(0, o);
   1134                 while (--i >= 0) {
   1135                     if ((*text)[i] == '\n')
   1136                         return VisiblePosition(Position(toText(n), i + 1), DOWNSTREAM);
   1137                 }
   1138             }
   1139             node = n;
   1140             offset = 0;
   1141             n = NodeTraversal::previousPostOrder(*n, startBlock);
   1142         } else if (editingIgnoresContent(n) || isRenderedTable(n)) {
   1143             node = n;
   1144             type = Position::PositionIsBeforeAnchor;
   1145             n = n->previousSibling() ? n->previousSibling() : NodeTraversal::previousPostOrder(*n, startBlock);
   1146         } else {
   1147             n = NodeTraversal::previousPostOrder(*n, startBlock);
   1148         }
   1149     }
   1150 
   1151     if (type == Position::PositionIsOffsetInAnchor) {
   1152         ASSERT(type == Position::PositionIsOffsetInAnchor || !offset);
   1153         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
   1154     }
   1155 
   1156     return VisiblePosition(Position(node, type), DOWNSTREAM);
   1157 }
   1158 
   1159 VisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossingRule boundaryCrossingRule)
   1160 {
   1161     if (c.isNull())
   1162         return VisiblePosition();
   1163 
   1164     Position p = c.deepEquivalent();
   1165     Node* startNode = p.deprecatedNode();
   1166 
   1167     if (isRenderedAsNonInlineTableImageOrHR(startNode))
   1168         return VisiblePosition(positionAfterNode(startNode));
   1169 
   1170     Node* startBlock = enclosingBlock(startNode);
   1171     Node* stayInsideBlock = startBlock;
   1172 
   1173     Node* node = startNode;
   1174     Node* highestRoot = highestEditableRoot(p);
   1175     int offset = p.deprecatedEditingOffset();
   1176     Position::AnchorType type = p.anchorType();
   1177 
   1178     Node* n = startNode;
   1179     bool startNodeIsEditable = startNode->rendererIsEditable();
   1180     while (n) {
   1181         if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->rendererIsEditable() != startNodeIsEditable)
   1182             break;
   1183         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
   1184             while (n && n->rendererIsEditable() != startNodeIsEditable)
   1185                 n = NodeTraversal::next(*n, stayInsideBlock);
   1186             if (!n || !n->isDescendantOf(highestRoot))
   1187                 break;
   1188         }
   1189 
   1190         RenderObject* r = n->renderer();
   1191         if (!r) {
   1192             n = NodeTraversal::next(*n, stayInsideBlock);
   1193             continue;
   1194         }
   1195         RenderStyle* style = r->style();
   1196         if (style->visibility() != VISIBLE) {
   1197             n = NodeTraversal::next(*n, stayInsideBlock);
   1198             continue;
   1199         }
   1200 
   1201         if (r->isBR() || isBlock(n))
   1202             break;
   1203 
   1204         // FIXME: We avoid returning a position where the renderer can't accept the caret.
   1205         if (r->isText() && toRenderText(r)->renderedTextLength()) {
   1206             ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode());
   1207             int length = toRenderText(r)->textLength();
   1208             type = Position::PositionIsOffsetInAnchor;
   1209             if (style->preserveNewline()) {
   1210                 RenderText* text = toRenderText(r);
   1211                 int o = n == startNode ? offset : 0;
   1212                 for (int i = o; i < length; ++i) {
   1213                     if ((*text)[i] == '\n')
   1214                         return VisiblePosition(Position(toText(n), i), DOWNSTREAM);
   1215                 }
   1216             }
   1217             node = n;
   1218             offset = r->caretMaxOffset();
   1219             n = NodeTraversal::next(*n, stayInsideBlock);
   1220         } else if (editingIgnoresContent(n) || isRenderedTable(n)) {
   1221             node = n;
   1222             type = Position::PositionIsAfterAnchor;
   1223             n = NodeTraversal::nextSkippingChildren(*n, stayInsideBlock);
   1224         } else {
   1225             n = NodeTraversal::next(*n, stayInsideBlock);
   1226         }
   1227     }
   1228 
   1229     if (type == Position::PositionIsOffsetInAnchor)
   1230         return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
   1231 
   1232     return VisiblePosition(Position(node, type), DOWNSTREAM);
   1233 }
   1234 
   1235 // FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
   1236 VisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition)
   1237 {
   1238     VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEditingBoundary));
   1239     VisiblePosition afterParagraphEnd(paragraphEnd.next(CannotCrossEditingBoundary));
   1240     // The position after the last position in the last cell of a table
   1241     // is not the start of the next paragraph.
   1242     if (isFirstPositionAfterTable(afterParagraphEnd))
   1243         return afterParagraphEnd.next(CannotCrossEditingBoundary);
   1244     return afterParagraphEnd;
   1245 }
   1246 
   1247 bool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b, EditingBoundaryCrossingRule boundaryCrossingRule)
   1248 {
   1249     return a.isNotNull() && startOfParagraph(a, boundaryCrossingRule) == startOfParagraph(b, boundaryCrossingRule);
   1250 }
   1251 
   1252 bool isStartOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
   1253 {
   1254     return pos.isNotNull() && pos == startOfParagraph(pos, boundaryCrossingRule);
   1255 }
   1256 
   1257 bool isEndOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
   1258 {
   1259     return pos.isNotNull() && pos == endOfParagraph(pos, boundaryCrossingRule);
   1260 }
   1261 
   1262 VisiblePosition previousParagraphPosition(const VisiblePosition& p, int x)
   1263 {
   1264     VisiblePosition pos = p;
   1265     do {
   1266         VisiblePosition n = previousLinePosition(pos, x);
   1267         if (n.isNull() || n == pos)
   1268             break;
   1269         pos = n;
   1270     } while (inSameParagraph(p, pos));
   1271     return pos;
   1272 }
   1273 
   1274 VisiblePosition nextParagraphPosition(const VisiblePosition& p, int x)
   1275 {
   1276     VisiblePosition pos = p;
   1277     do {
   1278         VisiblePosition n = nextLinePosition(pos, x);
   1279         if (n.isNull() || n == pos)
   1280             break;
   1281         pos = n;
   1282     } while (inSameParagraph(p, pos));
   1283     return pos;
   1284 }
   1285 
   1286 // ---------
   1287 
   1288 VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
   1289 {
   1290     Position position = visiblePosition.deepEquivalent();
   1291     Node* startBlock;
   1292     if (!position.containerNode() || !(startBlock = enclosingBlock(position.containerNode(), rule)))
   1293         return VisiblePosition();
   1294     return VisiblePosition(firstPositionInNode(startBlock));
   1295 }
   1296 
   1297 VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
   1298 {
   1299     Position position = visiblePosition.deepEquivalent();
   1300     Node* endBlock;
   1301     if (!position.containerNode() || !(endBlock = enclosingBlock(position.containerNode(), rule)))
   1302         return VisiblePosition();
   1303     return VisiblePosition(lastPositionInNode(endBlock));
   1304 }
   1305 
   1306 bool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
   1307 {
   1308     return !a.isNull() && enclosingBlock(a.deepEquivalent().containerNode()) == enclosingBlock(b.deepEquivalent().containerNode());
   1309 }
   1310 
   1311 bool isStartOfBlock(const VisiblePosition &pos)
   1312 {
   1313     return pos.isNotNull() && pos == startOfBlock(pos, CanCrossEditingBoundary);
   1314 }
   1315 
   1316 bool isEndOfBlock(const VisiblePosition &pos)
   1317 {
   1318     return pos.isNotNull() && pos == endOfBlock(pos, CanCrossEditingBoundary);
   1319 }
   1320 
   1321 // ---------
   1322 
   1323 VisiblePosition startOfDocument(const Node* node)
   1324 {
   1325     if (!node || !node->document().documentElement())
   1326         return VisiblePosition();
   1327 
   1328     return VisiblePosition(firstPositionInNode(node->document().documentElement()), DOWNSTREAM);
   1329 }
   1330 
   1331 VisiblePosition startOfDocument(const VisiblePosition &c)
   1332 {
   1333     return startOfDocument(c.deepEquivalent().deprecatedNode());
   1334 }
   1335 
   1336 VisiblePosition endOfDocument(const Node* node)
   1337 {
   1338     if (!node || !node->document().documentElement())
   1339         return VisiblePosition();
   1340 
   1341     Element* doc = node->document().documentElement();
   1342     return VisiblePosition(lastPositionInNode(doc), DOWNSTREAM);
   1343 }
   1344 
   1345 VisiblePosition endOfDocument(const VisiblePosition &c)
   1346 {
   1347     return endOfDocument(c.deepEquivalent().deprecatedNode());
   1348 }
   1349 
   1350 bool isStartOfDocument(const VisiblePosition &p)
   1351 {
   1352     return p.isNotNull() && p.previous(CanCrossEditingBoundary).isNull();
   1353 }
   1354 
   1355 bool isEndOfDocument(const VisiblePosition &p)
   1356 {
   1357     return p.isNotNull() && p.next(CanCrossEditingBoundary).isNull();
   1358 }
   1359 
   1360 // ---------
   1361 
   1362 VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
   1363 {
   1364     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
   1365     if (!highestRoot)
   1366         return VisiblePosition();
   1367 
   1368     return VisiblePosition(firstPositionInNode(highestRoot));
   1369 }
   1370 
   1371 VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
   1372 {
   1373     Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
   1374     if (!highestRoot)
   1375         return VisiblePosition();
   1376 
   1377     return VisiblePosition(lastPositionInNode(highestRoot));
   1378 }
   1379 
   1380 bool isEndOfEditableOrNonEditableContent(const VisiblePosition &p)
   1381 {
   1382     return p.isNotNull() && p.next().isNull();
   1383 }
   1384 
   1385 VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
   1386 {
   1387     return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
   1388 }
   1389 
   1390 VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
   1391 {
   1392     return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
   1393 }
   1394 
   1395 }
   1396