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