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