18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2004, 2005, 2006, 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 "Position.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSComputedStyleDeclaration.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Logging.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PositionIterator.h"
32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "RenderBlock.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h"
35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "VisiblePosition.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h>
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h>
402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.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
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic Node* nextRenderedEditable(Node* node)
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    while ((node = node->nextLeafNode())) {
492bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!node->rendererIsEditable())
50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* renderer = node->renderer();
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!renderer)
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return node;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic Node* previousRenderedEditable(Node* node)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    while ((node = node->previousLeafNode())) {
632bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!node->rendererIsEditable())
64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* renderer = node->renderer();
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!renderer)
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox()))
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return node;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
745f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPosition::Position(PassRefPtr<Node> anchorNode, int offset)
755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    : m_anchorNode(anchorNode)
765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_offset(offset)
775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_anchorType(anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset))
785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_isLegacyEditingPosition(true)
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
825f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPosition::Position(PassRefPtr<Node> anchorNode, AnchorType anchorType)
835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    : m_anchorNode(anchorNode)
845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_offset(0)
855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_anchorType(anchorType)
865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_isLegacyEditingPosition(false)
875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(anchorType != PositionIsOffsetInAnchor);
895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
915f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPosition::Position(PassRefPtr<Node> anchorNode, int offset, AnchorType anchorType)
925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    : m_anchorNode(anchorNode)
935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_offset(offset)
945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_anchorType(anchorType)
955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_isLegacyEditingPosition(false)
965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(!m_anchorNode || !editingIgnoresContent(m_anchorNode.get()));
985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(anchorType == PositionIsOffsetInAnchor);
995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid Position::moveToPosition(PassRefPtr<Node> node, int offset)
1025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(!editingIgnoresContent(node.get()));
1045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
1055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_anchorNode = node;
1065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_offset = offset;
1075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_isLegacyEditingPosition)
1085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
1095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid Position::moveToOffset(int offset)
1115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(anchorType() == PositionIsOffsetInAnchor || m_isLegacyEditingPosition);
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_offset = offset;
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_isLegacyEditingPosition)
1155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_anchorType = anchorTypeForLegacyEditingPosition(m_anchorNode.get(), m_offset);
1165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1185f1ab04193ad0130ca8204aadaceae083aca9881Feng QianNode* Position::containerNode() const
1195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_anchorNode)
1215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    switch (anchorType()) {
1245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsOffsetInAnchor:
1255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode.get();
1265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsBeforeAnchor:
1275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsAfterAnchor:
1285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->parentNode();
1295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT_NOT_REACHED();
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianint Position::computeOffsetInContainerNode() const
1355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_anchorNode)
1375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
1385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    switch (anchorType()) {
1405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsOffsetInAnchor:
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return std::min(lastOffsetInNode(m_anchorNode.get()), m_offset);
1425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsBeforeAnchor:
1435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->nodeIndex();
1445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsAfterAnchor:
1455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->nodeIndex() + 1;
1465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT_NOT_REACHED();
1485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return 0;
1495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochint Position::offsetForPositionAfterAnchor() const
15281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
15381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(m_anchorType == PositionIsAfterAnchor);
15481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(!m_isLegacyEditingPosition);
15581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return lastOffsetForEditing(m_anchorNode.get());
15681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
15781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
158ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch// Neighbor-anchored positions are invalid DOM positions, so they need to be
159ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch// fixed up before handing them off to the Range object.
160ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen MurdochPosition Position::parentAnchoredEquivalent() const
161ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
162ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!m_anchorNode)
163ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return Position();
164ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
165ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_offset <= 0 && m_anchorType != PositionIsAfterAnchor) {
167ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (m_anchorNode->parentNode() && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get())))
168ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            return positionInParentBeforeNode(m_anchorNode.get());
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block        return firstPositionInOrBeforeNode(m_anchorNode.get());
170ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!m_anchorNode->offsetInCharacters() && (m_anchorType == PositionIsAfterAnchor || static_cast<unsigned>(m_offset) == m_anchorNode->childNodeCount())
172ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        && (editingIgnoresContent(m_anchorNode.get()) || isTableElement(m_anchorNode.get()))) {
173ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return positionInParentAfterNode(m_anchorNode.get());
174ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
175ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
176ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    return Position(containerNode(), computeOffsetInContainerNode(), PositionIsOffsetInAnchor);
177ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
178ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
1795f1ab04193ad0130ca8204aadaceae083aca9881Feng QianNode* Position::computeNodeBeforePosition() const
1805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_anchorNode)
1825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
1835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    switch (anchorType()) {
1855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsOffsetInAnchor:
1865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->childNode(m_offset - 1); // -1 converts to childNode((unsigned)-1) and returns null.
1875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsBeforeAnchor:
1885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->previousSibling();
1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsAfterAnchor:
1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode.get();
1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT_NOT_REACHED();
1935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return 0;
1945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1965f1ab04193ad0130ca8204aadaceae083aca9881Feng QianNode* Position::computeNodeAfterPosition() const
1975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_anchorNode)
1995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
2005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    switch (anchorType()) {
2025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsOffsetInAnchor:
2035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->childNode(m_offset);
2045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsBeforeAnchor:
2055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode.get();
2065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    case PositionIsAfterAnchor:
2075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_anchorNode->nextSibling();
2085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT_NOT_REACHED();
2105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return 0;
2115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
2125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2135f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPosition::AnchorType Position::anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset)
2145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
2155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (anchorNode && editingIgnoresContent(anchorNode)) {
2165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (offset == 0)
2175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return Position::PositionIsBeforeAnchor;
2185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return Position::PositionIsAfterAnchor;
2195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return Position::PositionIsOffsetInAnchor;
2215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
2225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian// FIXME: This method is confusing (does it return anchorNode() or containerNode()?) and should be renamed or removed
2245f1ab04193ad0130ca8204aadaceae083aca9881Feng QianElement* Position::element() const
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Node* n = anchorNode();
2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    while (n && !n->isElementNode())
2285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        n = n->parentNode();
2295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return static_cast<Element*>(n);
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<CSSComputedStyleDeclaration> Position::computedStyle() const
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Element* elem = element();
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!elem)
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return WebCore::computedStyle(elem);
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPosition Position::previous(PositionMoveType moveType) const
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
24281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* n = deprecatedNode();
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return *this;
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block    int o = deprecatedEditingOffset();
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(o >= 0);
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (o > 0) {
2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        Node* child = n->childNode(o - 1);
2528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (child)
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block            return lastPositionInOrAfterNode(child);
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // There are two reasons child might be 0:
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //   1) The node is node like a text node that is not an element, and therefore has no children.
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //      Going backward one character at a time is correct.
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //   2) The old offset was a bogus offset like (<br>, 1), and there is no child.
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //      Going from 1 to 0 is correct.
2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        switch (moveType) {
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case CodePoint:
2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            return Position(n, o - 1);
2638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case Character:
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            return Position(n, uncheckedPreviousOffset(n, o));
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case BackwardDeletion:
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            return Position(n, uncheckedPreviousOffsetForBackwardDeletion(n, o));
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
270a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ContainerNode* parent = n->parentNode();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parent)
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return *this;
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(parent, n->nodeIndex());
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPosition Position::next(PositionMoveType moveType) const
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(moveType != BackwardDeletion);
2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
28181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* n = deprecatedNode();
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return *this;
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block    int o = deprecatedEditingOffset();
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(o >= 0);
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* child = n->childNode(o);
2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (child || (!n->hasChildNodes() && o < lastOffsetForEditing(n))) {
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (child)
2922bde8e466a4451c7319e3a072d118917957d6554Steve Block            return firstPositionInOrBeforeNode(child);
2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // There are two reasons child might be 0:
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //   1) The node is node like a text node that is not an element, and therefore has no children.
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //      Going forward one character at a time is correct.
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //      Going from 0 to 1 is correct.
2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return Position(n, (moveType == Character) ? uncheckedNextOffset(n, o) : o + 1);
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
302a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ContainerNode* parent = n->parentNode();
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parent)
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return *this;
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(parent, n->nodeIndex() + 1);
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint Position::uncheckedPreviousOffset(const Node* n, int current)
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return n->renderer() ? n->renderer()->previousOffset(current) : current - 1;
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianint Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current)
3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1;
3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint Position::uncheckedNextOffset(const Node* n, int current)
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return n->renderer() ? n->renderer()->nextOffset(current) : current + 1;
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool Position::atFirstEditingPositionForNode() const
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isNull())
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
3282bde8e466a4451c7319e3a072d118917957d6554Steve Block    return m_anchorType == PositionIsBeforeAnchor || m_offset <= 0;
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool Position::atLastEditingPositionForNode() const
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isNull())
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
3352bde8e466a4451c7319e3a072d118917957d6554Steve Block    return m_anchorType == PositionIsAfterAnchor || m_offset >= lastOffsetForEditing(deprecatedNode());
3368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
3378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// A position is considered at editing boundary if one of the following is true:
339643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// 1. It is the first position in the node and the next visually equivalent position
340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//    is non editable.
341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// 2. It is the last position in the node and the previous visually equivalent position
342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//    is non editable.
343643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// 3. It is an editable position and both the next and previous visually equivalent
344643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//    positions are both non editable.
345643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool Position::atEditingBoundary() const
346643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
347643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Position nextPosition = downstream(CanCrossEditingBoundary);
3482bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable())
349643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return true;
350643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
351643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Position prevPosition = upstream(CanCrossEditingBoundary);
3522bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable())
353643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return true;
354643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
3552bde8e466a4451c7319e3a072d118917957d6554Steve Block    return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->rendererIsEditable()
3562bde8e466a4451c7319e3a072d118917957d6554Steve Block        && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->rendererIsEditable();
357643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
358643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
359dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochNode* Position::parentEditingBoundary() const
360dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{
361dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!m_anchorNode || !m_anchorNode->document())
362dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return 0;
363dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
364dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Node* documentElement = m_anchorNode->document()->documentElement();
365dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!documentElement)
366dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return 0;
367dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
368dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Node* boundary = m_anchorNode.get();
3692bde8e466a4451c7319e3a072d118917957d6554Steve Block    while (boundary != documentElement && boundary->parentNode() && m_anchorNode->rendererIsEditable() == boundary->parentNode()->rendererIsEditable())
370dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        boundary = boundary->parentNode();
371dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
372dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    return boundary;
373dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch}
374dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
375dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
3768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool Position::atStartOfTree() const
3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isNull())
3798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return true;
38081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return !deprecatedNode()->parentNode() && m_offset <= 0;
3818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
3828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool Position::atEndOfTree() const
3848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
3858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isNull())
3868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return true;
38781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return !deprecatedNode()->parentNode() && m_offset >= lastOffsetForEditing(deprecatedNode());
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint Position::renderedOffset() const
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
39281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!deprecatedNode()->isTextNode())
3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return m_offset;
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
39581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!deprecatedNode()->renderer())
3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return m_offset;
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = 0;
39981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderText* textRenderer = toRenderText(deprecatedNode()->renderer());
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
401635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int start = box->start();
402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int end = box->start() + box->len();
4038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_offset < start)
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return result;
4058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_offset <= end) {
4068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            result += m_offset - start;
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return result;
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
409635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        result += box->len();
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// return first preceding DOM position rendered at a different location, or "this"
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition Position::previousCharacterPosition(EAffinity affinity) const
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
42081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool atStartOfLine = isStartOfLine(VisiblePosition(*this, affinity));
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool rendered = isCandidate();
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position currentPos = *this;
4268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    while (!currentPos.atStartOfTree()) {
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        currentPos = currentPos.previous();
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
42981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return *this;
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (atStartOfLine || !rendered) {
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentPos.isCandidate())
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return currentPos;
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (rendersInDifferentPosition(currentPos))
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return currentPos;
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return *this;
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// return first following position rendered at a different location, or "this"
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition Position::nextCharacterPosition(EAffinity affinity) const
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
44881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* fromRootEditableElement = deprecatedNode()->rootEditableElement();
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool atEndOfLine = isEndOfLine(VisiblePosition(*this, affinity));
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool rendered = isCandidate();
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position currentPos = *this;
4548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    while (!currentPos.atEndOfTree()) {
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        currentPos = currentPos.next();
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
45781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (currentPos.deprecatedNode()->rootEditableElement() != fromRootEditableElement)
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return *this;
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (atEndOfLine || !rendered) {
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentPos.isCandidate())
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return currentPos;
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (rendersInDifferentPosition(currentPos))
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return currentPos;
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return *this;
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// If true, adjacent candidates are visually distinct.
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Share code with isCandidate, if possible.
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool endsOfNodeAreVisuallyDistinctPositions(Node* node)
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node || !node->renderer())
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node->renderer()->isInline())
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Don't include inline tables.
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->hasTagName(tableTag))
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // There is a VisiblePosition inside an empty inline-block container.
487635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return node->renderer()->isReplaced() && canHaveChildrenForEditing(node) && toRenderBox(node->renderer())->height() != 0 && !node->firstChild();
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* enclosingVisualBoundary(Node* node)
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node && !endsOfNodeAreVisuallyDistinctPositions(node))
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node;
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// upstream() and downstream() want to return positions that are either in a
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// text node or at just before a non-text node.  This method checks for that.
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool isStreamer(const PositionIterator& pos)
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!pos.node())
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isAtomicNode(pos.node()))
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return pos.atStartOfNode();
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This function and downstream() are used for moving back and forth between visually equivalent candidates.
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// that map to the VisiblePosition between 'b' and the space.  This function will return the left candidate
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// and downstream() will return the right one.
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Also, upstream() will return [boundary, 0] for any of the positions from [boundary, 0] to the first candidate
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true.
517643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockPosition Position::upstream(EditingBoundaryCrossingRule rule) const
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
51981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* startNode = deprecatedNode();
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!startNode)
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // iterate backward from there, looking for a qualified position
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* boundary = enclosingVisualBoundary(startNode);
52581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: PositionIterator should respect Before and After positions.
52681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? Position(m_anchorNode, caretMaxOffset(m_anchorNode.get())) : *this;
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator currentPos = lastVisible;
5282bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool startEditable = startNode->rendererIsEditable();
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* lastNode = startNode;
530643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool boundaryCrossed = false;
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (; !currentPos.atStart(); currentPos.decrement()) {
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Node* currentNode = currentPos.node();
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Don't check for an editability change if we haven't moved to a different node,
5352bde8e466a4451c7319e3a072d118917957d6554Steve Block        // to avoid the expense of computing rendererIsEditable().
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currentNode != lastNode) {
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Don't change editability.
5382bde8e466a4451c7319e3a072d118917957d6554Steve Block            bool currentEditable = currentNode->rendererIsEditable();
539643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (startEditable != currentEditable) {
540643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (rule == CannotCrossEditingBoundary)
541643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    break;
542643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                boundaryCrossed = true;
543643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            }
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            lastNode = currentNode;
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
547d0825bca7fe65beaee391d30da42e937db621564Steve Block        // If we've moved to a position that is visually distinct, return the last saved position. There
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // is code below that terminates early if we're *about* to move to a visually distinct position.
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return lastVisible;
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // skip position in unrendered or invisible node
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* renderer = currentNode->renderer();
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!renderer || renderer->style()->visibility() != VISIBLE)
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
557643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (rule == CanCrossEditingBoundary && boundaryCrossed) {
558643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            lastVisible = currentPos;
559643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
560643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
561643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // track last visible streamer position
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isStreamer(currentPos))
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            lastVisible = currentPos;
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Don't move past a position that is visually distinct.  We could rely on code above to terminate and
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // return lastVisible on the next iteration, but we terminate early to avoid doing a nodeIndex() call.
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentPos.atStartOfNode())
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return lastVisible;
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Return position after tables and nodes which have content that can be ignored.
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentPos.atEndOfNode())
5742bde8e466a4451c7319e3a072d118917957d6554Steve Block                return positionAfterNode(currentNode);
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // return current position if it is in rendered text
579635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentNode != startNode) {
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // This assertion fires in layout tests in the case-transform.html test because
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // of a mix-up between offsets in the text in the DOM tree with text in the
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // render tree which can have a different length due to case transformation.
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Until we resolve that, disable this so we can run the layout tests!
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                //ASSERT(currentOffset >= renderer->caretMaxOffset());
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return Position(currentNode, renderer->caretMaxOffset());
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned textOffset = currentPos.offsetInLeafNode();
590635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderText* textRenderer = toRenderText(renderer);
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineTextBox* lastTextBox = textRenderer->lastTextBox();
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (textOffset <= box->start() + box->len()) {
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (textOffset > box->start())
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        return currentPos;
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box == lastTextBox || textOffset != box->start() + box->len() + 1)
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // The text continues on the next line only if the last text box is not on this line and
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // none of the boxes on this line have a larger start offset.
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                bool continuesOnNextLine = true;
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* otherBox = box;
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (continuesOnNextLine) {
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    otherBox = otherBox->nextLeafChild();
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!otherBox)
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
6118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continuesOnNextLine = false;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                otherBox = box;
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (continuesOnNextLine) {
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    otherBox = otherBox->prevLeafChild();
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!otherBox)
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
6208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset))
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continuesOnNextLine = false;
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (continuesOnNextLine)
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return currentPos;
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastVisible;
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This function and upstream() are used for moving back and forth between visually equivalent candidates.
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// For example, for the text node "foo     bar" where whitespace is collapsible, there are two candidates
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// that map to the VisiblePosition between 'b' and the space.  This function will return the right candidate
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// and upstream() will return the left one.
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Also, downstream() will return the last position in the last atomic node in boundary for all of the positions
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPositions(boundary).
639643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockPosition Position::downstream(EditingBoundaryCrossingRule rule) const
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
64181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* startNode = deprecatedNode();
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!startNode)
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // iterate forward from there, looking for a qualified position
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* boundary = enclosingVisualBoundary(startNode);
64781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: PositionIterator should respect Before and After positions.
64881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? Position(m_anchorNode, caretMaxOffset(m_anchorNode.get())) : *this;
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator currentPos = lastVisible;
6502bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool startEditable = startNode->rendererIsEditable();
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* lastNode = startNode;
652643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool boundaryCrossed = false;
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (; !currentPos.atEnd(); currentPos.increment()) {
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Node* currentNode = currentPos.node();
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Don't check for an editability change if we haven't moved to a different node,
6572bde8e466a4451c7319e3a072d118917957d6554Steve Block        // to avoid the expense of computing rendererIsEditable().
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currentNode != lastNode) {
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Don't change editability.
6602bde8e466a4451c7319e3a072d118917957d6554Steve Block            bool currentEditable = currentNode->rendererIsEditable();
661643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (startEditable != currentEditable) {
662643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (rule == CannotCrossEditingBoundary)
663643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    break;
664643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                boundaryCrossed = true;
665643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            }
666643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            lastNode = currentNode;
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // stop before going above the body, up into the head
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // return the last visible streamer position
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currentNode->hasTagName(bodyTag) && currentPos.atEndOfNode())
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Do not move to a visually distinct position.
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode != boundary)
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return lastVisible;
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Do not move past a visually disinct position.
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Note: The first position after the last in a node whose ends are visually distinct
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // positions will be [boundary->parentNode(), originalBlock->nodeIndex() + 1].
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (boundary && boundary->parentNode() == currentNode)
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return lastVisible;
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // skip position in unrendered or invisible node
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* renderer = currentNode->renderer();
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!renderer || renderer->style()->visibility() != VISIBLE)
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
689643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (rule == CanCrossEditingBoundary && boundaryCrossed) {
690643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            lastVisible = currentPos;
691643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            break;
692643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
693643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // track last visible streamer position
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isStreamer(currentPos))
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            lastVisible = currentPos;
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Return position before tables and nodes which have content that can be ignored.
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return Position(currentNode, renderer->caretMinOffset());
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // return current position if it is in rendered text
706635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (renderer->isText() && toRenderText(renderer)->firstTextBox()) {
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (currentNode != startNode) {
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(currentPos.atStartOfNode());
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return Position(currentNode, renderer->caretMinOffset());
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned textOffset = currentPos.offsetInLeafNode();
713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderText* textRenderer = toRenderText(renderer);
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineTextBox* lastTextBox = textRenderer->lastTextBox();
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (textOffset <= box->end()) {
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (textOffset >= box->start())
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        return currentPos;
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (box == lastTextBox || textOffset != box->start() + box->len())
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // The text continues on the next line only if the last text box is not on this line and
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // none of the boxes on this line have a larger start offset.
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                bool continuesOnNextLine = true;
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                InlineBox* otherBox = box;
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (continuesOnNextLine) {
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    otherBox = otherBox->nextLeafChild();
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!otherBox)
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
7348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continuesOnNextLine = false;
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                otherBox = box;
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (continuesOnNextLine) {
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    otherBox = otherBox->prevLeafChild();
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!otherBox)
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
7438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset))
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continuesOnNextLine = false;
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (continuesOnNextLine)
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return currentPos;
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastVisible;
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* stop = renderer->nextInPreOrderAfterChildren();
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())
7608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (o->node()) {
761635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if ((o->isText() && toRenderText(o)->linesBoundingBox().height()) ||
762635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                (o->isBox() && toRenderBox(o)->borderBoundingBox().height()))
763635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                return true;
764635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::nodeIsUserSelectNone(Node* node)
7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_NONE;
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::isCandidate() const
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
77881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deprecatedNode()->renderer();
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->visibility() != VISIBLE)
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->isBR())
7862bde8e466a4451c7319e3a072d118917957d6554Steve Block        // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor, but for now we still need to support legacy positions.
7872bde8e466a4451c7319e3a072d118917957d6554Steve Block        return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->isText())
79081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return !nodeIsUserSelectNone(deprecatedNode()) && inRenderedText();
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
79281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (isTableElement(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
79381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
795d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (m_anchorNode->hasTagName(htmlTag))
796d0825bca7fe65beaee391d30da42e937db621564Steve Block        return false;
797d0825bca7fe65beaee391d30da42e937db621564Steve Block
798d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (renderer->isBlockFlow()) {
799643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (toRenderBlock(renderer)->height() || m_anchorNode->hasTagName(bodyTag)) {
800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer))
80181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                return atFirstEditingPositionForNode() && !Position::nodeIsUserSelectNone(deprecatedNode());
8022bde8e466a4451c7319e3a072d118917957d6554Steve Block            return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
804d0825bca7fe65beaee391d30da42e937db621564Steve Block    } else
8052bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_anchorNode->rendererIsEditable() && !Position::nodeIsUserSelectNone(deprecatedNode()) && atEditingBoundary();
806643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::inRenderedText() const
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
81281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (isNull() || !deprecatedNode()->isTextNode())
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
81581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deprecatedNode()->renderer();
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
819635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderText *textRenderer = toRenderText(renderer);
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
8218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The offset we're looking for is before this node
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // this means the offset must be in content that is
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // not rendered. Return false.
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (box->containsCaretOffset(m_offset))
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Return false for offsets inside composed characters.
8298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset));
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic unsigned caretMaxRenderedOffset(const Node* n)
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = n->renderer();
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (r)
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return r->caretMaxRenderedOffset();
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (n->isCharacterDataNode())
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return static_cast<const CharacterData*>(n)->length();
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 1;
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::isRenderedCharacter() const
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
84881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (isNull() || !deprecatedNode()->isTextNode())
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
85181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deprecatedNode()->renderer();
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
855635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderText* textRenderer = toRenderText(renderer);
856635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
8578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) {
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The offset we're looking for is before this node
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // this means the offset must be in content that is
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // not rendered. Return false.
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len()))
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool Position::rendersInDifferentPosition(const Position &pos) const
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull() || pos.isNull())
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
87581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deprecatedNode()->renderer();
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
87981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* posRenderer = pos.deprecatedNode()->renderer();
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!posRenderer)
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->visibility() != VISIBLE ||
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        posRenderer->style()->visibility() != VISIBLE)
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
88781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (deprecatedNode() == pos.deprecatedNode()) {
88881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (deprecatedNode()->hasTagName(brTag))
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_offset == pos.deprecatedEditingOffset())
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
89481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!deprecatedNode()->isTextNode() && !pos.deprecatedNode()->isTextNode()) {
8955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (m_offset != pos.deprecatedEditingOffset())
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return true;
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (deprecatedNode()->hasTagName(brTag) && pos.isCandidate())
9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (pos.deprecatedNode()->hasTagName(brTag) && isCandidate())
9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (deprecatedNode()->enclosingBlockFlowElement() != pos.deprecatedNode()->enclosingBlockFlowElement())
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (deprecatedNode()->isTextNode() && !inRenderedText())
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
91281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (pos.deprecatedNode()->isTextNode() && !pos.inRenderedText())
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int thisRenderedOffset = renderedOffset();
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int posRenderedOffset = pos.renderedOffset();
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int ignoredCaretOffset;
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* b1;
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineBox* b2;
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
93181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(deprecatedNode()), caretMaxRenderedOffset(deprecatedNode()));
93281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.deprecatedNode()), caretMaxRenderedOffset(pos.deprecatedNode()));
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Editing, "----------------------------------------------------------------------\n");
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!b1 || !b2) {
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (b1->root() != b2->root()) {
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
94381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (nextRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
94481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        && thisRenderedOffset == (int)caretMaxRenderedOffset(deprecatedNode()) && !posRenderedOffset) {
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
94881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (previousRenderedEditable(deprecatedNode()) == pos.deprecatedNode()
94981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        && !thisRenderedOffset && posRenderedOffset == (int)caretMaxRenderedOffset(pos.deprecatedNode())) {
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This assumes that it starts in editable content.
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition Position::leadingWhitespacePosition(EAffinity affinity, bool considerNonCollapsibleWhitespace) const
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(isEditablePosition(*this));
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
96381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (upstream().deprecatedNode()->hasTagName(brTag))
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position prev = previousCharacterPosition(affinity);
96781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (prev != *this && prev.deprecatedNode()->inSameContainingBlockFlowElement(deprecatedNode()) && prev.deprecatedNode()->isTextNode()) {
96881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        String string = static_cast<Text *>(prev.deprecatedNode())->data();
9695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        UChar c = string[prev.deprecatedEditingOffset()];
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isEditablePosition(prev))
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return prev;
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This assumes that it starts in editable content.
979635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPosition Position::trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace) const
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(isEditablePosition(*this));
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition v(*this);
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar c = v.characterAfter();
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The space must not be in another paragraph and it must be editable.
9882bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!isEndOfParagraph(v) && v.next(CannotCrossEditingBoundary).isNotNull())
9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c))
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return *this;
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
997dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1000635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool isNonTextLeafChild(RenderObject* object)
1001635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1002635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (object->firstChild())
1003635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return false;
1004635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (object->isText())
1005635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return false;
1006635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return true;
1007635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
1008635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1009635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer)
1010635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1011635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderBlock* container = renderer->containingBlock();
1012635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RenderObject* next = renderer;
1013635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while ((next = next->nextInPreOrder(container))) {
1014635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (next->isRenderBlock())
10150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return 0;
1016635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (next->isBR())
10170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return 0;
1018635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (isNonTextLeafChild(next))
10190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return 0;
1020635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (next->isText()) {
10210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            InlineTextBox* match = 0;
10220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            int minOffset = INT_MAX;
1023635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; box = box->nextTextBox()) {
1024635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                int caretMinOffset = box->caretMinOffset();
1025635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                if (caretMinOffset < minOffset) {
1026635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    match = box;
1027635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    minOffset = caretMinOffset;
1028635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                }
1029635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
10300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (match)
10310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return match;
1032635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
1033635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
10340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 0;
1035635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
1036635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
103721939df44de1705786c545cd1bf519d47250322dBen Murdochstatic Position downstreamIgnoringEditingBoundaries(Position position)
103821939df44de1705786c545cd1bf519d47250322dBen Murdoch{
103921939df44de1705786c545cd1bf519d47250322dBen Murdoch    Position lastPosition;
104021939df44de1705786c545cd1bf519d47250322dBen Murdoch    while (position != lastPosition) {
104121939df44de1705786c545cd1bf519d47250322dBen Murdoch        lastPosition = position;
10424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        position = position.downstream(CanCrossEditingBoundary);
104321939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
104421939df44de1705786c545cd1bf519d47250322dBen Murdoch    return position;
104521939df44de1705786c545cd1bf519d47250322dBen Murdoch}
104621939df44de1705786c545cd1bf519d47250322dBen Murdoch
104721939df44de1705786c545cd1bf519d47250322dBen Murdochstatic Position upstreamIgnoringEditingBoundaries(Position position)
104821939df44de1705786c545cd1bf519d47250322dBen Murdoch{
104921939df44de1705786c545cd1bf519d47250322dBen Murdoch    Position lastPosition;
105021939df44de1705786c545cd1bf519d47250322dBen Murdoch    while (position != lastPosition) {
105121939df44de1705786c545cd1bf519d47250322dBen Murdoch        lastPosition = position;
10524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        position = position.upstream(CanCrossEditingBoundary);
105321939df44de1705786c545cd1bf519d47250322dBen Murdoch    }
105421939df44de1705786c545cd1bf519d47250322dBen Murdoch    return position;
105521939df44de1705786c545cd1bf519d47250322dBen Murdoch}
105621939df44de1705786c545cd1bf519d47250322dBen Murdoch
10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10592bde8e466a4451c7319e3a072d118917957d6554Steve Block    caretOffset = deprecatedEditingOffset();
106081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deprecatedNode()->renderer();
106121939df44de1705786c545cd1bf519d47250322dBen Murdoch
10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer->isText()) {
106321939df44de1705786c545cd1bf519d47250322dBen Murdoch        inlineBox = 0;
106481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
106521939df44de1705786c545cd1bf519d47250322dBen Murdoch            // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
106621939df44de1705786c545cd1bf519d47250322dBen Murdoch            // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
106721939df44de1705786c545cd1bf519d47250322dBen Murdoch            // of RenderObject::createVisiblePosition().
106821939df44de1705786c545cd1bf519d47250322dBen Murdoch            Position equivalent = downstreamIgnoringEditingBoundaries(*this);
10695af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            if (equivalent == *this) {
107021939df44de1705786c545cd1bf519d47250322dBen Murdoch                equivalent = upstreamIgnoringEditingBoundaries(*this);
10715af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke                if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this)
10725af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke                    return;
10735af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            }
107421939df44de1705786c545cd1bf519d47250322dBen Murdoch
107521939df44de1705786c545cd1bf519d47250322dBen Murdoch            equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
107621939df44de1705786c545cd1bf519d47250322dBen Murdoch            return;
1077643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
1078d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (renderer->isBox()) {
1079d0825bca7fe65beaee391d30da42e937db621564Steve Block            inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
1080d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
1081d0825bca7fe65beaee391d30da42e937db621564Steve Block                return;
1082d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1084635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        RenderText* textRenderer = toRenderText(renderer);
10858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineTextBox* box;
10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineTextBox* candidate = 0;
10888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMinOffset = box->caretMinOffset();
10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int caretMaxOffset = box->caretMaxOffset();
10928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
10948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
10958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
10978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = box;
10988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
10998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
1102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM)))
11038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
11048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            candidate = box;
11068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11078a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        if (candidate && candidate == textRenderer->lastTextBox() && affinity == DOWNSTREAM) {
1108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            box = searchAheadForBetterMatch(textRenderer);
1109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (box)
1110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                caretOffset = box->caretMinOffset();
1111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
11128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        inlineBox = box ? box : candidate;
11138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!inlineBox)
11168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
11178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned char level = inlineBox->bidiLevel();
11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (inlineBox->direction() == primaryDirection) {
11218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (caretOffset == inlineBox->caretRightmostOffset()) {
11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* nextBox = inlineBox->nextLeafChild();
11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!nextBox || nextBox->bidiLevel() >= level)
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            level = nextBox->bidiLevel();
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* prevBox = inlineBox;
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            do {
11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                prevBox = prevBox->prevLeafChild();
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } while (prevBox && prevBox->bidiLevel() > level);
11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // For example, abc 123 ^ CBA
11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (nextBox->bidiLevel() < level)
11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = nextBox;
11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretRightmostOffset();
11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* prevBox = inlineBox->prevLeafChild();
11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!prevBox || prevBox->bidiLevel() >= level)
11458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
11468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            level = prevBox->bidiLevel();
11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineBox* nextBox = inlineBox;
11498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            do {
11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                nextBox = nextBox->nextLeafChild();
11518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } while (nextBox && nextBox->bidiLevel() > level);
11528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (nextBox && nextBox->bidiLevel() == level)
11548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
11558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (prevBox->bidiLevel() < level)
11588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
11598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = prevBox;
11608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretLeftmostOffset();
11628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
11648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (caretOffset == inlineBox->caretLeftmostOffset()) {
11678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineBox* prevBox = inlineBox->prevLeafChild();
11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!prevBox || prevBox->bidiLevel() < level) {
11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Left edge of a secondary run. Set to the right edge of the entire run.
11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (nextBox->bidiLevel() < level)
11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = nextBox;
11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretRightmostOffset();
11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (prevBox->bidiLevel() > level) {
11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Right edge of a "tertiary" run. Set to the left edge of that run.
11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* tertiaryBox = inlineBox->prevLeafChild()) {
11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (tertiaryBox->bidiLevel() <= level)
11808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = tertiaryBox;
11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretLeftmostOffset();
11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineBox* nextBox = inlineBox->nextLeafChild();
11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!nextBox || nextBox->bidiLevel() < level) {
11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Right edge of a secondary run. Set to the left edge of the entire run.
11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (prevBox->bidiLevel() < level)
11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = prevBox;
11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretLeftmostOffset();
11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (nextBox->bidiLevel() > level) {
11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Left edge of a "tertiary" run. Set to the right edge of that run.
11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (InlineBox* tertiaryBox = inlineBox->nextLeafChild()) {
11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (tertiaryBox->bidiLevel() <= level)
11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                inlineBox = tertiaryBox;
12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            caretOffset = inlineBox->caretRightmostOffset();
12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
12048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1207dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockTextDirection Position::primaryDirection() const
1208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    TextDirection primaryDirection = LTR;
1210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) {
1211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (r->isBlockFlow()) {
1212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            primaryDirection = r->style()->direction();
1213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            break;
1214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return primaryDirection;
1218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
12218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Position::debugPosition(const char* msg) const
12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
12248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fprintf(stderr, "Position [%s]: null\n", msg);
12258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
122681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, deprecatedNode()->nodeName().utf8().data(), deprecatedNode(), m_offset);
12278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Position::formatForDebugger(char* buffer, unsigned length) const
12328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String result;
12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isNull())
12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = "<null>";
12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        char s[1024];
12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result += "offset ";
12408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result += String::number(m_offset);
12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result += " of ";
124281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        deprecatedNode()->formatForDebugger(s, sizeof(s));
12438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result += s;
12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    strncpy(buffer, result.utf8().data(), length - 1);
12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
124981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid Position::showAnchorTypeAndOffset() const
125081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
125181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (m_isLegacyEditingPosition)
125281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        fputs("legacy, ", stderr);
125381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    switch (anchorType()) {
125481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    case PositionIsOffsetInAnchor:
125581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        fputs("offset", stderr);
125681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        break;
125781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    case PositionIsAfterAnchor:
125881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        fputs("after", stderr);
125981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        break;
126081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    case PositionIsBeforeAnchor:
126181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        fputs("before", stderr);
126281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        break;
126381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
126481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    fprintf(stderr, ", offset:%d\n", m_offset);
126581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
126681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
12678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Position::showTreeForThis() const
12688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
126981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (anchorNode()) {
127081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        anchorNode()->showTreeForThis();
127181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        showAnchorTypeAndOffset();
1272d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
12768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
12798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
12808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
12828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid showTree(const WebCore::Position& pos)
12848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pos.showTreeForThis();
12868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid showTree(const WebCore::Position* pos)
12898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos)
12918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos->showTreeForThis();
12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1295