18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Element.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
32e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "Position.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderBlock.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderLayer.h"
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderObject.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextBoundaries.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextBreakIterator.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h"
39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "VisiblePosition.h"
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "VisibleSelection.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h"
428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <wtf/unicode/Unicode.h>
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianusing namespace WTF::Unicode;
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianenum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantypedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsigned offset, BoundarySearchContextAvailability, bool& needMoreContext);
525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = c.deepEquivalent();
56dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Node* boundary = pos.parentEditingBoundary();
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!boundary)
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
60dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Document* d = boundary->document();
61ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    Position start = Position(boundary, 0).parentAnchoredEquivalent();
62ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    Position end = pos.parentAnchoredEquivalent();
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Range> searchRange = Range::create(d);
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector<UChar, 1024> string;
668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    unsigned suffixLength = 0;
678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ExceptionCode ec = 0;
695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (requiresContextForWordBoundary(c.characterBefore())) {
708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RefPtr<Range> forwardsScanRange(d->createRange());
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        forwardsScanRange->setEndAfter(boundary, ec);
7281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        forwardsScanRange->setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        TextIterator forwardsIterator(forwardsScanRange.get());
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        while (!forwardsIterator.atEnd()) {
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            const UChar* characters = forwardsIterator.characters();
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            int length = forwardsIterator.length();
775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            int i = endOfFirstWordBoundaryContext(characters, length);
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            string.append(characters, i);
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            suffixLength += i;
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (i < length)
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                break;
828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            forwardsIterator.advance();
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
8781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    searchRange->setEnd(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(!ec);
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (ec)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    SimplifiedBackwardsTextIterator it(searchRange.get());
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned next = 0;
9581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool inTextSecurityMode = start.deprecatedNode() && start.deprecatedNode()->renderer() && start.deprecatedNode()->renderer()->style()->textSecurity() != TSNONE;
965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool needMoreContext = false;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!it.atEnd()) {
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // iterate to get chunks until the searchFunction returns a non-zero value.
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!inTextSecurityMode)
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            string.prepend(it.characters(), it.length());
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Treat bullets used in the text security mode as regular characters when looking for boundaries
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String iteratorString(it.characters(), it.length());
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            iteratorString = iteratorString.impl()->secure('x');
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            string.prepend(iteratorString.characters(), iteratorString.length());
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (next != 0)
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        it.advance();
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (needMoreContext) {
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // The last search returned the beginning of the buffer and asked for more context,
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // but there is no earlier text. Force a search with what's available.
1155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
1165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!needMoreContext);
1175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
119ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!next)
120ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM);
121ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
122ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    Node* node = it.range()->startContainer(ec);
123ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
124ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        // The next variable contains a usable index into a text node
125ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return VisiblePosition(Position(node, next), DOWNSTREAM);
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
127ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // Use the character iterator to translate the next value into a DOM position.
12881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    BackwardsCharacterIterator charIt(searchRange.get());
129ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    charIt.advance(string.size() - suffixLength - next);
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: charIt can get out of shadow host.
131ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = c.deepEquivalent();
137dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Node* boundary = pos.parentEditingBoundary();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!boundary)
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
141dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Document* d = boundary->document();
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Range> searchRange(d->createRange());
143ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    Position start(pos.parentAnchoredEquivalent());
1448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector<UChar, 1024> string;
1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    unsigned prefixLength = 0;
1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
1495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (requiresContextForWordBoundary(c.characterAfter())) {
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RefPtr<Range> backwardsScanRange(d->createRange());
15181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        backwardsScanRange->setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get());
1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        while (!backwardsIterator.atEnd()) {
1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            const UChar* characters = backwardsIterator.characters();
1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            int length = backwardsIterator.length();
1565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            int i = startOfLastWordBoundaryContext(characters, length);
1575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            string.prepend(characters + i, length - i);
1585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            prefixLength += length - i;
1595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (i > 0)
1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                break;
1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            backwardsIterator.advance();
1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    searchRange->selectNodeContents(boundary, ec);
16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    searchRange->setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
16721939df44de1705786c545cd1bf519d47250322dBen Murdoch    TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned next = 0;
16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool inTextSecurityMode = start.deprecatedNode() && start.deprecatedNode()->renderer() && start.deprecatedNode()->renderer()->style()->textSecurity() != TSNONE;
1705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool needMoreContext = false;
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!it.atEnd()) {
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Keep asking the iterator for chunks until the search function
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // returns an end value not equal to the length of the string passed to it.
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!inTextSecurityMode)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            string.append(it.characters(), it.length());
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Treat bullets used in the text security mode as regular characters when looking for boundaries
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String iteratorString(it.characters(), it.length());
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            iteratorString = iteratorString.impl()->secure('x');
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            string.append(iteratorString.characters(), iteratorString.length());
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext);
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (next != string.size())
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        it.advance();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (needMoreContext) {
1885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // The last search returned the end of the buffer and asked for more context,
1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // but there is no further text. Force a search with what's available.
1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        next = searchFunction(string.data(), string.size(), prefixLength, DontHaveMoreContext, needMoreContext);
1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!needMoreContext);
1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (it.atEnd() && next == string.size()) {
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos = it.range()->startPosition();
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (next != prefixLength) {
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Use the character iterator to translate the next value into a DOM position.
19821939df44de1705786c545cd1bf519d47250322dBen Murdoch        CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        charIt.advance(next - prefixLength - 1);
200bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        RefPtr<Range> characterRange = charIt.range();
201bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        pos = characterRange->endPosition();
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (*charIt.characters() == '\n') {
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            VisiblePosition visPos = VisiblePosition(pos);
206bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            if (visPos == VisiblePosition(characterRange->startPosition())) {
207bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                charIt.advance(1);
208bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                pos = charIt.range()->startPosition();
209bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            }
2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // generate VisiblePosition, use UPSTREAM affinity if possible
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic bool canHaveCursor(RenderObject* o)
218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return (o->isText() && toRenderText(o)->linesBoundingBox().height())
220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        || (o->isBox() && toRenderBox(o)->borderBoundingBox().height());
221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned startWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(offset);
2285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
2295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        needMoreContext = true;
2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return 0;
2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    needMoreContext = false;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int start, end;
2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    findWordBoundary(characters, length, offset - 1, &start, &end);
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return start;
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfWord(const VisiblePosition &c, EWordSide side)
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This returns a null VP for c at the start of the document
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and side == LeftWordIfOnBoundary
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition p = c;
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (side == RightWordIfOnBoundary) {
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // at paragraph end, the startofWord is the current position
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isEndOfParagraph(c))
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return c;
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = c.next();
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isNull())
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return c;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return previousBoundary(p, startWordBoundary);
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned endWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(offset <= length);
2585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
2595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        needMoreContext = true;
2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return length;
2615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    needMoreContext = false;
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int start, end;
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    findWordBoundary(characters, length, offset, &start, &end);
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return end;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition p = c;
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (side == LeftWordIfOnBoundary) {
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isStartOfParagraph(c))
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return c;
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = c.previous();
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isNull())
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return c;
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (isEndOfParagraph(c))
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return c;
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nextBoundary(p, endWordBoundary);
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned previousWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) {
2875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        needMoreContext = true;
2888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return 0;
2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    needMoreContext = false;
2918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return findNextWordFromIndex(characters, length, offset, false);
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousWordPosition(const VisiblePosition &c)
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary);
2972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrBefore(prev);
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned nextWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) {
3035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        needMoreContext = true;
3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return length;
3055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    needMoreContext = false;
3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return findNextWordFromIndex(characters, length, offset, true);
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextWordPosition(const VisiblePosition &c)
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition next = nextBoundary(c, nextWordPositionBoundary);
3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrAfter(next);
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic RootInlineBox *rootBoxForLine(const VisiblePosition &c)
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = c.deepEquivalent();
32181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* node = p.deprecatedNode();
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = node->renderer();
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* box;
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int offset;
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    c.getInlineBoxAndOffset(box, offset);
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return box ? box->root() : 0;
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition positionAvoidingFirstPositionInTable(const VisiblePosition& c)
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // return table offset 0 instead of the first VisiblePosition inside the table
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition previous = c.previous();
3400617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (isLastPositionBeforeTable(previous) && isEditablePosition(previous.deepEquivalent()))
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return previous;
3420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return c;
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition startPositionForLine(const VisiblePosition& c)
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (c.isNull())
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox *rootBox = rootBoxForLine(c);
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!rootBox) {
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // There are VisiblePositions at offset 0 in blocks without
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // RootInlineBoxes, like empty editable blocks and bordered blocks.
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Position p = c.deepEquivalent();
35681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return positionAvoidingFirstPositionInTable(c);
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Generated content (e.g. list markers and CSS :before and :after
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // pseudoelements) have no corresponding DOM element, and so cannot be
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // represented by a VisiblePosition.  Use whatever follows instead.
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox *startBox = rootBox->firstLeafChild();
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *startNode;
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (1) {
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!startBox)
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return VisiblePosition();
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RenderObject *startRenderer = startBox->renderer();
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!startRenderer)
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return VisiblePosition();
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        startNode = startRenderer->node();
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (startNode)
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startBox = startBox->nextLeafChild();
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3822bde8e466a4451c7319e3a072d118917957d6554Steve Block    VisiblePosition visPos = startNode->isTextNode() ? VisiblePosition(Position(startNode, static_cast<InlineTextBox *>(startBox)->start(), Position::PositionIsOffsetInAnchor), DOWNSTREAM)
3832bde8e466a4451c7319e3a072d118917957d6554Steve Block                                                     : VisiblePosition(positionBeforeNode(startNode), DOWNSTREAM);
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return positionAvoidingFirstPositionInTable(visPos);
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfLine(const VisiblePosition& c)
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition visPos = startPositionForLine(c);
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrBefore(visPos);
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition endPositionForLine(const VisiblePosition& c)
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (c.isNull())
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox *rootBox = rootBoxForLine(c);
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!rootBox) {
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // There are VisiblePositions at offset 0 in blocks without
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // RootInlineBoxes, like empty editable blocks and bordered blocks.
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Position p = c.deepEquivalent();
40481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return c;
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Generated content (e.g. list markers and CSS :before and :after
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // pseudoelements) have no corresponding DOM element, and so cannot be
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // represented by a VisiblePosition.  Use whatever precedes instead.
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *endNode;
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox *endBox = rootBox->lastLeafChild();
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (1) {
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!endBox)
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return VisiblePosition();
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RenderObject *endRenderer = endBox->renderer();
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!endRenderer)
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return VisiblePosition();
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        endNode = endRenderer->node();
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endNode)
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endBox = endBox->prevLeafChild();
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
42981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Position pos;
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (endNode->hasTagName(brTag)) {
43181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = positionBeforeNode(endNode);
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (endBox->isInlineTextBox()) {
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox);
43481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        int endOffset = endTextBox->start();
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!endTextBox->isLineBreak())
436635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            endOffset += endTextBox->len();
43781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = Position(endNode, endOffset, Position::PositionIsOffsetInAnchor);
43881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    } else
43981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = positionAfterNode(endNode);
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
44181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfLine(const VisiblePosition& c)
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition visPos = endPositionForLine(c);
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Make sure the end of line is at the same line as the given input position.  Else use the previous position to
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // obtain end of line.  This condition happens when the input position is before the space character at the end
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // versus lines without that style, which would break before a space by default.
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!inSameLine(c, visPos)) {
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        visPos = c.previous();
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (visPos.isNull())
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return VisiblePosition();
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        visPos = endPositionForLine(visPos);
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrAfter(visPos);
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameLine(const VisiblePosition &a, const VisiblePosition &b)
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return a.isNotNull() && startOfLine(a) == startOfLine(b);
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfLine(const VisiblePosition &p)
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return p.isNotNull() && p == startOfLine(p);
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfLine(const VisiblePosition &p)
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return p.isNotNull() && p == endOfLine(p);
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// The first leaf before node that has the same editability as node.
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* previousLeafWithSameEditability(Node* node)
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4812bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool editable = node->rendererIsEditable();
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = node->previousLeafNode();
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (n) {
4842bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (editable == n->rendererIsEditable())
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        n = n->previousLeafNode();
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic Node* enclosingNodeWithNonInlineRenderer(Node* n)
4925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
4935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (Node* p = n; p; p = p->parentNode()) {
4945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (p->renderer() && !p->renderer()->isInline())
4955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return p;
4965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
4975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return 0;
4985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
4995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int x)
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = visiblePosition.deepEquivalent();
50381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* node = p.deprecatedNode();
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(p);
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node->document()->updateLayoutIgnorePendingStylesheets();
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = node->renderer();
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderBlock *containingBlock = 0;
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox *root = 0;
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* box;
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int ignoredCaretOffset;
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (box) {
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        root = box->root()->prevRootBox();
521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // We want to skip zero height boxes.
522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // This could happen in case it is a TrailingFloatsRootInlineBox.
523bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (root && root->logicalHeight())
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            containingBlock = renderer->containingBlock();
525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else
526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            root = 0;
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!root) {
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This containing editable block does not have a previous line.
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Need to move back to previous containing editable block in this root editable
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // block and find the last root line box in that block.
5335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Node* startBlock = enclosingNodeWithNonInlineRenderer(node);
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Node* n = previousLeafWithSameEditability(node);
5355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        while (n && startBlock == enclosingNodeWithNonInlineRenderer(n))
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = previousLeafWithSameEditability(n);
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (n) {
5382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (highestEditableRoot(firstPositionInOrBeforeNode(n)) != highestRoot)
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Position pos(n, caretMinOffset(n));
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (pos.isCandidate()) {
542dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                RenderObject* o = n->renderer();
543dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                ASSERT(o);
544dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (canHaveCursor(o)) {
545dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    Position maxPos(n, caretMaxOffset(n));
546dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    maxPos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    if (box) {
548dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        // previous root line box found
549dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        root = box->root();
550dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        containingBlock = n->renderer()->containingBlock();
551dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        break;
552dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    }
553dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
554dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    return VisiblePosition(pos, DOWNSTREAM);
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = previousLeafWithSameEditability(n);
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (root) {
562635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // FIXME: Can be wrong for multi-column layout and with transforms.
563635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint());
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (containingBlock->hasOverflowClip())
565635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            absPos -= containingBlock->layer()->scrolledContentOffset();
5666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        RenderObject* renderer = root->closestLeafChildForLogicalLeftPosition(x - absPos.x(), isEditablePosition(p))->renderer();
567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        Node* node = renderer->node();
5685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (node && editingIgnoresContent(node))
5692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return positionInParentBeforeNode(node);
570231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return renderer->positionForPoint(IntPoint(x - absPos.x(), root->lineTop()));
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Could not find a previous line. This means we must already be on the first line.
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Move to the start of the content in this block, which effectively moves us
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to the start of the line we're on.
5762bde8e466a4451c7319e3a072d118917957d6554Steve Block    Element* rootElement = node->rendererIsEditable() ? node->rootEditableElement() : node->document()->documentElement();
5772bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!rootElement)
5782bde8e466a4451c7319e3a072d118917957d6554Steve Block        return VisiblePosition();
57981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* nextLeafWithSameEditability(Node* node, int offset)
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5842bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool editable = node->rendererIsEditable();
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(offset >= 0);
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* child = node->childNode(offset);
5872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Node* n = child ? child->nextLeafNode() : node->lastDescendant()->nextLeafNode();
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (n) {
5892bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (editable == n->rendererIsEditable())
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        n = n->nextLeafNode();
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* nextLeafWithSameEditability(Node* node)
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6012bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool editable = node->rendererIsEditable();
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = node->nextLeafNode();
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (n) {
6042bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (editable == n->rendererIsEditable())
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        n = n->nextLeafNode();
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x)
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = visiblePosition.deepEquivalent();
61481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* node = p.deprecatedNode();
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(p);
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node->document()->updateLayoutIgnorePendingStylesheets();
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = node->renderer();
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderBlock *containingBlock = 0;
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox *root = 0;
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* box;
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int ignoredCaretOffset;
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (box) {
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        root = box->root()->nextRootBox();
632dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // We want to skip zero height boxes.
633dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // This could happen in case it is a TrailingFloatsRootInlineBox.
634bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (root && root->logicalHeight())
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            containingBlock = renderer->containingBlock();
636dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else
637dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            root = 0;
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!root) {
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This containing editable block does not have a next line.
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Need to move forward to next containing editable block in this root editable
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // block and find the first root line box in that block.
6445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Node* startBlock = enclosingNodeWithNonInlineRenderer(node);
6455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Node* n = nextLeafWithSameEditability(node, p.deprecatedEditingOffset());
6465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        while (n && startBlock == enclosingNodeWithNonInlineRenderer(n))
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = nextLeafWithSameEditability(n);
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (n) {
6492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (highestEditableRoot(firstPositionInOrBeforeNode(n)) != highestRoot)
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Position pos(n, caretMinOffset(n));
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (pos.isCandidate()) {
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(n->renderer());
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box) {
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // next root line box found
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    root = box->root();
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    containingBlock = n->renderer()->containingBlock();
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return VisiblePosition(pos, DOWNSTREAM);
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = nextLeafWithSameEditability(n);
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (root) {
669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // FIXME: Can be wrong for multi-column layout and with transforms.
670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint());
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (containingBlock->hasOverflowClip())
672635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            absPos -= containingBlock->layer()->scrolledContentOffset();
6736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        RenderObject* renderer = root->closestLeafChildForLogicalLeftPosition(x - absPos.x(), isEditablePosition(p))->renderer();
674635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        Node* node = renderer->node();
6755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (node && editingIgnoresContent(node))
6762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return positionInParentBeforeNode(node);
677231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return renderer->positionForPoint(IntPoint(x - absPos.x(), root->lineTop()));
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Could not find a next line. This means we must already be on the last line.
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Move to the end of the content in this block, which effectively moves us
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to the end of the line we're on.
6832bde8e466a4451c7319e3a072d118917957d6554Steve Block    Element* rootElement = node->rendererIsEditable() ? node->rootEditableElement() : node->document()->documentElement();
6842bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!rootElement)
6852bde8e466a4451c7319e3a072d118917957d6554Steve Block        return VisiblePosition();
68681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: The following function can return -1; we don't handle that.
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return textBreakPreceding(iterator, length);
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfSentence(const VisiblePosition &c)
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return previousBoundary(c, startSentenceBoundary);
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned endSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return textBreakNext(iterator);
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: This includes the space after the punctuation that marks the end of the sentence.
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfSentence(const VisiblePosition &c)
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nextBoundary(c, endSentenceBoundary);
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right.
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: The following function can return -1; we don't handle that.
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return textBreakPreceding(iterator, length);
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousSentencePosition(const VisiblePosition &c)
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary);
7262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrBefore(prev);
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&)
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This is identical to endSentenceBoundary.  This isn't right, it needs to
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // move to the equivlant position in the following sentence.
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextBreakIterator* iterator = sentenceBreakIterator(characters, length);
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return textBreakFollowing(iterator, 0);
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextSentencePosition(const VisiblePosition &c)
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary);
7402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrAfter(next);
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7434576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangVisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = c.deepEquivalent();
74681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* startNode = p.deprecatedNode();
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!startNode)
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
751643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (isRenderedAsNonInlineTableImageOrHR(startNode))
7522bde8e466a4451c7319e3a072d118917957d6554Steve Block        return positionBeforeNode(startNode);
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* startBlock = enclosingBlock(startNode);
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7562bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* node = startNode;
7572bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* highestRoot = highestEditableRoot(p);
7585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int offset = p.deprecatedEditingOffset();
75981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Position::AnchorType type = p.anchorType();
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7612bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* n = startNode;
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (n) {
7632bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (boundaryCrossingRule == CannotCrossEditingBoundary && n->rendererIsEditable() != startNode->rendererIsEditable())
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
7652bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
7662bde8e466a4451c7319e3a072d118917957d6554Steve Block            while (n && n->rendererIsEditable() != startNode->rendererIsEditable())
7672bde8e466a4451c7319e3a072d118917957d6554Steve Block                n = n->traversePreviousNodePostOrder(startBlock);
7682bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (!n || !n->isDescendantOf(highestRoot))
7692bde8e466a4451c7319e3a072d118917957d6554Steve Block                break;
7702bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject *r = n->renderer();
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!r) {
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traversePreviousNodePostOrder(startBlock);
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderStyle *style = r->style();
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (style->visibility() != VISIBLE) {
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traversePreviousNodePostOrder(startBlock);
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->isBR() || isBlock(n))
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
784e14391e94c850b8bd03680c23b38978db68687a8John Reck
785e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (r->isText() && r->caretMaxRenderedOffset() > 0) {
78681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            type = Position::PositionIsOffsetInAnchor;
7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (style->preserveNewline()) {
788635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                const UChar* chars = toRenderText(r)->characters();
789635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                int i = toRenderText(r)->textLength();
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                int o = offset;
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (n == startNode && o < i)
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    i = max(0, o);
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (--i >= 0)
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (chars[i] == '\n')
79581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                        return VisiblePosition(Position(n, i + 1, Position::PositionIsOffsetInAnchor), DOWNSTREAM);
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            node = n;
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offset = 0;
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traversePreviousNodePostOrder(startBlock);
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (editingIgnoresContent(n) || isTableElement(n)) {
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            node = n;
80281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            type = Position::PositionIsBeforeAnchor;
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->previousSibling() ? n->previousSibling() : n->traversePreviousNodePostOrder(startBlock);
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traversePreviousNodePostOrder(startBlock);
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
80881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (type == Position::PositionIsOffsetInAnchor)
80981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
81081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
81181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(Position(node, type), DOWNSTREAM);
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8144576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangVisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossingRule boundaryCrossingRule)
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (c.isNull())
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = c.deepEquivalent();
82081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* startNode = p.deprecatedNode();
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
822643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (isRenderedAsNonInlineTableImageOrHR(startNode))
8232bde8e466a4451c7319e3a072d118917957d6554Steve Block        return positionAfterNode(startNode);
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* startBlock = enclosingBlock(startNode);
8262bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* stayInsideBlock = startBlock;
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8282bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* node = startNode;
8292bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* highestRoot = highestEditableRoot(p);
8305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int offset = p.deprecatedEditingOffset();
83181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Position::AnchorType type = p.anchorType();
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8332bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* n = startNode;
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (n) {
8352bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (boundaryCrossingRule == CannotCrossEditingBoundary && n->rendererIsEditable() != startNode->rendererIsEditable())
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
8372bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
8382bde8e466a4451c7319e3a072d118917957d6554Steve Block            while (n && n->rendererIsEditable() != startNode->rendererIsEditable())
8392bde8e466a4451c7319e3a072d118917957d6554Steve Block                n = n->traverseNextNode(stayInsideBlock);
8402bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (!n || !n->isDescendantOf(highestRoot))
8412bde8e466a4451c7319e3a072d118917957d6554Steve Block                break;
8422bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
8432bde8e466a4451c7319e3a072d118917957d6554Steve Block
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject *r = n->renderer();
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!r) {
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traverseNextNode(stayInsideBlock);
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderStyle *style = r->style();
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (style->visibility() != VISIBLE) {
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traverseNextNode(stayInsideBlock);
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->isBR() || isBlock(n))
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
857e14391e94c850b8bd03680c23b38978db68687a8John Reck
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: We avoid returning a position where the renderer can't accept the caret.
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->isText() && r->caretMaxRenderedOffset() > 0) {
860635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            int length = toRenderText(r)->textLength();
86181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            type = Position::PositionIsOffsetInAnchor;
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (style->preserveNewline()) {
863635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                const UChar* chars = toRenderText(r)->characters();
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                int o = n == startNode ? offset : 0;
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                for (int i = o; i < length; ++i)
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (chars[i] == '\n')
86781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                        return VisiblePosition(Position(n, i, Position::PositionIsOffsetInAnchor), DOWNSTREAM);
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            node = n;
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offset = r->caretMaxOffset();
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traverseNextNode(stayInsideBlock);
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (editingIgnoresContent(n) || isTableElement(n)) {
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            node = n;
87481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            type = Position::PositionIsAfterAnchor;
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traverseNextSibling(stayInsideBlock);
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            n = n->traverseNextNode(stayInsideBlock);
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
88081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (type == Position::PositionIsOffsetInAnchor)
88181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
88281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
88381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(Position(node, type), DOWNSTREAM);
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8862bde8e466a4451c7319e3a072d118917957d6554Steve Block// FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition)
8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8892bde8e466a4451c7319e3a072d118917957d6554Steve Block    VisiblePosition paragraphEnd(endOfParagraph(visiblePosition, CanSkipOverEditingBoundary));
8902bde8e466a4451c7319e3a072d118917957d6554Steve Block    VisiblePosition afterParagraphEnd(paragraphEnd.next(CannotCrossEditingBoundary));
8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The position after the last position in the last cell of a table
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // is not the start of the next paragraph.
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isFirstPositionAfterTable(afterParagraphEnd))
8942bde8e466a4451c7319e3a072d118917957d6554Steve Block        return afterParagraphEnd.next(CannotCrossEditingBoundary);
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return afterParagraphEnd;
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8982bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b, EditingBoundaryCrossingRule boundaryCrossingRule)
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9002bde8e466a4451c7319e3a072d118917957d6554Steve Block    return a.isNotNull() && startOfParagraph(a, boundaryCrossingRule) == startOfParagraph(b, boundaryCrossingRule);
9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9034576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool isStartOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
905e14391e94c850b8bd03680c23b38978db68687a8John Reck    return pos.isNotNull() && pos == startOfParagraph(pos, boundaryCrossingRule);
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9084576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool isEndOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule)
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
910e14391e94c850b8bd03680c23b38978db68687a8John Reck    return pos.isNotNull() && pos == endOfParagraph(pos, boundaryCrossingRule);
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisiblePosition previousParagraphPosition(const VisiblePosition& p, int x)
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition pos = p;
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    do {
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        VisiblePosition n = previousLinePosition(pos, x);
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n.isNull() || n == pos)
9198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            break;
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos = n;
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } while (inSameParagraph(p, pos));
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return pos;
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisiblePosition nextParagraphPosition(const VisiblePosition& p, int x)
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition pos = p;
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    do {
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        VisiblePosition n = nextLinePosition(pos, x);
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n.isNull() || n == pos)
9318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            break;
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos = n;
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } while (inSameParagraph(p, pos));
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return pos;
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9392bde8e466a4451c7319e3a072d118917957d6554Steve BlockVisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9412bde8e466a4451c7319e3a072d118917957d6554Steve Block    Position position = visiblePosition.deepEquivalent();
9422bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* startBlock;
9432bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!position.containerNode() || !(startBlock = enclosingBlock(position.containerNode(), rule)))
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
9452bde8e466a4451c7319e3a072d118917957d6554Steve Block    return firstPositionInNode(startBlock);
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9482bde8e466a4451c7319e3a072d118917957d6554Steve BlockVisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9502bde8e466a4451c7319e3a072d118917957d6554Steve Block    Position position = visiblePosition.deepEquivalent();
9512bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* endBlock;
9522bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!position.containerNode() || !(endBlock = enclosingBlock(position.containerNode(), rule)))
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
9542bde8e466a4451c7319e3a072d118917957d6554Steve Block    return lastPositionInNode(endBlock);
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9592bde8e466a4451c7319e3a072d118917957d6554Steve Block    return !a.isNull() && enclosingBlock(a.deepEquivalent().containerNode()) == enclosingBlock(b.deepEquivalent().containerNode());
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfBlock(const VisiblePosition &pos)
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9642bde8e466a4451c7319e3a072d118917957d6554Steve Block    return pos.isNotNull() && pos == startOfBlock(pos, CanCrossEditingBoundary);
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfBlock(const VisiblePosition &pos)
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9692bde8e466a4451c7319e3a072d118917957d6554Steve Block    return pos.isNotNull() && pos == endOfBlock(pos, CanCrossEditingBoundary);
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfDocument(const Node* node)
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
97981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(firstPositionInNode(node->document()->documentElement()), DOWNSTREAM);
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfDocument(const VisiblePosition &c)
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
98481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return startOfDocument(c.deepEquivalent().deprecatedNode());
9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfDocument(const Node* node)
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
989dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!node || !node->document() || !node->document()->documentElement())
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Element* doc = node->document()->documentElement();
99381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(lastPositionInNode(doc), DOWNSTREAM);
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfDocument(const VisiblePosition &c)
9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
99881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return endOfDocument(c.deepEquivalent().deprecatedNode());
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameDocument(const VisiblePosition &a, const VisiblePosition &b)
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position ap = a.deepEquivalent();
100481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* an = ap.deprecatedNode();
10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!an)
10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position bp = b.deepEquivalent();
100881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* bn = bp.deprecatedNode();
10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (an == bn)
10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return an->document() == bn->document();
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfDocument(const VisiblePosition &p)
10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return p.isNotNull() && p.previous().isNull();
10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfDocument(const VisiblePosition &p)
10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return p.isNotNull() && p.next().isNull();
10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ---------
10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10332bde8e466a4451c7319e3a072d118917957d6554Steve Block    return firstPositionInNode(highestRoot);
10348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10422bde8e466a4451c7319e3a072d118917957d6554Steve Block    return lastPositionInNode(highestRoot);
10435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
10445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition logicalStartPositionForLine(const VisiblePosition& c)
10465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
10475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (c.isNull())
10485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
10495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RootInlineBox* rootBox = rootBoxForLine(c);
10515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!rootBox) {
10525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // There are VisiblePositions at offset 0 in blocks without
10535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // RootInlineBoxes, like empty editable blocks and bordered blocks.
10545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Position p = c.deepEquivalent();
105581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
10565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return positionAvoidingFirstPositionInTable(c);
10575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
10595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    InlineBox* logicalStartBox;
10622bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* logicalStartNode = rootBox->getLogicalStartBoxWithNode(logicalStartBox);
10635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!logicalStartNode)
10655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
10665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
106781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    VisiblePosition visPos = logicalStartNode->isTextNode() ? VisiblePosition(Position(logicalStartNode, logicalStartBox->caretMinOffset(), Position::PositionIsOffsetInAnchor), DOWNSTREAM)
106881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                                                            : VisiblePosition(positionBeforeNode(logicalStartNode), DOWNSTREAM);
10695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return positionAvoidingFirstPositionInTable(visPos);
10705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
10715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10725f1ab04193ad0130ca8204aadaceae083aca9881Feng QianVisiblePosition logicalStartOfLine(const VisiblePosition& c)
10735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1074cad810f21b803229eb11403f9209855525a25d57Steve Block    // TODO: this is the current behavior that might need to be fixed.
1075cad810f21b803229eb11403f9209855525a25d57Steve Block    // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
10765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    VisiblePosition visPos = logicalStartPositionForLine(c);
10775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrBefore(visPos);
10795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
10805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition logicalEndPositionForLine(const VisiblePosition& c)
10825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
10835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (c.isNull())
10845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
10855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RootInlineBox* rootBox = rootBoxForLine(c);
10875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!rootBox) {
10885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // There are VisiblePositions at offset 0 in blocks without
10895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // RootInlineBoxes, like empty editable blocks and bordered blocks.
10905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Position p = c.deepEquivalent();
109181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (p.deprecatedNode()->renderer() && p.deprecatedNode()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset())
10925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return c;
10935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
10945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    InlineBox* logicalEndBox;
10972bde8e466a4451c7319e3a072d118917957d6554Steve Block    Node* logicalEndNode = rootBox->getLogicalEndBoxWithNode(logicalEndBox);
10982bde8e466a4451c7319e3a072d118917957d6554Steve Block
10995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!logicalEndNode)
11005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return VisiblePosition();
11015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
110281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Position pos;
11035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (logicalEndNode->hasTagName(brTag))
110481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = positionBeforeNode(logicalEndNode);
11055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    else if (logicalEndBox->isInlineTextBox()) {
11065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        InlineTextBox* endTextBox = static_cast<InlineTextBox*>(logicalEndBox);
110781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        int endOffset = endTextBox->start();
11085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!endTextBox->isLineBreak())
11095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            endOffset += endTextBox->len();
111081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = Position(logicalEndNode, endOffset, Position::PositionIsOffsetInAnchor);
111181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    } else
111281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        pos = positionAfterNode(logicalEndNode);
11135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
111481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
11155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
11165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b)
11185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
11195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
11205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
11215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11225f1ab04193ad0130ca8204aadaceae083aca9881Feng QianVisiblePosition logicalEndOfLine(const VisiblePosition& c)
11235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1124cad810f21b803229eb11403f9209855525a25d57Steve Block    // TODO: this is the current behavior that might need to be fixed.
1125cad810f21b803229eb11403f9209855525a25d57Steve Block    // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
1126cad810f21b803229eb11403f9209855525a25d57Steve Block
11275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    VisiblePosition visPos = logicalEndPositionForLine(c);
11285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end
11305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line.
11315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg
11325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
11335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // In this case, use the previous position of the computed logical end position.
11345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!inSameLogicalLine(c, visPos))
11355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        visPos = visPos.previous();
11365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return c.honorEditableBoundaryAtOrAfter(visPos);
11385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
11395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1140cad810f21b803229eb11403f9209855525a25d57Steve BlockVisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1141cad810f21b803229eb11403f9209855525a25d57Steve Block{
1142cad810f21b803229eb11403f9209855525a25d57Steve Block    return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
1143cad810f21b803229eb11403f9209855525a25d57Steve Block}
1144cad810f21b803229eb11403f9209855525a25d57Steve Block
1145cad810f21b803229eb11403f9209855525a25d57Steve BlockVisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
1146cad810f21b803229eb11403f9209855525a25d57Steve Block{
1147cad810f21b803229eb11403f9209855525a25d57Steve Block    return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
1148cad810f21b803229eb11403f9209855525a25d57Steve Block}
1149cad810f21b803229eb11403f9209855525a25d57Steve Block
11502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const int invalidOffset = -1;
11512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition previousWordBreakInBoxInsideBlockWithSameDirectionality(const InlineBox* box, const VisiblePosition& previousWordBreak, int& offsetOfWordBreak)
11532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
11542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool hasSeenWordBreakInThisBox = previousWordBreak.isNotNull();
11552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // In a LTR block, the word break should be on the left boundary of a word.
11562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // In a RTL block, the word break should be on the right boundary of a word.
11572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Because nextWordPosition() returns the word break on the right boundary of the word for LTR text,
11582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // we need to use previousWordPosition() to traverse words within the inline boxes from right to left
11592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // to find the previous word break (i.e. the first word break on the left). The same applies to RTL text.
11602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak = hasSeenWordBreakInThisBox ? previousWordBreak : Position(box->renderer()->node(), box->caretMaxOffset(), Position::PositionIsOffsetInAnchor);
11622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: handle multi-spaces (http://webkit.org/b/57543).
11642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak = previousWordPosition(wordBreak);
11662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (previousWordBreak == wordBreak)
11672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return VisiblePosition();
11682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* boxContainingPreviousWordBreak;
11702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak.getInlineBoxAndOffset(boxContainingPreviousWordBreak, offsetOfWordBreak);
11712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boxContainingPreviousWordBreak != box)
11722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return VisiblePosition();
11732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return wordBreak;
11742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
11752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition leftmostPositionInRTLBoxInLTRBlock(const InlineBox* box)
11772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
11782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Probably need to take care of bidi level too.
11792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Node* node = box->renderer()->node();
11802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* previousLeaf = box->prevLeafChild();
11812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* nextLeaf = box->nextLeafChild();
11822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (previousLeaf && !previousLeaf->isLeftToRightDirection())
11842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return Position(node, box->caretMaxOffset(), Position::PositionIsOffsetInAnchor);
11852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (nextLeaf && !nextLeaf->isLeftToRightDirection()) {
11872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (previousLeaf)
11882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return Position(previousLeaf->renderer()->node(), previousLeaf->caretMaxOffset(), Position::PositionIsOffsetInAnchor);
11892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        InlineBox* lastRTLLeaf;
11912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        do {
11922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            lastRTLLeaf = nextLeaf;
11932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            nextLeaf = nextLeaf->nextLeafChild();
11942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } while (nextLeaf && !nextLeaf->isLeftToRightDirection());
11952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return Position(lastRTLLeaf->renderer()->node(), lastRTLLeaf->caretMinOffset(), Position::PositionIsOffsetInAnchor);
11962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return Position(node, box->caretMinOffset(), Position::PositionIsOffsetInAnchor);
11992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
12002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition rightmostPositionInLTRBoxInRTLBlock(const InlineBox* box)
12022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
12032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Probably need to take care of bidi level too.
12042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Node* node = box->renderer()->node();
12052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* previousLeaf = box->prevLeafChild();
12062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* nextLeaf = box->nextLeafChild();
12072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (nextLeaf && nextLeaf->isLeftToRightDirection())
12092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return Position(node, box->caretMaxOffset(), Position::PositionIsOffsetInAnchor);
12102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (previousLeaf && previousLeaf->isLeftToRightDirection()) {
12122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (nextLeaf)
12132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return Position(nextLeaf->renderer()->node(), nextLeaf->caretMaxOffset(), Position::PositionIsOffsetInAnchor);
12142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        InlineBox* firstLTRLeaf;
12162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        do {
12172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            firstLTRLeaf = previousLeaf;
12182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            previousLeaf = previousLeaf->prevLeafChild();
12192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } while (previousLeaf && previousLeaf->isLeftToRightDirection());
12202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return Position(firstLTRLeaf->renderer()->node(), firstLTRLeaf->caretMinOffset(), Position::PositionIsOffsetInAnchor);
12212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return Position(node, box->caretMinOffset(), Position::PositionIsOffsetInAnchor);
12242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
12252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition lastWordBreakInBox(const InlineBox* box, int& offsetOfWordBreak)
12272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
12282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Add the leftmost word break for RTL box or rightmost word break for LTR box.
12292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* previousLeaf = box->prevLeafChild();
12302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* nextLeaf = box->nextLeafChild();
12312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition boundaryPosition;
12322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (box->direction() == RTL && (!previousLeaf || previousLeaf->isLeftToRightDirection()))
12332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        boundaryPosition = leftmostPositionInRTLBoxInLTRBlock(box);
12342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else if (box->direction() == LTR && (!nextLeaf || !nextLeaf->isLeftToRightDirection()))
12352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        boundaryPosition = rightmostPositionInLTRBoxInRTLBlock(box);
12362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boundaryPosition.isNull())
12382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return VisiblePosition();
12392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak = nextWordPosition(boundaryPosition);
12412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (wordBreak != boundaryPosition)
12422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        wordBreak = previousWordPosition(wordBreak);
12432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* boxOfWordBreak;
12452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak.getInlineBoxAndOffset(boxOfWordBreak, offsetOfWordBreak);
12462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boxOfWordBreak == box)
12472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return wordBreak;
12482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return VisiblePosition();
12492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
12502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool positionIsVisuallyOrderedInBoxInBlockWithDifferentDirectionality(const VisiblePosition& wordBreak, const InlineBox* box, int& offsetOfWordBreak)
12522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
12532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int previousOffset = offsetOfWordBreak;
12542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* boxOfWordBreak;
12552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak.getInlineBoxAndOffset(boxOfWordBreak, offsetOfWordBreak);
12562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boxOfWordBreak == box && (previousOffset == invalidOffset || previousOffset < offsetOfWordBreak))
12572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
12582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return false;
12592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
12602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition nextWordBreakInBoxInsideBlockWithDifferentDirectionality(
12622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const InlineBox* box, const VisiblePosition& previousWordBreak, int& offsetOfWordBreak, bool& isLastWordBreakInBox)
12632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
12642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Probably need to take care of bidi level too.
12652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // In a LTR block, the word break should be on the left boundary of a word.
12672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // In a RTL block, the word break should be on the right boundary of a word.
12682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Because previousWordPosition() returns the word break on the right boundary of the word for RTL text,
12692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // we need to use nextWordPosition() to traverse words within the inline boxes from right to left to find the next word break.
12702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // The same applies to LTR text, in which words are traversed within the inline boxes from left to right.
12712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: handle multi-spaces (http://webkit.org/b/57543).
12732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool hasSeenWordBreakInThisBox = previousWordBreak.isNotNull();
12752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak = hasSeenWordBreakInThisBox ? previousWordBreak : Position(box->renderer()->node(), box->caretMinOffset(), Position::PositionIsOffsetInAnchor);
12762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak = nextWordPosition(wordBreak);
12772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (wordBreak == previousWordBreak) {
12792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        isLastWordBreakInBox = true;
12802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return VisiblePosition();
12812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Given RTL box "ABC DEF" either follows a LTR box or is the first visual box in an LTR block as an example,
12852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // the visual display of the RTL box is: "(0)J(10)I(9)H(8) (7)F(6)E(5)D(4) (3)C(2)B(1)A(11)",
12862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // where the number in parenthesis represents offset in visiblePosition.
12872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Start at offset 0, the first word break is at offset 3, the 2nd word break is at offset 7, and the 3rd word break should be at offset 0.
12882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // But nextWordPosition() of offset 7 is offset 11, which should be ignored,
12892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // and the position at offset 0 should be manually added as the last word break within the box.
12902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (positionIsVisuallyOrderedInBoxInBlockWithDifferentDirectionality(wordBreak, box, offsetOfWordBreak)) {
12912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        isLastWordBreakInBox = false;
12922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return wordBreak;
12932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    isLastWordBreakInBox = true;
12962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return lastWordBreakInBox(box, offsetOfWordBreak);
12972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
12982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstruct WordBoundaryEntry {
13002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WordBoundaryEntry()
13012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : offsetInInlineBox(invalidOffset)
13022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
13032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WordBoundaryEntry(const VisiblePosition& position, int offset)
13062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : visiblePosition(position)
13072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , offsetInInlineBox(offset)
13082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
13092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition visiblePosition;
13122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offsetInInlineBox;
13132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
13142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochtypedef Vector<WordBoundaryEntry, 50> WordBoundaryVector;
13162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void collectWordBreaksInBoxInsideBlockWithSameDirectionality(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries)
13182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    orderedWordBoundaries.clear();
13202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
13222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offsetOfWordBreak = invalidOffset;
13232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (1) {
13242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        wordBreak = previousWordBreakInBoxInsideBlockWithSameDirectionality(box, wordBreak, offsetOfWordBreak);
13252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (wordBreak.isNull())
13262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
13272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        WordBoundaryEntry wordBoundaryEntry(wordBreak, offsetOfWordBreak);
13282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        orderedWordBoundaries.append(wordBoundaryEntry);
13292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void collectWordBreaksInBoxInsideBlockWithDifferntDirectionality(const InlineBox* box, WordBoundaryVector& orderedWordBoundaries)
13332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    orderedWordBoundaries.clear();
13352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
13372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offsetOfWordBreak = invalidOffset;
13382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (1) {
13392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool isLastWordBreakInBox = false;
13402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        wordBreak = nextWordBreakInBoxInsideBlockWithDifferentDirectionality(box, wordBreak, offsetOfWordBreak, isLastWordBreakInBox);
13412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (wordBreak.isNotNull()) {
13422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            WordBoundaryEntry wordBoundaryEntry(wordBreak, offsetOfWordBreak);
13432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            orderedWordBoundaries.append(wordBoundaryEntry);
13442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
13452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (isLastWordBreakInBox)
13462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
13472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition previousWordBreakInBox(const InlineBox* box, int offset, TextDirection blockDirection)
13512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offsetOfWordBreak = 0;
13532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
13542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (true) {
13552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (box->direction() == blockDirection)
13562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = previousWordBreakInBoxInsideBlockWithSameDirectionality(box, wordBreak, offsetOfWordBreak);
13572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // FIXME: Implement the 'else' case when the box direction is not equal to the block direction.
13582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (wordBreak.isNull())
13592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
13602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (offset == invalidOffset || offsetOfWordBreak != offset)
13612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return wordBreak;
13622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return VisiblePosition();
13642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int greatestValueUnder(int offset, bool boxAndBlockAreInSameDirection, const WordBoundaryVector& orderedWordBoundaries)
13672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!orderedWordBoundaries.size())
13692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return invalidOffset;
13702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: binary search.
13712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boxAndBlockAreInSameDirection) {
13722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < orderedWordBoundaries.size(); ++i) {
13732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (orderedWordBoundaries[i].offsetInInlineBox < offset)
13742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return i;
13752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
13762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return invalidOffset;
13772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (int i = orderedWordBoundaries.size() - 1; i >= 0; --i) {
13792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (orderedWordBoundaries[i].offsetInInlineBox < offset)
13802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return i;
13812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return invalidOffset;
13832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int smallestOffsetAbove(int offset, bool boxAndBlockAreInSameDirection, const WordBoundaryVector& orderedWordBoundaries)
13862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!orderedWordBoundaries.size())
13882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return invalidOffset;
13892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: binary search.
13902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (boxAndBlockAreInSameDirection) {
13912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (int i = orderedWordBoundaries.size() - 1; i >= 0; --i) {
13922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (orderedWordBoundaries[i].offsetInInlineBox > offset)
13932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return i;
13942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
13952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return invalidOffset;
13962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (unsigned i = 0; i < orderedWordBoundaries.size(); ++i) {
13982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (orderedWordBoundaries[i].offsetInInlineBox > offset)
13992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return i;
14002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return invalidOffset;
14022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition leftWordBoundary(const InlineBox* box, int offset, TextDirection blockDirection)
14052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
14072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for  (const InlineBox* adjacentBox = box; adjacentBox; adjacentBox = adjacentBox->prevLeafChild()) {
14082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == LTR)
14092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = previousWordBreakInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset, blockDirection);
14102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // FIXME: Implement the "else" case.
14112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (wordBreak.isNotNull())
14122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return wordBreak;
14132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return VisiblePosition();
14152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition rightWordBoundary(const InlineBox* box, int offset, TextDirection blockDirection)
14182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
14212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (const InlineBox* adjacentBox = box; adjacentBox; adjacentBox = adjacentBox->nextLeafChild()) {
14222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == RTL)
14232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = previousWordBreakInBox(adjacentBox, adjacentBox == box ? offset : invalidOffset, blockDirection);
14242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // FIXME: Implement the "else" case.
14252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!wordBreak.isNull())
14262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return wordBreak;
14272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return VisiblePosition();
14292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool positionIsInsideBox(const VisiblePosition& wordBreak, const InlineBox* box)
14322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* boxOfWordBreak;
14342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offsetOfWordBreak;
14352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    wordBreak.getInlineBoxAndOffset(boxOfWordBreak, offsetOfWordBreak);
14362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return box == boxOfWordBreak && offsetOfWordBreak != box->caretMaxOffset() && offsetOfWordBreak != box->caretMinOffset();
14372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition positionBeforeNextWord(const VisiblePosition& position)
14402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition positionAfterCurrentWord = nextWordPosition(position);
14422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition positionAfterNextWord = nextWordPosition(positionAfterCurrentWord);
14432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (positionAfterCurrentWord == positionAfterNextWord)
14442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return positionAfterCurrentWord;
14452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return previousWordPosition(positionAfterNextWord);
14462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic VisiblePosition positionAfterPreviousWord(const VisiblePosition& position)
14492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition positionBeforeCurrentWord = previousWordPosition(position);
14512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition positionBeforePreviousWord = previousWordPosition(positionBeforeCurrentWord);
14522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (positionBeforeCurrentWord == positionBeforePreviousWord)
14532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return positionBeforeCurrentWord;
14542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return nextWordPosition(positionBeforePreviousWord);
14552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochVisiblePosition leftWordPosition(const VisiblePosition& visiblePosition)
14582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* box;
14602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offset;
14612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    visiblePosition.getInlineBoxAndOffset(box, offset);
14622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
14632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: If the box's directionality is the same as that of the enclosing block, when the offset is at the box boundary
14652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // and the direction is towards inside the box, do I still need to make it a special case? For example, a LTR box inside a LTR block,
14662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // when offset is at box's caretMinOffset and the direction is DirectionRight, should it be taken care as a general case?
14672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (offset == box->caretLeftmostOffset())
14682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return leftWordBoundary(box->prevLeafChild(), invalidOffset, blockDirection);
14692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (offset == box->caretRightmostOffset())
14702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return leftWordBoundary(box, offset, blockDirection);
14712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
14742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (box->direction() == blockDirection) {
14752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == RTL)
14762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = positionBeforeNextWord(visiblePosition);
14772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
14782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = previousWordPosition(visiblePosition);
14792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
14802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == RTL)
14812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = positionAfterPreviousWord(visiblePosition);
14822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
14832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = nextWordPosition(visiblePosition);
14842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (positionIsInsideBox(wordBreak, box))
14862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return wordBreak;
14872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WordBoundaryVector orderedWordBoundaries;
14892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (box->direction() == blockDirection)
14902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collectWordBreaksInBoxInsideBlockWithSameDirectionality(box, orderedWordBoundaries);
14912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else
14922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collectWordBreaksInBoxInsideBlockWithDifferntDirectionality(box, orderedWordBoundaries);
14932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int index = box->isLeftToRightDirection() ? greatestValueUnder(offset, blockDirection == LTR, orderedWordBoundaries) :
14952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        smallestOffsetAbove(offset, blockDirection == RTL, orderedWordBoundaries);
14962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (index != invalidOffset)
14972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return orderedWordBoundaries[index].visiblePosition;
14982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return leftWordBoundary(box->prevLeafChild(), invalidOffset, blockDirection);
15002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochVisiblePosition rightWordPosition(const VisiblePosition& visiblePosition)
15032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
15042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    InlineBox* box;
15052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int offset;
15062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    visiblePosition.getInlineBoxAndOffset(box, offset);
15072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    TextDirection blockDirection = directionOfEnclosingBlock(visiblePosition.deepEquivalent());
15082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (offset == box->caretLeftmostOffset())
15102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return rightWordBoundary(box, offset, blockDirection);
15112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (offset == box->caretRightmostOffset())
15122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return rightWordBoundary(box->nextLeafChild(), invalidOffset, blockDirection);
15132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    VisiblePosition wordBreak;
15152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (box->direction() == blockDirection) {
15162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == LTR)
15172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = positionBeforeNextWord(visiblePosition);
15182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
15192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = previousWordPosition(visiblePosition);
15202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
15212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (blockDirection == LTR)
15222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = positionAfterPreviousWord(visiblePosition);
15232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
15242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            wordBreak = nextWordPosition(visiblePosition);
15252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
15262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (positionIsInsideBox(wordBreak, box))
15272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return wordBreak;
15282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    WordBoundaryVector orderedWordBoundaries;
15302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (box->direction() == blockDirection)
15312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collectWordBreaksInBoxInsideBlockWithSameDirectionality(box, orderedWordBoundaries);
15322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else
15332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collectWordBreaksInBoxInsideBlockWithDifferntDirectionality(box, orderedWordBoundaries);
15342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int index = box->isLeftToRightDirection() ? smallestOffsetAbove(offset, blockDirection == LTR, orderedWordBoundaries) :
15352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        greatestValueUnder(offset, blockDirection == RTL, orderedWordBoundaries);
15362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (index != invalidOffset)
15372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return orderedWordBoundaries[index].visiblePosition;
15382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return rightWordBoundary(box->nextLeafChild(), invalidOffset, blockDirection);
15402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1543