visible_units.cpp revision cad810f21b803229eb11403f9209855525a25d57
18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Element.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 32e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "Position.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderBlock.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderLayer.h" 35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderObject.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextBoundaries.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextBreakIterator.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h" 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "VisiblePosition.h" 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h" 418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <wtf/unicode/Unicode.h> 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianusing namespace WTF::Unicode; 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianenum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext }; 495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantypedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsigned offset, BoundarySearchContextAvailability, bool& needMoreContext); 515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position pos = c.deepEquivalent(); 55dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Node* boundary = pos.parentEditingBoundary(); 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!boundary) 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 59dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Document* d = boundary->document(); 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position start = rangeCompliantEquivalent(Position(boundary, 0)); 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position end = rangeCompliantEquivalent(pos); 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> searchRange = Range::create(d); 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Vector<UChar, 1024> string; 658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian unsigned suffixLength = 0; 668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ExceptionCode ec = 0; 685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (requiresContextForWordBoundary(c.characterBefore())) { 698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RefPtr<Range> forwardsScanRange(d->createRange()); 708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian forwardsScanRange->setEndAfter(boundary, ec); 715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian forwardsScanRange->setStart(end.node(), end.deprecatedEditingOffset(), ec); 728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TextIterator forwardsIterator(forwardsScanRange.get()); 738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (!forwardsIterator.atEnd()) { 748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian const UChar* characters = forwardsIterator.characters(); 758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int length = forwardsIterator.length(); 765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int i = endOfFirstWordBoundaryContext(characters, length); 778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian string.append(characters, i); 788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian suffixLength += i; 798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (i < length) 808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian forwardsIterator.advance(); 828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec); 865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian searchRange->setEnd(end.node(), end.deprecatedEditingOffset(), ec); 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!ec); 898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (ec) 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 92dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsAtEditingBoundary); 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned next = 0; 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE; 955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian bool needMoreContext = false; 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!it.atEnd()) { 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // iterate to get chunks until the searchFunction returns a non-zero value. 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!inTextSecurityMode) 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string.prepend(it.characters(), it.length()); 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Treat bullets used in the text security mode as regular characters when looking for boundaries 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String iteratorString(it.characters(), it.length()); 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project iteratorString = iteratorString.impl()->secure('x'); 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string.prepend(iteratorString.characters(), iteratorString.length()); 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian next = searchFunction(string.data(), string.size(), string.size() - suffixLength, MayHaveMoreContext, needMoreContext); 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (next != 0) 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project it.advance(); 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (needMoreContext) { 1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The last search returned the beginning of the buffer and asked for more context, 1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // but there is no earlier text. Force a search with what's available. 1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian next = searchFunction(string.data(), string.size(), string.size() - suffixLength, DontHaveMoreContext, needMoreContext); 1155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(!needMoreContext); 1165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (it.atEnd() && next == 0) { 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos = it.range()->startPosition(); 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (next != 0) { 1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Node *node = it.range()->startContainer(ec); 1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next)) 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The next variable contains a usable index into a text node 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos = Position(node, next); 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // Use the character iterator to translate the next value into a DOM position. 127dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary); 1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian charIt.advance(string.size() - suffixLength - next); 1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian pos = charIt.range()->endPosition(); 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(pos, DOWNSTREAM); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction) 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position pos = c.deepEquivalent(); 139dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Node* boundary = pos.parentEditingBoundary(); 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!boundary) 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 143dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch Document* d = boundary->document(); 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> searchRange(d->createRange()); 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position start(rangeCompliantEquivalent(pos)); 1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Vector<UChar, 1024> string; 1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian unsigned prefixLength = 0; 1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec = 0; 1515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (requiresContextForWordBoundary(c.characterAfter())) { 1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RefPtr<Range> backwardsScanRange(d->createRange()); 1535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian backwardsScanRange->setEnd(start.node(), start.deprecatedEditingOffset(), ec); 1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get()); 1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (!backwardsIterator.atEnd()) { 1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian const UChar* characters = backwardsIterator.characters(); 1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int length = backwardsIterator.length(); 1585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int i = startOfLastWordBoundaryContext(characters, length); 1595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian string.prepend(characters + i, length - i); 1605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian prefixLength += length - i; 1615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (i > 0) 1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian backwardsIterator.advance(); 1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project searchRange->selectNodeContents(boundary, ec); 1685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec); 16921939df44de1705786c545cd1bf519d47250322dBen Murdoch TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned next = 0; 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE; 1725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian bool needMoreContext = false; 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!it.atEnd()) { 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Keep asking the iterator for chunks until the search function 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // returns an end value not equal to the length of the string passed to it. 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!inTextSecurityMode) 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string.append(it.characters(), it.length()); 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Treat bullets used in the text security mode as regular characters when looking for boundaries 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String iteratorString(it.characters(), it.length()); 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project iteratorString = iteratorString.impl()->secure('x'); 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string.append(iteratorString.characters(), iteratorString.length()); 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext); 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (next != string.size()) 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project it.advance(); 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (needMoreContext) { 1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The last search returned the end of the buffer and asked for more context, 1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // but there is no further text. Force a search with what's available. 1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian next = searchFunction(string.data(), string.size(), prefixLength, DontHaveMoreContext, needMoreContext); 1935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(!needMoreContext); 1945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (it.atEnd() && next == string.size()) { 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos = it.range()->startPosition(); 1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } else if (next != prefixLength) { 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Use the character iterator to translate the next value into a DOM position. 20021939df44de1705786c545cd1bf519d47250322dBen Murdoch CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); 2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian charIt.advance(next - prefixLength - 1); 202bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen RefPtr<Range> characterRange = charIt.range(); 203bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen pos = characterRange->endPosition(); 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (*charIt.characters() == '\n') { 2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593) 2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian VisiblePosition visPos = VisiblePosition(pos); 208bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (visPos == VisiblePosition(characterRange->startPosition())) { 209bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen charIt.advance(1); 210bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen pos = charIt.range()->startPosition(); 211bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // generate VisiblePosition, use UPSTREAM affinity if possible 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic bool canHaveCursor(RenderObject* o) 220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return (o->isText() && toRenderText(o)->linesBoundingBox().height()) 222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block || (o->isBox() && toRenderBox(o)->borderBoundingBox().height()); 223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned startWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext) 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(offset); 2305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) { 2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = true; 2328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return 0; 2335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 2345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = false; 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int start, end; 2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian findWordBoundary(characters, length, offset - 1, &start, &end); 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return start; 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfWord(const VisiblePosition &c, EWordSide side) 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This returns a null VP for c at the start of the document 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // and side == LeftWordIfOnBoundary 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition p = c; 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (side == RightWordIfOnBoundary) { 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // at paragraph end, the startofWord is the current position 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isEndOfParagraph(c)) 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = c.next(); 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p.isNull()) 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return previousBoundary(p, startWordBoundary); 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned endWordBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext) 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(offset <= length); 2605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) { 2615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = true; 2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return length; 2635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 2645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = false; 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int start, end; 2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian findWordBoundary(characters, length, offset, &start, &end); 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return end; 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfWord(const VisiblePosition &c, EWordSide side) 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition p = c; 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (side == LeftWordIfOnBoundary) { 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isStartOfParagraph(c)) 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = c.previous(); 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (p.isNull()) 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (isEndOfParagraph(c)) 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return nextBoundary(p, endWordBoundary); 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned previousWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext) 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (mayHaveMoreContext && !startOfLastWordBoundaryContext(characters, offset)) { 2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = true; 2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return 0; 2915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 2925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = false; 2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return findNextWordFromIndex(characters, length, offset, false); 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousWordPosition(const VisiblePosition &c) 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prev = previousBoundary(c, previousWordPositionBoundary); 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrAfter(prev); 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned nextWordPositionBoundary(const UChar* characters, unsigned length, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext) 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (mayHaveMoreContext && endOfFirstWordBoundaryContext(characters + offset, length - offset) == static_cast<int>(length - offset)) { 3055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = true; 3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return length; 3075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 3085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian needMoreContext = false; 3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return findNextWordFromIndex(characters, length, offset, true); 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextWordPosition(const VisiblePosition &c) 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition next = nextBoundary(c, nextWordPositionBoundary); 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrBefore(next); 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic RootInlineBox *rootBoxForLine(const VisiblePosition &c) 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *node = p.node(); 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject *renderer = node->renderer(); 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer) 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox* box; 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset; 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project c.getInlineBoxAndOffset(box, offset); 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return box ? box->root() : 0; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition positionAvoidingFirstPositionInTable(const VisiblePosition& c) 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // return table offset 0 instead of the first VisiblePosition inside the table 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition previous = c.previous(); 3420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (isLastPositionBeforeTable(previous) && isEditablePosition(previous.deepEquivalent())) 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return previous; 3440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition startPositionForLine(const VisiblePosition& c) 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c.isNull()) 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RootInlineBox *rootBox = rootBoxForLine(c); 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!rootBox) { 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There are VisiblePositions at offset 0 in blocks without 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // RootInlineBoxes, like empty editable blocks and bordered blocks. 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 3585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.deprecatedEditingOffset() == 0) 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return positionAvoidingFirstPositionInTable(c); 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Generated content (e.g. list markers and CSS :before and :after 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // pseudoelements) have no corresponding DOM element, and so cannot be 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // represented by a VisiblePosition. Use whatever follows instead. 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox *startBox = rootBox->firstLeafChild(); 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *startNode; 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startBox) 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderObject *startRenderer = startBox->renderer(); 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startRenderer) 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian startNode = startRenderer->node(); 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startNode) 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startBox = startBox->nextLeafChild(); 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int startOffset = 0; 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startBox->isInlineTextBox()) { 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox); 387635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project startOffset = startTextBox->start(); 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM); 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return positionAvoidingFirstPositionInTable(visPos); 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfLine(const VisiblePosition& c) 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition visPos = startPositionForLine(c); 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrAfter(visPos); 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition endPositionForLine(const VisiblePosition& c) 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c.isNull()) 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RootInlineBox *rootBox = rootBoxForLine(c); 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!rootBox) { 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There are VisiblePositions at offset 0 in blocks without 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // RootInlineBoxes, like empty editable blocks and bordered blocks. 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 4115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.deprecatedEditingOffset() == 0) 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c; 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Generated content (e.g. list markers and CSS :before and :after 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // pseudoelements) have no corresponding DOM element, and so cannot be 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // represented by a VisiblePosition. Use whatever precedes instead. 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *endNode; 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox *endBox = rootBox->lastLeafChild(); 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!endBox) 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RenderObject *endRenderer = endBox->renderer(); 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!endRenderer) 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian endNode = endRenderer->node(); 4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (endNode) 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endBox = endBox->prevLeafChild(); 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int endOffset = 1; 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (endNode->hasTagName(brTag)) { 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endOffset = 0; 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (endBox->isInlineTextBox()) { 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox); 441635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project endOffset = endTextBox->start(); 4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!endTextBox->isLineBreak()) 443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project endOffset += endTextBox->len(); 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE); 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfLine(const VisiblePosition& c) 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition visPos = endPositionForLine(c); 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Make sure the end of line is at the same line as the given input position. Else use the previous position to 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // obtain end of line. This condition happens when the input position is before the space character at the end 4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // of a soft-wrapped non-editable line. In this scenario, endPositionForLine would incorrectly hand back a position 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // in the next line instead. This fix is to account for the discrepancy between lines with webkit-line-break:after-white-space style 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // versus lines without that style, which would break before a space by default. 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!inSameLine(c, visPos)) { 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project visPos = c.previous(); 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visPos.isNull()) 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project visPos = endPositionForLine(visPos); 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrBefore(visPos); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameLine(const VisiblePosition &a, const VisiblePosition &b) 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a.isNotNull() && startOfLine(a) == startOfLine(b); 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfLine(const VisiblePosition &p) 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return p.isNotNull() && p == startOfLine(p); 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfLine(const VisiblePosition &p) 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return p.isNotNull() && p == endOfLine(p); 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// The first leaf before node that has the same editability as node. 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* previousLeafWithSameEditability(Node* node) 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool editable = node->isContentEditable(); 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* n = node->previousLeafNode(); 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (editable == n->isContentEditable()) 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return n; 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->previousLeafNode(); 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic Node* enclosingNodeWithNonInlineRenderer(Node* n) 4975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 4985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (Node* p = n; p; p = p->parentNode()) { 4995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (p->renderer() && !p->renderer()->isInline()) 5005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return p; 5015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 5025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return 0; 5035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 5045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int x) 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = visiblePosition.deepEquivalent(); 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *node = p.node(); 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* highestRoot = highestEditableRoot(p); 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node->document()->updateLayoutIgnorePendingStylesheets(); 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject *renderer = node->renderer(); 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer) 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderBlock *containingBlock = 0; 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RootInlineBox *root = 0; 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox* box; 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int ignoredCaretOffset; 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset); 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (box) { 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project root = box->root()->prevRootBox(); 526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We want to skip zero height boxes. 527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // This could happen in case it is a TrailingFloatsRootInlineBox. 528bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (root && root->logicalHeight()) 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project containingBlock = renderer->containingBlock(); 530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block root = 0; 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!root) { 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This containing editable block does not have a previous line. 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to move back to previous containing editable block in this root editable 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // block and find the last root line box in that block. 5385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Node* startBlock = enclosingNodeWithNonInlineRenderer(node); 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* n = previousLeafWithSameEditability(node); 5405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (n && startBlock == enclosingNodeWithNonInlineRenderer(n)) 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = previousLeafWithSameEditability(n); 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (highestEditableRoot(Position(n, 0)) != highestRoot) 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position pos(n, caretMinOffset(n)); 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pos.isCandidate()) { 547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RenderObject* o = n->renderer(); 548dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(o); 549dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (canHaveCursor(o)) { 550dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Position maxPos(n, caretMaxOffset(n)); 551dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block maxPos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset); 552dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (box) { 553dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // previous root line box found 554dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block root = box->root(); 555dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block containingBlock = n->renderer()->containingBlock(); 556dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 557dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 558dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 559dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return VisiblePosition(pos, DOWNSTREAM); 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = previousLeafWithSameEditability(n); 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (root) { 567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Can be wrong for multi-column layout and with transforms. 568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint()); 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (containingBlock->hasOverflowClip()) 570635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project absPos -= containingBlock->layer()->scrolledContentOffset(); 5716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner RenderObject* renderer = root->closestLeafChildForLogicalLeftPosition(x - absPos.x(), isEditablePosition(p))->renderer(); 572635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* node = renderer->node(); 5735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (node && editingIgnoresContent(node)) 5746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return Position(node->parentNode(), node->nodeIndex()); 575231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return renderer->positionForPoint(IntPoint(x - absPos.x(), root->lineTop())); 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Could not find a previous line. This means we must already be on the first line. 5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Move to the start of the content in this block, which effectively moves us 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // to the start of the line we're on. 5815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement(); 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(rootElement, 0, DOWNSTREAM); 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* nextLeafWithSameEditability(Node* node, int offset) 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool editable = node->isContentEditable(); 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(offset >= 0); 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* child = node->childNode(offset); 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* n = child ? child->nextLeafNode() : node->nextLeafNode(); 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (editable == n->isContentEditable()) 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return n; 5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->nextLeafNode(); 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* nextLeafWithSameEditability(Node* node) 6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool editable = node->isContentEditable(); 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* n = node->nextLeafNode(); 6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (editable == n->isContentEditable()) 6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return n; 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->nextLeafNode(); 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x) 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = visiblePosition.deepEquivalent(); 6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *node = p.node(); 6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* highestRoot = highestEditableRoot(p); 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node->document()->updateLayoutIgnorePendingStylesheets(); 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject *renderer = node->renderer(); 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer) 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderBlock *containingBlock = 0; 6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RootInlineBox *root = 0; 6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox* box; 6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int ignoredCaretOffset; 6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset); 6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (box) { 6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project root = box->root()->nextRootBox(); 635dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We want to skip zero height boxes. 636dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // This could happen in case it is a TrailingFloatsRootInlineBox. 637bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (root && root->logicalHeight()) 6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project containingBlock = renderer->containingBlock(); 639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 640dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block root = 0; 6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!root) { 6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This containing editable block does not have a next line. 6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to move forward to next containing editable block in this root editable 6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // block and find the first root line box in that block. 6475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Node* startBlock = enclosingNodeWithNonInlineRenderer(node); 6485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Node* n = nextLeafWithSameEditability(node, p.deprecatedEditingOffset()); 6495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (n && startBlock == enclosingNodeWithNonInlineRenderer(n)) 6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = nextLeafWithSameEditability(n); 6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (highestEditableRoot(Position(n, 0)) != highestRoot) 6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position pos(n, caretMinOffset(n)); 6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pos.isCandidate()) { 6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(n->renderer()); 6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset); 6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (box) { 6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // next root line box found 6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project root = box->root(); 6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project containingBlock = n->renderer()->containingBlock(); 6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(pos, DOWNSTREAM); 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = nextLeafWithSameEditability(n); 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (root) { 672635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: Can be wrong for multi-column layout and with transforms. 673635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint absPos = containingBlock->localToAbsolute(FloatPoint()); 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (containingBlock->hasOverflowClip()) 675635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project absPos -= containingBlock->layer()->scrolledContentOffset(); 6766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner RenderObject* renderer = root->closestLeafChildForLogicalLeftPosition(x - absPos.x(), isEditablePosition(p))->renderer(); 677635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* node = renderer->node(); 6785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (node && editingIgnoresContent(node)) 6796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return Position(node->parentNode(), node->nodeIndex()); 680231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return renderer->positionForPoint(IntPoint(x - absPos.x(), root->lineTop())); 6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Could not find a next line. This means we must already be on the last line. 6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Move to the end of the content in this block, which effectively moves us 6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // to the end of the line we're on. 6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement(); 6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM); 6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned startSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: The following function can return -1; we don't handle that. 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return textBreakPreceding(iterator, length); 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfSentence(const VisiblePosition &c) 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return previousBoundary(c, startSentenceBoundary); 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned endSentenceBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) 7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return textBreakNext(iterator); 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: This includes the space after the punctuation that marks the end of the sentence. 7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfSentence(const VisiblePosition &c) 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return nextBoundary(c, endSentenceBoundary); 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned previousSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's not right. 7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: The following function can return -1; we don't handle that. 7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return textBreakPreceding(iterator, length); 7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition previousSentencePosition(const VisiblePosition &c) 7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prev = previousBoundary(c, previousSentencePositionBoundary); 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrAfter(prev); 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic unsigned nextSentencePositionBoundary(const UChar* characters, unsigned length, unsigned, BoundarySearchContextAvailability, bool&) 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs to 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // move to the equivlant position in the following sentence. 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project TextBreakIterator* iterator = sentenceBreakIterator(characters, length); 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return textBreakFollowing(iterator, 0); 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition nextSentencePosition(const VisiblePosition &c) 7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition next = nextBoundary(c, nextSentencePositionBoundary); 7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return c.honorEditableBoundaryAtOrBefore(next); 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangVisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule) 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *startNode = p.node(); 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startNode) 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 752643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (isRenderedAsNonInlineTableImageOrHR(startNode)) 7538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return firstDeepEditingPositionForNode(startNode); 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* startBlock = enclosingBlock(startNode); 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *node = startNode; 7585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int offset = p.deprecatedEditingOffset(); 7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *n = startNode; 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 7624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (boundaryCrossingRule == CannotCrossEditingBoundary && n->isContentEditable() != startNode->isContentEditable()) 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject *r = n->renderer(); 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) { 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traversePreviousNodePostOrder(startBlock); 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle *style = r->style(); 7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style->visibility() != VISIBLE) { 7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traversePreviousNodePostOrder(startBlock); 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->isBR() || isBlock(n)) 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 777e14391e94c850b8bd03680c23b38978db68687a8John Reck 778e14391e94c850b8bd03680c23b38978db68687a8John Reck if (r->isText() && r->caretMaxRenderedOffset() > 0) { 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style->preserveNewline()) { 780635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const UChar* chars = toRenderText(r)->characters(); 781635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int i = toRenderText(r)->textLength(); 7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int o = offset; 7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (n == startNode && o < i) 7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project i = max(0, o); 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (--i >= 0) 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (chars[i] == '\n') 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(n, i + 1, DOWNSTREAM); 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node = n; 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project offset = 0; 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traversePreviousNodePostOrder(startBlock); 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (editingIgnoresContent(n) || isTableElement(n)) { 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node = n; 7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project offset = 0; 7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->previousSibling() ? n->previousSibling() : n->traversePreviousNodePostOrder(startBlock); 7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traversePreviousNodePostOrder(startBlock); 7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(node, offset, DOWNSTREAM); 8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8034576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangVisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossingRule boundaryCrossingRule) 8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (c.isNull()) 8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* startNode = p.node(); 8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 811643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (isRenderedAsNonInlineTableImageOrHR(startNode)) 8128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return lastDeepEditingPositionForNode(startNode); 8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* startBlock = enclosingBlock(startNode); 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *stayInsideBlock = startBlock; 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *node = startNode; 8185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int offset = p.deprecatedEditingOffset(); 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *n = startNode; 8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n) { 8224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (boundaryCrossingRule == CannotCrossEditingBoundary && n->isContentEditable() != startNode->isContentEditable()) 8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject *r = n->renderer(); 8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) { 8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traverseNextNode(stayInsideBlock); 8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle *style = r->style(); 8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style->visibility() != VISIBLE) { 8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traverseNextNode(stayInsideBlock); 8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->isBR() || isBlock(n)) 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 837e14391e94c850b8bd03680c23b38978db68687a8John Reck 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: We avoid returning a position where the renderer can't accept the caret. 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->isText() && r->caretMaxRenderedOffset() > 0) { 840635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int length = toRenderText(r)->textLength(); 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style->preserveNewline()) { 842635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const UChar* chars = toRenderText(r)->characters(); 8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int o = n == startNode ? offset : 0; 8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = o; i < length; ++i) 8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (chars[i] == '\n') 8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(n, i, DOWNSTREAM); 8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node = n; 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project offset = r->caretMaxOffset(); 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traverseNextNode(stayInsideBlock); 8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (editingIgnoresContent(n) || isTableElement(n)) { 8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project node = n; 8538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian offset = lastOffsetForEditing(n); 8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traverseNextSibling(stayInsideBlock); 8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = n->traverseNextNode(stayInsideBlock); 8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(node, offset, DOWNSTREAM); 8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfNextParagraph(const VisiblePosition& visiblePosition) 8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition paragraphEnd(endOfParagraph(visiblePosition)); 8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition afterParagraphEnd(paragraphEnd.next(true)); 8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The position after the last position in the last cell of a table 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is not the start of the next paragraph. 8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isFirstPositionAfterTable(afterParagraphEnd)) 8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return afterParagraphEnd.next(true); 8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return afterParagraphEnd; 8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameParagraph(const VisiblePosition &a, const VisiblePosition &b) 8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a.isNotNull() && startOfParagraph(a) == startOfParagraph(b); 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool isStartOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule) 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 880e14391e94c850b8bd03680c23b38978db68687a8John Reck return pos.isNotNull() && pos == startOfParagraph(pos, boundaryCrossingRule); 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool isEndOfParagraph(const VisiblePosition &pos, EditingBoundaryCrossingRule boundaryCrossingRule) 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 885e14391e94c850b8bd03680c23b38978db68687a8John Reck return pos.isNotNull() && pos == endOfParagraph(pos, boundaryCrossingRule); 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisiblePosition previousParagraphPosition(const VisiblePosition& p, int x) 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition pos = p; 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project do { 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition n = previousLinePosition(pos, x); 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (n.isNull() || n == pos) 8948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos = n; 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } while (inSameParagraph(p, pos)); 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return pos; 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisiblePosition nextParagraphPosition(const VisiblePosition& p, int x) 9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition pos = p; 9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project do { 9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition n = nextLinePosition(pos, x); 9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (n.isNull() || n == pos) 9068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian break; 9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pos = n; 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } while (inSameParagraph(p, pos)); 9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return pos; 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfBlock(const VisiblePosition &c) 9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *startNode = p.node(); 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startNode) 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(Position(startNode->enclosingBlockFlowElement(), 0), DOWNSTREAM); 9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfBlock(const VisiblePosition &c) 9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p = c.deepEquivalent(); 9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *startNode = p.node(); 9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startNode) 9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *startBlock = startNode->enclosingBlockFlowElement(); 9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(startBlock, startBlock->childNodeCount(), VP_DEFAULT_AFFINITY); 9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameBlock(const VisiblePosition &a, const VisiblePosition &b) 9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return !a.isNull() && enclosingBlockFlowElement(a) == enclosingBlockFlowElement(b); 9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfBlock(const VisiblePosition &pos) 9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return pos.isNotNull() && pos == startOfBlock(pos); 9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfBlock(const VisiblePosition &pos) 9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return pos.isNotNull() && pos == endOfBlock(pos); 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfDocument(const Node* node) 9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(node->document()->documentElement(), 0, DOWNSTREAM); 9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfDocument(const VisiblePosition &c) 9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startOfDocument(c.deepEquivalent().node()); 9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfDocument(const Node* node) 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 968dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!node || !node->document() || !node->document()->documentElement()) 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Element* doc = node->document()->documentElement(); 9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(doc, doc->childNodeCount(), DOWNSTREAM); 9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfDocument(const VisiblePosition &c) 9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return endOfDocument(c.deepEquivalent().node()); 9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool inSameDocument(const VisiblePosition &a, const VisiblePosition &b) 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position ap = a.deepEquivalent(); 9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *an = ap.node(); 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!an) 9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position bp = b.deepEquivalent(); 9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *bn = bp.node(); 9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (an == bn) 9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return an->document() == bn->document(); 9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isStartOfDocument(const VisiblePosition &p) 9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return p.isNotNull() && p.previous().isNull(); 9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEndOfDocument(const VisiblePosition &p) 10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return p.isNotNull() && p.next().isNull(); 10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --------- 10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition) 10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent()); 10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!highestRoot) 10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return firstDeepEditingPositionForNode(highestRoot); 10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) 10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent()); 10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!highestRoot) 10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return lastDeepEditingPositionForNode(highestRoot); 10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic void getLeafBoxesInLogicalOrder(RootInlineBox* rootBox, Vector<InlineBox*>& leafBoxesInLogicalOrder) 10255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 10265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian unsigned char minLevel = 128; 10275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian unsigned char maxLevel = 0; 10285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian unsigned count = 0; 10295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox* r = rootBox->firstLeafChild(); 10305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // First find highest and lowest levels, 10315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order. 10325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (r) { 10335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (r->bidiLevel() > maxLevel) 10345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian maxLevel = r->bidiLevel(); 10355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (r->bidiLevel() < minLevel) 10365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian minLevel = r->bidiLevel(); 10375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian leafBoxesInLogicalOrder.append(r); 10385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian r = r->nextLeafChild(); 10395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ++count; 10405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 10425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (rootBox->renderer()->style()->visuallyOrdered()) 10435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 10445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Reverse of reordering of the line (L2 according to Bidi spec): 10455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // L2. From the highest level found in the text to the lowest odd level on each line, 10465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // reverse any contiguous sequence of characters that are at that level or higher. 10475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 10485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Reversing the reordering of the line is only done up to the lowest odd level. 10495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!(minLevel % 2)) 10505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian minLevel++; 10515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 10525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox** end = leafBoxesInLogicalOrder.end(); 10535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (minLevel <= maxLevel) { 10545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox** iter = leafBoxesInLogicalOrder.begin(); 10555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (iter != end) { 10565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (iter != end) { 10575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if ((*iter)->bidiLevel() >= minLevel) 10585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian break; 10595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ++iter; 10605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox** first = iter; 10625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian while (iter != end) { 10635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if ((*iter)->bidiLevel() < minLevel) 10645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian break; 10655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ++iter; 10665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox** last = iter; 10685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian std::reverse(first, last); 10695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ++minLevel; 10715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 10735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 10745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic void getLogicalStartBoxAndNode(RootInlineBox* rootBox, InlineBox*& startBox, Node*& startNode) 10755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 10765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Vector<InlineBox*> leafBoxesInLogicalOrder; 10775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian getLeafBoxesInLogicalOrder(rootBox, leafBoxesInLogicalOrder); 10785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian startBox = 0; 10795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian startNode = 0; 10805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (size_t i = 0; i < leafBoxesInLogicalOrder.size(); ++i) { 10815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian startBox = leafBoxesInLogicalOrder[i]; 10825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian startNode = startBox->renderer()->node(); 10835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (startNode) 10845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 10855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 10865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 10875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 10885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic void getLogicalEndBoxAndNode(RootInlineBox* rootBox, InlineBox*& endBox, Node*& endNode) 10895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 10905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Vector<InlineBox*> leafBoxesInLogicalOrder; 10915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian getLeafBoxesInLogicalOrder(rootBox, leafBoxesInLogicalOrder); 10925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endBox = 0; 10935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endNode = 0; 10945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Generated content (e.g. list markers and CSS :before and :after 10955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // pseudoelements) have no corresponding DOM element, and so cannot be 10965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // represented by a VisiblePosition. Use whatever precedes instead. 10975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (size_t i = leafBoxesInLogicalOrder.size(); i > 0; --i) { 10985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endBox = leafBoxesInLogicalOrder[i - 1]; 10995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endNode = endBox->renderer()->node(); 11005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (endNode) 11015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 11025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 11035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition logicalStartPositionForLine(const VisiblePosition& c) 11065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 11075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (c.isNull()) 11085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian RootInlineBox* rootBox = rootBoxForLine(c); 11115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!rootBox) { 11125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // There are VisiblePositions at offset 0 in blocks without 11135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // RootInlineBoxes, like empty editable blocks and bordered blocks. 11145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Position p = c.deepEquivalent(); 11155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset()) 11165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return positionAvoidingFirstPositionInTable(c); 11175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 11205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox* logicalStartBox; 11225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Node* logicalStartNode; 11235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian getLogicalStartBoxAndNode(rootBox, logicalStartBox, logicalStartNode); 11245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!logicalStartNode) 11265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int startOffset = logicalStartBox->caretMinOffset(); 11295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian VisiblePosition visPos = VisiblePosition(logicalStartNode, startOffset, DOWNSTREAM); 11315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return positionAvoidingFirstPositionInTable(visPos); 11325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11345f1ab04193ad0130ca8204aadaceae083aca9881Feng QianVisiblePosition logicalStartOfLine(const VisiblePosition& c) 11355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1136cad810f21b803229eb11403f9209855525a25d57Steve Block // TODO: this is the current behavior that might need to be fixed. 1137cad810f21b803229eb11403f9209855525a25d57Steve Block // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. 11385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian VisiblePosition visPos = logicalStartPositionForLine(c); 11395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return c.honorEditableBoundaryAtOrAfter(visPos); 11415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic VisiblePosition logicalEndPositionForLine(const VisiblePosition& c) 11445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 11455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (c.isNull()) 11465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian RootInlineBox* rootBox = rootBoxForLine(c); 11495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!rootBox) { 11505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // There are VisiblePositions at offset 0 in blocks without 11515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // RootInlineBoxes, like empty editable blocks and bordered blocks. 11525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Position p = c.deepEquivalent(); 11535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && !p.deprecatedEditingOffset()) 11545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return c; 11555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 11575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineBox* logicalEndBox; 11595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Node* logicalEndNode; 11605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian getLogicalEndBoxAndNode(rootBox, logicalEndBox, logicalEndNode); 11615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!logicalEndNode) 11625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(); 11635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int endOffset = 1; 11655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (logicalEndNode->hasTagName(brTag)) 11665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endOffset = 0; 11675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian else if (logicalEndBox->isInlineTextBox()) { 11685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian InlineTextBox* endTextBox = static_cast<InlineTextBox*>(logicalEndBox); 11695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endOffset = endTextBox->start(); 11705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!endTextBox->isLineBreak()) 11715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian endOffset += endTextBox->len(); 11725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 11735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return VisiblePosition(logicalEndNode, endOffset, VP_UPSTREAM_IF_POSSIBLE); 11755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b) 11785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 11795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b); 11805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11825f1ab04193ad0130ca8204aadaceae083aca9881Feng QianVisiblePosition logicalEndOfLine(const VisiblePosition& c) 11835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1184cad810f21b803229eb11403f9209855525a25d57Steve Block // TODO: this is the current behavior that might need to be fixed. 1185cad810f21b803229eb11403f9209855525a25d57Steve Block // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. 1186cad810f21b803229eb11403f9209855525a25d57Steve Block 11875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian VisiblePosition visPos = logicalEndPositionForLine(c); 11885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end 11905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line. 11915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg 11925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div> 11935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // In this case, use the previous position of the computed logical end position. 11945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!inSameLogicalLine(c, visPos)) 11955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian visPos = visPos.previous(); 11965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 11975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return c.honorEditableBoundaryAtOrBefore(visPos); 11985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 11995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1200cad810f21b803229eb11403f9209855525a25d57Steve BlockVisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction) 1201cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1202cad810f21b803229eb11403f9209855525a25d57Steve Block return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c); 1203cad810f21b803229eb11403f9209855525a25d57Steve Block} 1204cad810f21b803229eb11403f9209855525a25d57Steve Block 1205cad810f21b803229eb11403f9209855525a25d57Steve BlockVisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction) 1206cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1207cad810f21b803229eb11403f9209855525a25d57Steve Block return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c); 1208cad810f21b803229eb11403f9209855525a25d57Steve Block} 1209cad810f21b803229eb11403f9209855525a25d57Steve Block 12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1211