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 "VisiblePosition.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CString.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FloatQuad.h"
325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "HTMLElement.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "InlineTextBox.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Logging.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Range.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition::VisiblePosition(const Position &pos, EAffinity affinity)
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    init(pos, affinity);
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition::VisiblePosition(Node *node, int offset, EAffinity affinity)
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(offset >= 0);
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    init(Position(node, offset), affinity);
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid VisiblePosition::init(const Position& position, EAffinity affinity)
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_affinity = affinity;
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_deepPosition = canonicalPosition(position);
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // When not at a line wrap, make sure to end up with DOWNSTREAM affinity.
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_affinity == UPSTREAM && (isNull() || inSameLine(VisiblePosition(position, DOWNSTREAM), *this)))
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_affinity = DOWNSTREAM;
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::next(bool stayInEditableContent) const
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition next(nextVisuallyDistinctCandidate(m_deepPosition), m_affinity);
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!stayInEditableContent)
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return next;
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return honorEditableBoundaryAtOrAfter(next);
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::previous(bool stayInEditableContent) const
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // find first previous DOM position that is visible
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = previousVisuallyDistinctCandidate(m_deepPosition);
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // return null visible position if there is no previous visible position
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (pos.atStartOfTree())
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM);
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(prev != *this);
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we should always be able to make the affinity DOWNSTREAM, because going previous from an
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // UPSTREAM position can never yield another UPSTREAM position (unless line wrap length is 0!).
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (prev.isNotNull() && m_affinity == UPSTREAM) {
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        VisiblePosition temp = prev;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        temp.setAffinity(UPSTREAM);
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(inSameLine(temp, prev));
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!stayInEditableContent)
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return prev;
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return honorEditableBoundaryAtOrBefore(prev);
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition VisiblePosition::leftVisuallyDistinctCandidate() const
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = m_deepPosition;
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!p.node())
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextDirection primaryDirection = LTR;
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->isBlockFlow()) {
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            primaryDirection = r->style()->direction();
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineBox* box;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int offset;
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!box)
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RenderObject* renderer = box->renderer();
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (true) {
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return box->direction() == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offset = box->direction() == LTR ? renderer->previousOffset(offset) : renderer->nextOffset(offset);
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMinOffset = box->caretMinOffset();
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMaxOffset = box->caretMaxOffset();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (offset > caretMinOffset && offset < caretMaxOffset)
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (box->direction() == LTR ? offset < caretMinOffset : offset > caretMaxOffset) {
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Overshot to the left.
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* prevBox = box->prevLeafChild();
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!prevBox)
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box = prevBox;
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = prevBox->caretRightmostOffset();
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(offset == box->caretLeftmostOffset());
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned char level = box->bidiLevel();
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* prevBox = box->prevLeafChild();
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (box->direction() == primaryDirection) {
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!prevBox || prevBox->bidiLevel() >= level)
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                level = prevBox->bidiLevel();
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* nextBox = box;
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                do {
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    nextBox = nextBox->nextLeafChild();
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } while (nextBox && nextBox->bidiLevel() > level);
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (nextBox && nextBox->bidiLevel() == level)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (InlineBox* prevBox = box->prevLeafChild()) {
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (prevBox->bidiLevel() < level)
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    box = prevBox;
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = box->caretRightmostOffset();
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box->direction() == primaryDirection)
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (prevBox) {
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box = prevBox;
1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = box->caretRightmostOffset();
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box->bidiLevel() > level) {
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    do {
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        prevBox = box->prevLeafChild();
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    } while (prevBox && prevBox->bidiLevel() > level);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!prevBox || prevBox->bidiLevel() < level)
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continue;
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Trailing edge of a secondary run. Set to the leading edge of the entire run.
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (true) {
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    while (InlineBox* nextBox = box->nextLeafChild()) {
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (nextBox->bidiLevel() < level)
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            break;
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        box = nextBox;
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (box->bidiLevel() == level)
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    level = box->bidiLevel();
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    while (InlineBox* prevBox = box->prevLeafChild()) {
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (prevBox->bidiLevel() < level)
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            break;
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        box = prevBox;
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (box->bidiLevel() == level)
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    level = box->bidiLevel();
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
2188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        p = Position(renderer->node(), offset);
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::left(bool stayInEditableContent) const
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = leftVisuallyDistinctCandidate();
2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // FIXME: Why can't we move left from the last position in a tree?
2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (pos.atStartOfTree() || pos.atEndOfTree())
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(left != *this);
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!stayInEditableContent)
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return left;
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This may need to do something different from "before".
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return honorEditableBoundaryAtOrBefore(left);
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition VisiblePosition::rightVisuallyDistinctCandidate() const
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = m_deepPosition;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!p.node())
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextDirection primaryDirection = LTR;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->isBlockFlow()) {
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            primaryDirection = r->style()->direction();
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineBox* box;
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int offset;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!box)
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RenderObject* renderer = box->renderer();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (true) {
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return box->direction() == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offset = box->direction() == LTR ? renderer->nextOffset(offset) : renderer->previousOffset(offset);
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMinOffset = box->caretMinOffset();
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMaxOffset = box->caretMaxOffset();
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (offset > caretMinOffset && offset < caretMaxOffset)
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (box->direction() == LTR ? offset > caretMaxOffset : offset < caretMinOffset) {
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Overshot to the right.
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* nextBox = box->nextLeafChild();
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!nextBox)
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box = nextBox;
2928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = nextBox->caretLeftmostOffset();
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(offset == box->caretRightmostOffset());
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned char level = box->bidiLevel();
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* nextBox = box->nextLeafChild();
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (box->direction() == primaryDirection) {
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!nextBox || nextBox->bidiLevel() >= level)
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                level = nextBox->bidiLevel();
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* prevBox = box;
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                do {
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    prevBox = prevBox->prevLeafChild();
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } while (prevBox && prevBox->bidiLevel() > level);
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // For example, abc 123 ^ CBA
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (InlineBox* nextBox = box->nextLeafChild()) {
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (nextBox->bidiLevel() < level)
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    box = nextBox;
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = box->caretLeftmostOffset();
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box->direction() == primaryDirection)
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (nextBox) {
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box = nextBox;
3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = box->caretLeftmostOffset();
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box->bidiLevel() > level) {
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    do {
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        nextBox = box->nextLeafChild();
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    } while (nextBox && nextBox->bidiLevel() > level);
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!nextBox || nextBox->bidiLevel() < level)
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continue;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Trailing edge of a secondary run. Set to the leading edge of the entire run.
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (true) {
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    while (InlineBox* prevBox = box->prevLeafChild()) {
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (prevBox->bidiLevel() < level)
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            break;
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        box = prevBox;
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (box->bidiLevel() == level)
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    level = box->bidiLevel();
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    while (InlineBox* nextBox = box->nextLeafChild()) {
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (nextBox->bidiLevel() < level)
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            break;
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        box = nextBox;
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (box->bidiLevel() == level)
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    level = box->bidiLevel();
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
3618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                renderer = box->renderer();
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        p = Position(renderer->node(), offset);
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::right(bool stayInEditableContent) const
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = rightVisuallyDistinctCandidate();
3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // FIXME: Why can't we move left from the last position in a tree?
3788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (pos.atStartOfTree() || pos.atEndOfTree())
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition right = VisiblePosition(pos, DOWNSTREAM);
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(right != *this);
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!stayInEditableContent)
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return right;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This may need to do something different from "after".
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return honorEditableBoundaryAtOrAfter(right);
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::honorEditableBoundaryAtOrBefore(const VisiblePosition &pos) const
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.isNull())
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(deepEquivalent());
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return empty position if pos is not somewhere inside the editable region containing this position
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (highestRoot && !pos.deepEquivalent().node()->isDescendantOf(highestRoot))
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return pos itself if the two are from the very same editable region, or both are non-editable
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
4048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return empty position if this position is non-editable, but pos is editable
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Move to the previous non-editable region.
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return the last position before pos that is in the same editable region as this position
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastEditablePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot);
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition VisiblePosition::honorEditableBoundaryAtOrAfter(const VisiblePosition &pos) const
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.isNull())
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = highestEditableRoot(deepEquivalent());
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return empty position if pos is not somewhere inside the editable region containing this position
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (highestRoot && !pos.deepEquivalent().node()->isDescendantOf(highestRoot))
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return pos itself if the two are from the very same editable region, or both are non-editable
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return empty position if this position is non-editable, but pos is editable
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Move to the next non-editable region.
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return the next position after pos that is in the same editable region as this position
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return firstEditablePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot);
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic Position canonicalizeCandidate(const Position& candidate)
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (candidate.isNull())
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(candidate.isCandidate());
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position upstream = candidate.upstream();
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (upstream.isCandidate())
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return upstream;
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return candidate;
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition VisiblePosition::canonicalPosition(const Position& position)
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME (9535):  Canonicalizing to the leftmost candidate means that if we're at a line wrap, we will
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ask renderers to paint downstream carets for other renderers.
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // To fix this, we need to either a) add code to all paintCarets to pass the responsibility off to
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the appropriate renderer for VisiblePosition's like these, or b) canonicalize to the rightmost candidate
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // unless the affinity is upstream.
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = position.node();
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node->document()->updateLayoutIgnorePendingStylesheets();
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position candidate = position.upstream();
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (candidate.isCandidate())
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return candidate;
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    candidate = position.downstream();
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (candidate.isCandidate())
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return candidate;
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // When neither upstream or downstream gets us to a candidate (upstream/downstream won't leave
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // blocks or enter new ones), we search forward and backward until we find one.
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position next = canonicalizeCandidate(nextCandidate(position));
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position prev = canonicalizeCandidate(previousCandidate(position));
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nextNode = next.node();
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* prevNode = prev.node();
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The new position must be in the same editable element. Enforce that first.
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Unless the descent is from a non-editable html element to an editable body.
4838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (node->hasTagName(htmlTag) && !node->isContentEditable() && node->document()->body() && node->document()->body()->isContentEditable())
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return next.isNotNull() ? next : prev;
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* editingRoot = editableRootForPosition(position);
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the html element is editable, descending into its body will look like a descent
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // from non-editable to editable content since rootEditableElement() always stops at the body.
4908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if ((editingRoot && editingRoot->hasTagName(htmlTag)) || position.node()->isDocumentNode())
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return next.isNotNull() ? next : prev;
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool prevIsInSameEditableElement = prevNode && editableRootForPosition(prev) == editingRoot;
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool nextIsInSameEditableElement = nextNode && editableRootForPosition(next) == editingRoot;
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (prevIsInSameEditableElement && !nextIsInSameEditableElement)
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return prev;
4978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (nextIsInSameEditableElement && !prevIsInSameEditableElement)
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return next;
5008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!nextIsInSameEditableElement && !prevIsInSameEditableElement)
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The new position should be in the same block flow element. Favor that.
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *originalBlock = node->enclosingBlockFlowElement();
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool nextIsOutsideOriginalBlock = !nextNode->isDescendantOf(originalBlock) && nextNode != originalBlock;
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool prevIsOutsideOriginalBlock = !prevNode->isDescendantOf(originalBlock) && prevNode != originalBlock;
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (nextIsOutsideOriginalBlock && !prevIsOutsideOriginalBlock)
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return prev;
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return next;
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5145f1ab04193ad0130ca8204aadaceae083aca9881Feng QianUChar32 VisiblePosition::characterAfter() const
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We canonicalize to the first of two equivalent candidates, but the second of the two candidates
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // is the one that will be inside the text node containing the character after this visible position.
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position pos = m_deepPosition.downstream();
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = pos.node();
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node || !node->isTextNode())
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Text* textNode = static_cast<Text*>(pos.node());
5235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned offset = pos.deprecatedEditingOffset();
5245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned length = textNode->length();
5255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (offset >= length)
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
5275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar32 ch;
5295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    const UChar* characters = textNode->data().characters();
5305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    U16_NEXT(characters, offset, length, ch);
5315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return ch;
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
534635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectIntRect VisiblePosition::localCaretRect(RenderObject*& renderer) const
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = m_deepPosition.node();
537635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!node) {
538635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        renderer = 0;
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntRect();
540635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
541635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
542635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    renderer = node->renderer();
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntRect();
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* inlineBox;
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int caretOffset;
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    getInlineBoxAndOffset(inlineBox, caretOffset);
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (inlineBox)
5518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        renderer = inlineBox->renderer();
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return renderer->localCaretRect(inlineBox, caretOffset);
554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
556635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectIntRect VisiblePosition::absoluteCaretBounds() const
557635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
558635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderObject* renderer;
559635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    IntRect localRect = localCaretRect(renderer);
560635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (localRect.isEmpty() || !renderer)
561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return IntRect();
562635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
563635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
564635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
565635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
566635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint VisiblePosition::xOffsetForVerticalNavigation() const
567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderObject* renderer;
569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    IntRect localRect = localCaretRect(renderer);
570635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (localRect.isEmpty() || !renderer)
571635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
572635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
573635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // This ignores transforms on purpose, for now. Vertical navigation is done
574635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // without consulting transforms, so that 'up' in transformed text is 'up'
575635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // relative to the text, not absolute 'up'.
576635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return renderer->localToAbsolute(localRect.location()).x();
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid VisiblePosition::debugPosition(const char* msg) const
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fprintf(stderr, "Position [%s]: null\n", msg);
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
5845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().utf8().data(), m_deepPosition.node(), m_deepPosition.deprecatedEditingOffset());
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid VisiblePosition::formatForDebugger(char* buffer, unsigned length) const
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_deepPosition.formatForDebugger(buffer, length);
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid VisiblePosition::showTreeForThis() const
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_deepPosition.showTreeForThis();
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition &end)
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
603635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (start.isNull() || end.isNull())
604635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
605635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position s = rangeCompliantEquivalent(start);
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position e = rangeCompliantEquivalent(end);
6085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return Range::create(s.node()->document(), s.node(), s.deprecatedEditingOffset(), e.node(), e.deprecatedEditingOffset());
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startVisiblePosition(const Range *r, EAffinity affinity)
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int exception = 0;
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(r->startContainer(exception), r->startOffset(exception), affinity);
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endVisiblePosition(const Range *r, EAffinity affinity)
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int exception = 0;
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(r->endContainer(exception), r->endOffset(exception), affinity);
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool setStart(Range *r, const VisiblePosition &visiblePosition)
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!r)
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = rangeCompliantEquivalent(visiblePosition);
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int code = 0;
6295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    r->setStart(p.node(), p.deprecatedEditingOffset(), code);
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return code == 0;
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool setEnd(Range *r, const VisiblePosition &visiblePosition)
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!r)
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = rangeCompliantEquivalent(visiblePosition);
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int code = 0;
6395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    r->setEnd(p.node(), p.deprecatedEditingOffset(), code);
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return code == 0;
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode *enclosingBlockFlowElement(const VisiblePosition &visiblePosition)
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return NULL;
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return visiblePosition.deepEquivalent().node()->enclosingBlockFlowElement();
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isFirstVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node)
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!visiblePosition.deepEquivalent().node()->isDescendantOf(node))
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition previous = visiblePosition.previous();
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return previous.isNull() || !previous.deepEquivalent().node()->isDescendantOf(node);
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isLastVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node)
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!visiblePosition.deepEquivalent().node()->isDescendantOf(node))
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition next = visiblePosition.next();
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return next.isNull() || !next.deepEquivalent().node()->isDescendantOf(node);
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}  // namespace WebCore
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid showTree(const WebCore::VisiblePosition* vpos)
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (vpos)
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        vpos->showTreeForThis();
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid showTree(const WebCore::VisiblePosition& vpos)
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    vpos.showTreeForThis();
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
691