18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2d0825bca7fe65beaee391d30da42e937db621564Steve Block * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005 Alexey Proskuryakov. 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h" 312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "Frame.h" 325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "HTMLElement.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "InlineTextBox.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Range.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderTableCell.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderTableRow.h" 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderTextControl.h" 40dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderTextFragment.h" 41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "TextBoundaries.h" 42f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "TextBreakIterator.h" 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "VisiblePosition.h" 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h" 452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h> 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "TextBreakIteratorInternalICU.h" 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <unicode/usearch.h> 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF::Unicode; 53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectusing namespace std; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Buffer that knows how to compare with a search target. 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Keeps enough of the previous text to be able to search in the future, but no more. 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// Non-breaking spaces are always equal to normal spaces. 62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Case folding is also done if the CaseInsensitive option is specified. 63f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Matches are further filtered if the AtWordStarts option is specified, although some 64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// matches inside a word are permitted if TreatMedialCapitalAsWordStart is specified as well. 65ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochclass SearchBuffer { 66ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch WTF_MAKE_NONCOPYABLE(SearchBuffer); 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic: 68f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch SearchBuffer(const String& target, FindOptions); 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ~SearchBuffer(); 70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Returns number of characters appended; guaranteed to be in the range [1, length]. 72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t append(const UChar*, size_t length); 73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool needsMoreContext() const; 74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch void prependContext(const UChar*, size_t length); 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project void reachedBreak(); 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Result is the size in characters of what was found. 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // And <startOffset> is the number of characters back to the start of what was found. 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t search(size_t& startOffset); 80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool atBreak() const; 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectprivate: 85d0825bca7fe65beaee391d30da42e937db621564Steve Block bool isBadMatch(const UChar*, size_t length) const; 86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool isWordStartMatch(size_t start, size_t length) const; 87d0825bca7fe65beaee391d30da42e937db621564Steve Block 88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project String m_target; 89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FindOptions m_options; 90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 91635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<UChar> m_buffer; 92635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t m_overlap; 93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t m_prefixLength; 94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool m_atBreak; 95f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool m_needsMoreContext; 96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 97d0825bca7fe65beaee391d30da42e937db621564Steve Block bool m_targetRequiresKanaWorkaround; 98d0825bca7fe65beaee391d30da42e937db621564Steve Block Vector<UChar> m_normalizedTarget; 99d0825bca7fe65beaee391d30da42e937db621564Steve Block mutable Vector<UChar> m_normalizedMatch; 100d0825bca7fe65beaee391d30da42e937db621564Steve Block 101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate: 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void append(UChar, bool isCharacterStart); 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t length() const; 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String m_target; 108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FindOptions m_options; 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<UChar> m_buffer; 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<bool> m_isCharacterStartBuffer; 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool m_isBufferFull; 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t m_cursor; 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned bitsInWord = sizeof(unsigned) * 8; 1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned bitInWordMask = bitsInWord - 1; 1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochBitStack::BitStack() 1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_size(0) 1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 128a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochBitStack::~BitStack() 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid BitStack::push(bool bit) 1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned index = m_size / bitsInWord; 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned shift = m_size & bitInWordMask; 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!shift && index == m_words.size()) { 1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_words.grow(index + 1); 1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_words[index] = 0; 1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned& word = m_words[index]; 1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned mask = 1U << shift; 1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (bit) 1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch word |= mask; 1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else 1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch word &= ~mask; 1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ++m_size; 1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid BitStack::pop() 1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_size) 1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch --m_size; 1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool BitStack::top() const 1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!m_size) 1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned shift = (m_size - 1) & bitInWordMask; 1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return m_words.last() & (1U << shift); 1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochunsigned BitStack::size() const 1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return m_size; 1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// -------- 1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 170d0825bca7fe65beaee391d30da42e937db621564Steve Block#if !ASSERT_DISABLED 1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic unsigned depthCrossingShadowBoundaries(Node* node) 1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned depth = 0; 175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* parent = node->parentOrHostNode(); parent; parent = parent->parentOrHostNode()) 1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ++depth; 1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return depth; 1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// This function is like Range::pastLastNode, except for the fact that it can climb up out of shadow trees. 1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic Node* nextInPreOrderCrossingShadowBoundaries(Node* rangeEndContainer, int rangeEndOffset) 1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!rangeEndContainer) 1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (rangeEndOffset >= 0 && !rangeEndContainer->offsetInCharacters()) { 1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* next = rangeEndContainer->childNode(rangeEndOffset)) 1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return next; 1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* node = rangeEndContainer; node; node = node->parentOrHostNode()) { 1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* next = node->nextSibling()) 1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return next; 1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// -------- 1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool fullyClipsContents(Node* node) 2010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = node->renderer(); 2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!renderer || !renderer->isBox() || !renderer->hasOverflowClip()) 2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return toRenderBox(renderer)->size().isEmpty(); 2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool ignoresContainerClip(Node* node) 2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = node->renderer(); 2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!renderer || renderer->isText()) 2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch EPosition position = renderer->style()->position(); 2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return position == AbsolutePosition || position == FixedPosition; 2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void pushFullyClippedState(BitStack& stack, Node* node) 2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(stack.size() == depthCrossingShadowBoundaries(node)); 2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Push true if this node full clips its contents, or if a parent already has fully 2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // clipped and this is not a node that ignores its container's clip. 223643ca7872b450ea4efacab6188849e5aac2ba161Steve Block stack.push(fullyClipsContents(node) || (stack.top() && !ignoresContainerClip(node))); 2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void setUpFullyClippedStack(BitStack& stack, Node* node) 2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Put the nodes in a vector so we can iterate in reverse order. 2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Vector<Node*, 100> ancestry; 230f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* parent = node->parentOrHostNode(); parent; parent = parent->parentOrHostNode()) 2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ancestry.append(parent); 2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Call pushFullyClippedState on each node starting with the earliest ancestor. 2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t size = ancestry.size(); 2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (size_t i = 0; i < size; ++i) 2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(stack, ancestry[size - i - 1]); 2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(stack, node); 2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node)); 2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 242773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 243773979f92560dd1aead375c82fd75b584a141e5dJohn Reckstatic bool checkFormControlElement(Node* startNode) 244773979f92560dd1aead375c82fd75b584a141e5dJohn Reck{ 245773979f92560dd1aead375c82fd75b584a141e5dJohn Reck Node* node = startNode; 246773979f92560dd1aead375c82fd75b584a141e5dJohn Reck while (node) { 247773979f92560dd1aead375c82fd75b584a141e5dJohn Reck if (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()) 248773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return true; 249773979f92560dd1aead375c82fd75b584a141e5dJohn Reck node = node->parentNode(); 250773979f92560dd1aead375c82fd75b584a141e5dJohn Reck } 251773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return false; 252773979f92560dd1aead375c82fd75b584a141e5dJohn Reck} 253773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 254773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 255773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// -------- 2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectTextIterator::TextIterator() 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_startContainer(0) 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_startOffset(0) 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_endContainer(0) 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_endOffset(0) 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_positionNode(0) 2645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian , m_textCharacters(0) 2655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian , m_textLength(0) 266dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_remainingTextBox(0) 267dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_firstLetterText(0) 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_lastCharacter(0) 26921939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_emitsCharactersBetweenAllVisiblePositions(false) 27021939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_entersTextControls(false) 271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_emitsTextWithoutTranscoding(false) 272dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_handledFirstLetter(false) 27368513a70bcd92384395513322f1b801e7bf9c729Steve Block , m_ignoresStyleVisibility(false) 2742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch , m_emitsObjectReplacementCharacters(false) 275773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 276773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_stopsOnFormControls(false) 277773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_shouldStop(false) 278773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockTextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) 283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block : m_startContainer(0) 284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_startOffset(0) 285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_endContainer(0) 286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_endOffset(0) 287dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_positionNode(0) 288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_textCharacters(0) 289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_textLength(0) 290dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_remainingTextBox(0) 291dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_firstLetterText(0) 29221939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_emitsCharactersBetweenAllVisiblePositions(behavior & TextIteratorEmitsCharactersBetweenAllVisiblePositions) 29321939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_entersTextControls(behavior & TextIteratorEntersTextControls) 29421939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding) 295dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_handledFirstLetter(false) 29668513a70bcd92384395513322f1b801e7bf9c729Steve Block , m_ignoresStyleVisibility(behavior & TextIteratorIgnoresStyleVisibility) 2972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch , m_emitsObjectReplacementCharacters(behavior & TextIteratorEmitsObjectReplacementCharacters) 298773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 299773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls) 300773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_shouldStop(false) 301773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // get and validate the range endpoints 307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* startContainer = r->startContainer(); 308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!startContainer) 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int startOffset = r->startOffset(); 311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* endContainer = r->endContainer(); 312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int endOffset = r->endOffset(); 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Callers should be handing us well-formed ranges. If we discover that this isn't 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the case, we could consider changing this assertion to an early return. 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(r->boundaryPointsValid()); 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember range - this does not change 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startContainer = startContainer; 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startOffset = startOffset; 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endContainer = endContainer; 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endOffset = endOffset; 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // set up the current node for processing 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = r->firstNode(); 3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!m_node) 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch setUpFullyClippedStack(m_fullyClippedStack, m_node); 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = m_node == m_startContainer ? m_startOffset : 0; 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // calculate first out of bounds node 3340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_pastEndNode = nextInPreOrderCrossingShadowBoundaries(endContainer, endOffset); 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // initialize node processing state 33721939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = false; 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = 0; 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // initialize record of previous node processing 34121939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = false; 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = 0; 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = 0; 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // need this just because of the assert in advance() 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node; 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // identify the first run 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(); 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 355a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochTextIterator::~TextIterator() 356a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 357a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 358a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 359773979f92560dd1aead375c82fd75b584a141e5dJohn Reckbool TextIterator::atEnd() const 360773979f92560dd1aead375c82fd75b584a141e5dJohn Reck{ 361773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 362773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return !m_positionNode || m_shouldStop; 363773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#else 364773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return !m_positionNode; 365773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 366773979f92560dd1aead375c82fd75b584a141e5dJohn Reck} 367773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::advance() 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 370773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 371773979f92560dd1aead375c82fd75b584a141e5dJohn Reck if (m_shouldStop) 372773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return; 373773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // reset the run information 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = 0; 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle remembered node that needed a newline after the text node's newline 37921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_needsAnotherNewline) { 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit the extra newline, and position it *inside* m_node, after m_node's 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // contents, in case it's a block, in the same way that we position the first 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // newline. The range for the emitted newline should start where the line 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // break begins. 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: It would be cleaner if we emitted two newlines during the last 38521939df44de1705786c545cd1bf519d47250322dBen Murdoch // iteration, instead of using m_needsAnotherNewline. 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 38821939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = false; 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 392dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_textBox && m_remainingTextBox) { 393dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = m_remainingTextBox; 394dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = 0; 395dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 396dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_offset = 0; 397dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle remembered text box 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textBox) { 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project handleTextBox(); 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_node && m_node != m_pastEndNode) { 406773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 407773979f92560dd1aead375c82fd75b584a141e5dJohn Reck if (!m_shouldStop && m_stopsOnFormControls && checkFormControlElement(m_node)) 408773979f92560dd1aead375c82fd75b584a141e5dJohn Reck m_shouldStop = true; 409773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // if the range ends at offset 0 of an element, represent the 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // position, but not the content, of that element e.g. if the 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // node is a blockflow element, emit a newline that 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // precedes the element 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_node == m_endContainer && m_endOffset == 0) { 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project representNodeOffsetZero(); 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = 0; 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = m_node->renderer(); 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer) { 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle current node according to its type 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_handledNode) { 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) // FIXME: What about CDATA_SECTION_NODE? 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleTextNode(); 4298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else if (renderer && (renderer->isImage() || renderer->isWidget() || 4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (renderer->node() && renderer->node()->isElementNode() && 4318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian static_cast<Element*>(renderer->node())->isFormControlElement()))) 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleReplacedElement(); 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleNonTextNode(); 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // find a new current node to handle in depth-first manner, 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // calling exitNode() as we come back thru a parent node 4420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Node* next = m_handledChildren ? 0 : m_node->firstChild(); 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = 0; 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!next) { 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project next = m_node->nextSibling(); 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!next) { 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool pastEnd = m_node->traverseNextNode() == m_pastEndNode; 448f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Node* parentNode = m_node->parentOrHostNode(); 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!next && parentNode) { 4508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if ((pastEnd && parentNode == m_endContainer) || m_endContainer->isDescendantOf(parentNode)) 4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool haveRenderer = m_node->renderer(); 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = parentNode; 4540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 455f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch parentNode = m_node->parentOrHostNode(); 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (haveRenderer) 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project next = m_node->nextSibling(); 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // set the new current node 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = next; 4710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_node) 4720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 475dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = false; 476dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // how would this ever be? 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleTextNode() 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 48668513a70bcd92384395513322f1b801e7bf9c729Steve Block if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) 4870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 4880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 489635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RenderText* renderer = toRenderText(m_node->renderer()); 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = m_node; 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle pre-formatted text 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->style()->collapseWhiteSpace()) { 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runStart = m_offset; 497dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer)) { 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart); 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 501dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment()) { 502dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 503dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_firstLetterText) { 504dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch String firstLetter = m_firstLetterText->text(); 5054576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang emitText(m_node, m_firstLetterText, m_offset, m_offset + firstLetter.length()); 506dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 507dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = 0; 508dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 509dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 510dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 51168513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 512dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int strLength = str.length(); 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runEnd = min(strLength, end); 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runStart >= runEnd) 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitText(m_node, runStart, runEnd); 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->firstTextBox() && str.length() > 0) { 525dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment()) { 526dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 527dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_firstLetterText) { 528dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextBox(); 529dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 530dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 531dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 53268513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 533dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text) 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) { 5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxes.clear(); 5410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (InlineTextBox* textBox = renderer->firstTextBox(); textBox; textBox = textBox->nextTextBox()) { 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxes.append(textBox); 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 544f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick std::sort(m_sortedTextBoxes.begin(), m_sortedTextBoxes.end(), InlineTextBox::compareByStart); 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxesPosition = 0; 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 54821939df44de1705786c545cd1bf519d47250322dBen Murdoch m_textBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox(); 549dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) 550dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project handleTextBox(); 5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::handleTextBox() 5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 557dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* renderer = m_firstLetterText ? m_firstLetterText : toRenderText(m_node->renderer()); 55868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) { 559dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = 0; 560dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 561dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 563f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned start = m_offset; 5645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : UINT_MAX; 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_textBox) { 566f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned textBoxStart = m_textBox->start(); 567f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned runStart = max(textBoxStart, start); 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check for collapsed space at the start of this run. 5702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block InlineTextBox* firstTextBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox(); 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool needSpace = m_lastTextNodeEndedWithCollapsedSpace 5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || (m_textBox == firstTextBox && textBoxStart == runStart && runStart > 0); 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (needSpace && !isCollapsibleWhitespace(m_lastCharacter) && m_lastCharacter) { 574635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1] == ' ') { 575635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned spaceRunStart = runStart - 1; 576635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ') 577635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project --spaceRunStart; 5782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block emitText(m_node, renderer, spaceRunStart, spaceRunStart + 1); 579635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else 580635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart); 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 583f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned textBoxEnd = textBoxStart + m_textBox->len(); 584f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned runEnd = min(textBoxEnd, end); 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Determine what the next text box will be, but don't advance yet 5870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch InlineTextBox* nextTextBox = 0; 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) { 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size()) 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition + 1]; 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextTextBox = m_textBox->nextTextBox(); 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runStart < runEnd) { 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle either a single newline character (which becomes a space), 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // or a run of characters that does not include a newline. 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This effectively translates newlines to spaces without copying the text. 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (str[runStart] == '\n') { 5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart + 1); 6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = runStart + 1; 6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 602f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t subrunEnd = str.find('\n', runStart); 603f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (subrunEnd == notFound || subrunEnd > runEnd) 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project subrunEnd = runEnd; 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = subrunEnd; 607dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch emitText(m_node, renderer, runStart, subrunEnd); 6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we are doing a subrun that doesn't go to the end of the text box, 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // come back again to finish handling this text box; don't advance to the next one. 612f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (static_cast<unsigned>(m_positionEndOffset) < textBoxEnd) 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Advance and return 616f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned nextRunStart = nextTextBox ? nextTextBox->start() : str.length(); 6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextRunStart > runEnd) 6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = nextTextBox; 6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) 6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++m_sortedTextBoxesPosition; 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Advance and continue 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = nextTextBox; 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++m_sortedTextBoxesPosition; 6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 629dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_textBox && m_remainingTextBox) { 630dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = m_remainingTextBox; 631dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = 0; 632dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 633dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_offset = 0; 634dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextBox(); 635dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 636dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 637dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 638dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) 639dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 640dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->firstLetter()) { 641dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderObject* r = renderer->firstLetter(); 64268513a70bcd92384395513322f1b801e7bf9c729Steve Block if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 643dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 644dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch for (RenderObject *currChild = r->firstChild(); currChild; currChild->nextSibling()) { 645dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (currChild->isText()) { 646dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* firstLetter = toRenderText(currChild); 647dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = true; 648dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = m_textBox; 649dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = firstLetter->firstTextBox(); 650dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = firstLetter; 651dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 652dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 653dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 654dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 655dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = true; 6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleReplacedElement() 6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_fullyClippedStack.top()) 6610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 6620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* renderer = m_node->renderer(); 66468513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastTextNodeEndedWithCollapsedSpace) { 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_lastTextNode->parentNode(), m_lastTextNode, 1, 1); 6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 67221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_entersTextControls && renderer->isTextControl()) { 6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (HTMLElement* innerTextElement = toRenderTextControl(renderer)->innerTextElement()) { 6740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_node = innerTextElement->shadowTreeRootNode(); 6750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 6760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_offset = 0; 6770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 6780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 68121939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (m_emitsObjectReplacementCharacters && renderer && renderer->isReplaced()) { 6842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch emitCharacter(objectReplacementCharacter, m_node->parentNode(), m_node, 0, 1); 6852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return true; 6862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 6872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 68821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_emitsCharactersBetweenAllVisiblePositions) { 6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We want replaced elements to behave like punctuation for boundary 6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // finding, and to simply take up space for the selection preservation 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // code in moveParagraphs, so we use a comma. 6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(',', m_node->parentNode(), m_node, 0, 1); 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node->parentNode(); 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = m_node; 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = 0; 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = 1; 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = 0; 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = 0; 7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 709dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochbool TextIterator::hasVisibleTextNode(RenderText* renderer) 710dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 711dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->style()->visibility() == VISIBLE) 712dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 713dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->isTextFragment()) { 714dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderTextFragment* fragment = static_cast<RenderTextFragment*>(renderer); 715dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (fragment->firstLetter() && fragment->firstLetter()->style()->visibility() == VISIBLE) 716dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 717dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 718dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 719dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 720dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitTabBeforeNode(Node* node) 7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Table cells are delimited by tabs. 7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r || !isTableCell(node)) 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Want a tab before every cell other than the first one 7300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderTableCell* rc = toRenderTableCell(r); 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderTable* t = rc->table(); 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return t && (t->cellBefore(rc) || t->cellAbove(rc)); 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineForNode(Node* node) 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // br elements are represented by a single newline. 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node->hasTagName(brTag); 7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r->isBR(); 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlinesBeforeAndAfterNode(Node* node) 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Block flow (versus inline flow) is represented by having 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // a newline both before and after the element. 7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) { 7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (node->hasTagName(blockquoteTag) 7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(ddTag) 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(divTag) 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(dlTag) 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(dtTag) 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h1Tag) 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h2Tag) 7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h3Tag) 7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h4Tag) 7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h5Tag) 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h6Tag) 7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(hrTag) 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(liTag) 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(listingTag) 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(olTag) 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(pTag) 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(preTag) 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(trTag) 7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(ulTag)); 7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to make an exception for table cells, because they are blocks, but we 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // want them tab-delimited rather than having newlines before and after. 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isTableCell(node)) 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to make an exception for table row elements, because they are neither 7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "inline" or "RenderBlock", but we want newlines for them. 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->isTableRow()) { 7800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderTable* t = toRenderTableRow(r)->table(); 7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (t && !t->isInline()) 7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return !r->isInline() && r->isRenderBlock() && !r->isFloatingOrPositioned() && !r->isBody(); 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineAfterNode(Node* node) 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: It should be better but slower to create a VisiblePosition here. 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!shouldEmitNewlinesBeforeAndAfterNode(node)) 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check if this is the very last renderer in the document. 7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If so, then we should not emit a newline. 7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while ((node = node->traverseNextSibling())) 7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->renderer()) 7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineBeforeNode(Node* node) 8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return shouldEmitNewlinesBeforeAndAfterNode(node); 8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitExtraNewlineForNode(Node* node) 8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When there is a significant collapsed bottom margin, emit an extra 8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // newline for a more realistic result. We end up getting the right 8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // result even without margin collapsing. For example: <div><p>text</p></div> 8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will work right even if both the <div> and the <p> have bottom margins. 8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 813635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!r || !r->isBox()) 8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // not to do this at all 8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->hasTagName(h1Tag) 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h2Tag) 8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h3Tag) 8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h4Tag) 8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h5Tag) 8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h6Tag) 8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(pTag)) { 8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle* style = r->style(); 8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style) { 827bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen int bottomMargin = toRenderBox(r)->collapsedMarginAfter(); 8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fontSize = style->fontDescription().computedPixelSize(); 8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (bottomMargin * 2 >= fontSize) 8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 837d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic int collapsedSpaceLength(RenderText* renderer, int textEnd) 838d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 839d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* characters = renderer->text()->characters(); 840d0825bca7fe65beaee391d30da42e937db621564Steve Block int length = renderer->text()->length(); 841d0825bca7fe65beaee391d30da42e937db621564Steve Block for (int i = textEnd; i < length; ++i) { 842d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!renderer->style()->isCollapsibleWhiteSpace(characters[i])) 843d0825bca7fe65beaee391d30da42e937db621564Steve Block return i - textEnd; 844d0825bca7fe65beaee391d30da42e937db621564Steve Block } 845d0825bca7fe65beaee391d30da42e937db621564Steve Block 846d0825bca7fe65beaee391d30da42e937db621564Steve Block return length - textEnd; 847d0825bca7fe65beaee391d30da42e937db621564Steve Block} 848d0825bca7fe65beaee391d30da42e937db621564Steve Block 849d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic int maxOffsetIncludingCollapsedSpaces(Node* node) 850d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 851d0825bca7fe65beaee391d30da42e937db621564Steve Block int offset = caretMaxOffset(node); 852d0825bca7fe65beaee391d30da42e937db621564Steve Block 853d0825bca7fe65beaee391d30da42e937db621564Steve Block if (node->renderer() && node->renderer()->isText()) 854d0825bca7fe65beaee391d30da42e937db621564Steve Block offset += collapsedSpaceLength(toRenderText(node->renderer()), offset); 855d0825bca7fe65beaee391d30da42e937db621564Steve Block 856d0825bca7fe65beaee391d30da42e937db621564Steve Block return offset; 857d0825bca7fe65beaee391d30da42e937db621564Steve Block} 858d0825bca7fe65beaee391d30da42e937db621564Steve Block 859635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// Whether or not we should emit a character as we enter m_node (if it's a container) or as we hit it (if it's atomic). 8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::shouldRepresentNodeOffsetZero() 8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 86221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isTable()) 8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Leave element positioned flush with start of a paragraph 8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // (e.g. do not insert tab before a table cell at the start of a paragraph) 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastCharacter == '\n') 8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Otherwise, show the position if we have emitted any characters 87121939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_hasEmitted) 8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We've not emitted anything yet. Generally, there is no need for any positioning then. 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The only exception is when the element is visually not in the same line as 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the start of the range (e.g. the range starts at the end of the previous paragraph). 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: Creating VisiblePositions and comparing them is relatively expensive, so we 8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make quicker checks to possibly avoid that. Another check that we could make is 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is whether the inline vs block flow changed since the previous visible element. 8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // I think we're already in a special enough case that that won't be needed, tho. 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 882635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // No character needed if this is the first node in the range. 8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_node == m_startContainer) 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 886635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If we are outside the start container's subtree, assume we need to emit. 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: m_startContainer could be an inline block 8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_node->isDescendantOf(m_startContainer)) 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we started as m_startContainer offset 0 and the current node is a descendant of 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the start container, we already had enough context to correctly decide whether to 89321939df44de1705786c545cd1bf519d47250322dBen Murdoch // emit after a preceding block. We chose not to emit (m_hasEmitted is false), 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // so don't second guess that now. 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: Is this really correct when m_node is not a leftmost descendant? Probably 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // immaterial since we likely would have already emitted something by now. 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_startOffset == 0) 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 899635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 900635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If this node is unrendered or invisible the VisiblePosition checks below won't have much meaning. 901635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Additionally, if the range we are iterating over contains huge sections of unrendered content, 902635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we would create VisiblePositions on every call to this function without this check. 903635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_node->renderer() || m_node->renderer()->style()->visibility() != VISIBLE) 904635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return false; 9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The startPos.isNotNull() check is needed because the start could be before the body, 9075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // and in that case we'll get null. We don't want to put in newlines at the start in that case. 9085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The currPos.isNotNull() check is needed because positions in non-HTML content 9095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // (like SVG) do not have visible positions, and we don't want to emit for them either. 91081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch VisiblePosition startPos = VisiblePosition(Position(m_startContainer, m_startOffset, Position::PositionIsOffsetInAnchor), DOWNSTREAM); 91181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch VisiblePosition currPos = VisiblePosition(positionBeforeNode(m_node), DOWNSTREAM); 9125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return startPos.isNotNull() && currPos.isNotNull() && !inSameLine(startPos, currPos); 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::shouldEmitSpaceBeforeAndAfterNode(Node* node) 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 91721939df44de1705786c545cd1bf519d47250322dBen Murdoch return node->renderer() && node->renderer()->isTable() && (node->renderer()->isInline() || m_emitsCharactersBetweenAllVisiblePositions); 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::representNodeOffsetZero() 9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit a character to show the positioning of m_node. 9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When we haven't been emitting any characters, shouldRepresentNodeOffsetZero() can 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // create VisiblePositions, which is expensive. So, we perform the inexpensive checks 9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // on m_node to see if it necessitates emitting a character first and will early return 9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. 9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldEmitTabBeforeNode(m_node)) { 9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); 9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (shouldEmitNewlineBeforeNode(m_node)) { 9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); 9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { 9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); 9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleNonTextNode() 9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldEmitNewlineForNode(m_node)) 9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), m_node, 0, 1); 94421939df44de1705786c545cd1bf519d47250322dBen Murdoch else if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isHR()) 9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node->parentNode(), m_node, 0, 1); 9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project representNodeOffsetZero(); 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::exitNode() 9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // prevent emitting a newline when exiting a collapsed block at beginning of the range 95521939df44de1705786c545cd1bf519d47250322dBen Murdoch // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed block... it could 9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // have been an hr (e.g.). Also, a collapsed block could have height (e.g. a table) and 9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // therefore look like a blank line. 95821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!m_hasEmitted) 9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit with a position *inside* m_node, after m_node's contents, in 9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // case it is a block, because the run should start where the 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // emitted character is positioned visually. 9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; 9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making 9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the logic in _web_attributedStringFromRange match. We'll get that for free when we switch to use 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // TextIterator in _web_attributedStringFromRange. 9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // See <rdar://problem/5428427> for an example of how this mismatch will cause problems. 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastTextNode && shouldEmitNewlineAfterNode(m_node)) { 9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // use extra newline to represent margin bottom, as needed 9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool addNewline = shouldEmitExtraNewlineForNode(m_node); 9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: We need to emit a '\n' as we leave an empty block(s) that 9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // contain a VisiblePosition when doing selection preservation. 9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastCharacter != '\n') { 9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // insert a newline with a position following this block's contents. 9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember whether to later add a newline for the current node 97921939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(!m_needsAnotherNewline); 98021939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = addNewline; 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (addNewline) 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // insert a newline with a position following this block's contents. 9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If nothing was emitted, see if we need to emit a space. 9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_positionNode && shouldEmitSpaceBeforeAndAfterNode(m_node)) 9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', baseNode->parentNode(), baseNode, 1, 1); 9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode, int textStartOffset, int textEndOffset) 9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 99321939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember information with which to construct the TextIterator::range() 9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: textNode is often not a text node, so the range will specify child nodes of positionNode 9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = textNode; 9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = offsetBaseNode; 9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = textStartOffset; 10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = textEndOffset; 10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember information with which to construct the TextIterator::characters() and length() 10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_singleCharacterBuffer = c; 10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = &m_singleCharacterBuffer; 10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 1; 10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember some iteration state 10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = c; 10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1012dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::emitText(Node* textNode, RenderObject* renderObject, int textStartOffset, int textEndOffset) 10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1014dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* renderer = toRenderText(renderObject); 101521939df44de1705786c545cd1bf519d47250322dBen Murdoch m_text = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text(); 101621939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(m_text.characters()); 10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = textNode; 10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = 0; 10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = textStartOffset; 10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = textEndOffset; 102221939df44de1705786c545cd1bf519d47250322dBen Murdoch m_textCharacters = m_text.characters() + textStartOffset; 10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = textEndOffset - textStartOffset; 102421939df44de1705786c545cd1bf519d47250322dBen Murdoch m_lastCharacter = m_text[textEndOffset - 1]; 10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 102721939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1030dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset) 1031dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 1032dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch emitText(textNode, m_node->renderer(), textStartOffset, textEndOffset); 1033dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1034dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> TextIterator::range() const 10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // use the current run information, if we have it 10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionOffsetBaseNode) { 10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int index = m_positionOffsetBaseNode->nodeIndex(); 10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset += index; 10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset += index; 10438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = 0; 10448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset); 10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // otherwise, return the end of the overall range we were given 10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_endContainer) 10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_endContainer->document(), m_endContainer, m_endOffset, m_endContainer, m_endOffset); 10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* TextIterator::node() const 10568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> textRange = range(); 10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!textRange) 10598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* node = textRange->startContainer(); 10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 10638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->offsetInCharacters()) 10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node; 10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node->childNode(textRange->startOffset()); 10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() 1073dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch : m_behavior(TextIteratorDefaultBehavior) 1074dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_node(0) 1075dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_positionNode(0) 1076773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 1077773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_stopsOnFormControls(false) 1078773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_shouldStop(false) 1079773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1083dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochSimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior) 1084dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch : m_behavior(behavior) 1085dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_node(0) 1086dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_positionNode(0) 1087773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 1088773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls) 1089773979f92560dd1aead375c82fd75b584a141e5dJohn Reck , m_shouldStop(false) 1090773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1092773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 1093773979f92560dd1aead375c82fd75b584a141e5dJohn Reck ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorStopsOnFormControls); 1094773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#else 109581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(m_behavior == TextIteratorDefaultBehavior); 1096773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 1097dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 10988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 10998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* startNode = r->startContainer(); 1102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!startNode) 11038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* endNode = r->endContainer(); 1105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int startOffset = r->startOffset(); 1106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int endOffset = r->endOffset(); 11078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startNode->offsetInCharacters()) { 11098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startOffset >= 0 && startOffset < static_cast<int>(startNode->childNodeCount())) { 11108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startNode = startNode->childNode(startOffset); 11118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startOffset = 0; 11128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!endNode->offsetInCharacters()) { 11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (endOffset > 0 && endOffset <= static_cast<int>(endNode->childNodeCount())) { 11168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endNode = endNode->childNode(endOffset - 1); 1117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block endOffset = lastOffsetInNode(endNode); 11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 112181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_node = endNode; 11220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch setUpFullyClippedStack(m_fullyClippedStack, m_node); 11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = endOffset; 11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = endOffset == 0; 11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startNode = startNode; 11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startOffset = startOffset; 11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endNode = endNode; 11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endOffset = endOffset; 11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG 11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need this just because of the assert. 11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = endNode; 11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = 0; 11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = '\n'; 11390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 114081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_havePassedStartNode = false; 11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(); 11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1145773979f92560dd1aead375c82fd75b584a141e5dJohn Reckbool SimplifiedBackwardsTextIterator::atEnd() const 1146773979f92560dd1aead375c82fd75b584a141e5dJohn Reck{ 1147773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 1148773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return !m_positionNode || m_shouldStop; 1149773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#else 1150773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return !m_positionNode; 1151773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 1152773979f92560dd1aead375c82fd75b584a141e5dJohn Reck} 1153773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 11548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimplifiedBackwardsTextIterator::advance() 11558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_positionNode); 11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1158773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#if OS(ANDROID) 1159773979f92560dd1aead375c82fd75b584a141e5dJohn Reck if (m_shouldStop) 1160773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return; 1161773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 1162773979f92560dd1aead375c82fd75b584a141e5dJohn Reck // Prevent changing the iterator position if a form control element was found and advance should stop on it. 1163773979f92560dd1aead375c82fd75b584a141e5dJohn Reck if (m_stopsOnFormControls && checkFormControlElement(m_node)) { 1164773979f92560dd1aead375c82fd75b584a141e5dJohn Reck m_shouldStop = true; 1165773979f92560dd1aead375c82fd75b584a141e5dJohn Reck return; 1166773979f92560dd1aead375c82fd75b584a141e5dJohn Reck } 1167773979f92560dd1aead375c82fd75b584a141e5dJohn Reck#endif 1168773979f92560dd1aead375c82fd75b584a141e5dJohn Reck 11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = 0; 11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 117281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while (m_node && !m_havePassedStartNode) { 11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Don't handle node if we start iterating at [node, 0]. 11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_handledNode && !(m_node == m_endNode && m_endOffset == 0)) { 11750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = m_node->renderer(); 11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer && renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) { 11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: What about CDATA_SECTION_NODE? 11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->style()->visibility() == VISIBLE && m_offset > 0) 11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleTextNode(); 11808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (renderer && (renderer->isImage() || renderer->isWidget())) { 11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->style()->visibility() == VISIBLE && m_offset > 0) 11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleReplacedElement(); 11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleNonTextNode(); 11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 118981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!m_handledChildren && m_node->hasChildNodes()) { 119081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_node = m_node->lastChild(); 119181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 119281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } else { 11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Exit empty containers as we pass over them or containers 11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // where [container, 0] is where we started iterating. 1195ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch if (!m_handledNode 1196ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && canHaveChildrenForEditing(m_node) 1197ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && m_node->parentNode() 1198ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && (!m_node->lastChild() || (m_node == m_endNode && !m_endOffset))) { 11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 120481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } 12058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 120681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 12078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Exit all other containers. 1208dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch while (!m_node->previousSibling()) { 120981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!advanceRespectingRange(m_node->parentOrHostNode())) 12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 12110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 12128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 12138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 12148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 12158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 12168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1219dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 12200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 122181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (advanceRespectingRange(m_node->previousSibling())) 122281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 122381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch else 122481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_node = 0; 12258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1226dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 1227d0825bca7fe65beaee391d30da42e937db621564Steve Block // For the purpose of word boundary detection, 1228d0825bca7fe65beaee391d30da42e937db621564Steve Block // we should iterate all visible text and trailing (collapsed) whitespaces. 1229d0825bca7fe65beaee391d30da42e937db621564Steve Block m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0; 12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 12328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleTextNode() 12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = m_node; 12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderText* renderer = toRenderText(m_node->renderer()); 12438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->firstTextBox() && str.length() > 0) 12468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = m_offset; 12498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = (m_node == m_startNode) ? m_startOffset : 0; 12518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node; 12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = m_offset; 12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = m_positionEndOffset - m_positionStartOffset; 12548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = str.characters() + m_positionStartOffset; 12558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = str[m_positionEndOffset - 1]; 12578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleReplacedElement() 12628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned index = m_node->nodeIndex(); 12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We want replaced elements to behave like punctuation for boundary 12658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // finding, and to simply take up space for the selection preservation 12668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // code in moveParagraphs, so we use a comma. Unconditionally emit 12678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // here because this iterator is only used for boundary finding. 12688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(',', m_node->parentNode(), index, index + 1); 12698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleNonTextNode() 12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We can use a linefeed in place of a tab because this simple iterator is only used to 12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. 12760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineAfterNode(m_node) || shouldEmitTabBeforeNode(m_node)) { 12778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned index = m_node->nodeIndex(); 12780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The start of this emitted range is wrong. Ensuring correctness would require 12790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // VisiblePositions and so would be slow. previousBoundary expects this. 12808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); 12818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimplifiedBackwardsTextIterator::exitNode() 12868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineBeforeNode(m_node) || shouldEmitTabBeforeNode(m_node)) { 12880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The start of this emitted range is wrong. Ensuring correctness would require 12890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // VisiblePositions and so would be slow. previousBoundary expects this. 12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node, 0, 0); 12910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int startOffset, int endOffset) 12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_singleCharacterBuffer = c; 12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = node; 12988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = startOffset; 12998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = endOffset; 13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = &m_singleCharacterBuffer; 13018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 1; 13028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = c; 13038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 130581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool SimplifiedBackwardsTextIterator::advanceRespectingRange(Node* next) 1306dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 130781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!next) 1308dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 130981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_havePassedStartNode |= m_node == m_startNode; 131081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (m_havePassedStartNode) 1311dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 131281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_node = next; 1313dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 1314dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1315dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const 13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset); 13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset); 13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectCharacterIterator::CharacterIterator() 13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_offset(0) 13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_runOffset(0) 13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_atBreak(true) 13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 133321939df44de1705786c545cd1bf519d47250322dBen MurdochCharacterIterator::CharacterIterator(const Range* r, TextIteratorBehavior behavior) 13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_offset(0) 13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_runOffset(0) 13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_atBreak(true) 133721939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_textIterator(r, behavior) 13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!atEnd() && m_textIterator.length() == 0) 13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> CharacterIterator::range() const 13448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> r = m_textIterator.range(); 13468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_textIterator.atEnd()) { 13478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.length() <= 1) { 13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_runOffset == 0); 13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 1350635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* n = r->startContainer(); 1351635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(n == r->endContainer()); 1352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int offset = r->startOffset() + m_runOffset; 1353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ExceptionCode ec = 0; 1354635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->setStart(n, offset, ec); 1355635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->setEnd(n, offset + 1, ec); 1356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 13578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r.release(); 13608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid CharacterIterator::advance(int count) 13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count <= 0) { 13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(count == 0); 13668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = false; 13708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // easy if there is enough left in the current m_textIterator run 13728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int remaining = m_textIterator.length() - m_runOffset; 13738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count < remaining) { 13748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset += count; 13758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += count; 13768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // exhaust the current m_textIterator run 13808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project count -= remaining; 13818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += remaining; 13828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // move to a subsequent m_textIterator run 13848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) { 13858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runLength = m_textIterator.length(); 13868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runLength == 0) 13878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = true; 13888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 13898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // see whether this is m_textIterator to use 13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count < runLength) { 13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset = count; 13928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += count; 13938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // exhaust this m_textIterator run 13978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project count -= runLength; 13988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += runLength; 13998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ran to the end of the m_textIterator... no more runs left 14038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = true; 14048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset = 0; 14058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString CharacterIterator::string(int numChars) 14088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 14108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.reserveInitialCapacity(numChars); 14118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (numChars > 0 && !atEnd()) { 14128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runSize = min(numChars, length()); 14138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(characters(), runSize); 14148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project numChars -= runSize; 14158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(runSize); 14168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 14188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1420635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PassRefPtr<Range> characterSubrange(CharacterIterator& it, int offset, int length) 1421635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1422635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(offset); 1423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Range> start = it.range(); 1424635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1425635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (length > 1) 1426635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(length - 1); 1427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Range> end = it.range(); 1428635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return Range::create(start->startContainer()->document(), 1430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start->startContainer(), start->startOffset(), 1431635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project end->endContainer(), end->endOffset()); 1432635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1433635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 14348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianBackwardsCharacterIterator::BackwardsCharacterIterator() 14358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian : m_offset(0) 14368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_runOffset(0) 14378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_atBreak(true) 14388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 14408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1441dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochBackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior) 14428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian : m_offset(0) 14438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_runOffset(0) 14448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_atBreak(true) 1445dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_textIterator(range, behavior) 14468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (!atEnd() && !m_textIterator.length()) 14488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_textIterator.advance(); 14498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 14508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<Range> BackwardsCharacterIterator::range() const 14528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RefPtr<Range> r = m_textIterator.range(); 14548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!m_textIterator.atEnd()) { 14558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_textIterator.length() <= 1) 14568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(m_runOffset == 0); 14578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 14588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Node* n = r->startContainer(); 14598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(n == r->endContainer()); 14608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int offset = r->endOffset() - m_runOffset; 14618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ExceptionCode ec = 0; 14628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian r->setStart(n, offset - 1, ec); 14638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian r->setEnd(n, offset, ec); 14648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!ec); 14658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return r.release(); 14688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 14698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid BackwardsCharacterIterator::advance(int count) 14718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count <= 0) { 14738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!count); 14748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = false; 14788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int remaining = m_textIterator.length() - m_runOffset; 14808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count < remaining) { 14818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset += count; 14828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += count; 14838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian count -= remaining; 14878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += remaining; 14888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) { 14908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int runLength = m_textIterator.length(); 14918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (runLength == 0) 14928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = true; 14938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 14948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count < runLength) { 14958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset = count; 14968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += count; 14978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 15008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian count -= runLength; 15018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += runLength; 15028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 15038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 15048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 15058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = true; 15068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset = 0; 15078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 15088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 15098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWordAwareIterator::WordAwareIterator() 15120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_previousText(0) 15130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_didLookAhead(false) 15148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochWordAwareIterator::WordAwareIterator(const Range* r) 15180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_previousText(0) 15190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_didLookAhead(true) // so we consider the first chunk from the text iterator 15200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_textIterator(r) 15218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch advance(); // get in position over the first chunk of text 15238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1525a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochWordAwareIterator::~WordAwareIterator() 1526a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 1527a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 1528a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 15298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We're always in one of these modes: 15308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - The current chunk in the text iterator is our current chunk 15318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// (typically its a piece of whitespace, or text that ended with whitespace) 15328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - The previous chunk in the text iterator is our current chunk 15338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// (we looked ahead to the next chunk and found a word boundary) 15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - We built up our own chunk of text from many chunks from the text iterator 15358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// FIXME: Performance could be bad for huge spans next to each other that don't fall on word boundaries. 15378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WordAwareIterator::advance() 15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = 0; 15418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.clear(); // toss any old buffer we built up 15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If last time we did a look-ahead, start with that looked-ahead chunk now 15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_didLookAhead) { 15458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_textIterator.atEnd()); 15468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 15478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_didLookAhead = false; 15498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Go to next non-empty chunk 15518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!m_textIterator.atEnd() && m_textIterator.length() == 0) 15528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 15538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_range = m_textIterator.range(); 15548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.atEnd()) 15568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 15598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If this chunk ends in whitespace we can just use it as our chunk. 15608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSpaceOrNewline(m_textIterator.characters()[m_textIterator.length() - 1])) 15618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If this is the first chunk that failed, save it in previousText before look ahead 15648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_buffer.isEmpty()) { 15658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = m_textIterator.characters(); 15668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousLength = m_textIterator.length(); 15678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Look ahead to next chunk. If it is whitespace or a break, we can use the previous stuff 15708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 15718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.atEnd() || m_textIterator.length() == 0 || isSpaceOrNewline(m_textIterator.characters()[0])) { 15728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_didLookAhead = true; 15738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_buffer.isEmpty()) { 15778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Start gobbling chunks until we get to a suitable stopping point 15788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.append(m_previousText, m_previousLength); 15798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = 0; 15808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.append(m_textIterator.characters(), m_textIterator.length()); 15828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 1583635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.range()->endOffset(), exception); 15848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint WordAwareIterator::length() const 15888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_buffer.isEmpty()) 15908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_buffer.size(); 15918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_previousText) 15928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_previousLength; 15938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_textIterator.length(); 15948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst UChar* WordAwareIterator::characters() const 15978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_buffer.isEmpty()) 15998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_buffer.data(); 16008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_previousText) 16018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_previousText; 16028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_textIterator.characters(); 16038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 16048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 16058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 16068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1607bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline UChar foldQuoteMarkOrSoftHyphen(UChar c) 16080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 16090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch (c) { 16100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case hebrewPunctuationGershayim: 16110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case leftDoubleQuotationMark: 16120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case rightDoubleQuotationMark: 16130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '"'; 16140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case hebrewPunctuationGeresh: 16150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case leftSingleQuotationMark: 16160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case rightSingleQuotationMark: 16170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '\''; 1618bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case softHyphen: 1619bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Replace soft hyphen with an ignorable character so that their presence or absence will 1620bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // not affect string comparison. 1621bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return 0; 16220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch default: 16230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return c; 16240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 16250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 16260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1627bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline void foldQuoteMarksAndSoftHyphens(String& s) 16280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 16290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(hebrewPunctuationGeresh, '\''); 16300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(hebrewPunctuationGershayim, '"'); 16310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(leftDoubleQuotationMark, '"'); 16320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(leftSingleQuotationMark, '\''); 16330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(rightDoubleQuotationMark, '"'); 16340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(rightSingleQuotationMark, '\''); 1635bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Replace soft hyphen with an ignorable character so that their presence or absence will 1636bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // not affect string comparison. 1637bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen s.replace(softHyphen, 0); 16380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 16390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1640635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 1641635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1642bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline void foldQuoteMarksAndSoftHyphens(UChar* data, size_t length) 16430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 16440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (size_t i = 0; i < length; ++i) 1645bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen data[i] = foldQuoteMarkOrSoftHyphen(data[i]); 16460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 16470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1648635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic const size_t minimumSearchBufferSize = 8192; 1649635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1650635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1651635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool searcherInUse; 1652635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1653635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1654635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic UStringSearch* createSearcher() 1655635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1656635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Provide a non-empty pattern and non-empty text so usearch_open will not fail, 1657635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // but it doesn't matter exactly what it is, since we don't perform any searches 1658635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // without setting both the pattern and the text. 1659635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 16600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch UStringSearch* searcher = usearch_open(&newlineCharacter, 1, &newlineCharacter, 1, currentSearchLocaleID(), 0, &status); 16610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING); 1662635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return searcher; 1663635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1664635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1665635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic UStringSearch* searcher() 1666635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1667635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static UStringSearch* searcher = createSearcher(); 1668635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return searcher; 1669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1671635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void lockSearcher() 1672635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1673635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1674635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!searcherInUse); 1675635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project searcherInUse = true; 1676635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1677635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1678635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1679635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void unlockSearcher() 1680635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1681635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1682635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(searcherInUse); 1683635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project searcherInUse = false; 1684635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1685635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1686635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1687d0825bca7fe65beaee391d30da42e937db621564Steve Block// ICU's search ignores the distinction between small kana letters and ones 1688d0825bca7fe65beaee391d30da42e937db621564Steve Block// that are not small, and also characters that differ only in the voicing 1689d0825bca7fe65beaee391d30da42e937db621564Steve Block// marks when considering only primary collation strength diffrences. 1690d0825bca7fe65beaee391d30da42e937db621564Steve Block// This is not helpful for end users, since these differences make words 1691d0825bca7fe65beaee391d30da42e937db621564Steve Block// distinct, so for our purposes we need these to be considered. 1692d0825bca7fe65beaee391d30da42e937db621564Steve Block// The Unicode folks do not think the collation algorithm should be 1693d0825bca7fe65beaee391d30da42e937db621564Steve Block// changed. To work around this, we would like to tailor the ICU searcher, 1694d0825bca7fe65beaee391d30da42e937db621564Steve Block// but we can't get that to work yet. So instead, we check for cases where 1695d0825bca7fe65beaee391d30da42e937db621564Steve Block// these differences occur, and skip those matches. 1696d0825bca7fe65beaee391d30da42e937db621564Steve Block 1697d0825bca7fe65beaee391d30da42e937db621564Steve Block// We refer to the above technique as the "kana workaround". The next few 1698d0825bca7fe65beaee391d30da42e937db621564Steve Block// functions are helper functinos for the kana workaround. 1699d0825bca7fe65beaee391d30da42e937db621564Steve Block 1700d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isKanaLetter(UChar character) 1701d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1702d0825bca7fe65beaee391d30da42e937db621564Steve Block // Hiragana letters. 1703d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x3041 && character <= 0x3096) 1704d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1705d0825bca7fe65beaee391d30da42e937db621564Steve Block 1706d0825bca7fe65beaee391d30da42e937db621564Steve Block // Katakana letters. 1707d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x30A1 && character <= 0x30FA) 1708d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1709d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x31F0 && character <= 0x31FF) 1710d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1711d0825bca7fe65beaee391d30da42e937db621564Steve Block 1712d0825bca7fe65beaee391d30da42e937db621564Steve Block // Halfwidth katakana letters. 1713d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0xFF66 && character <= 0xFF9D && character != 0xFF70) 1714d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1715d0825bca7fe65beaee391d30da42e937db621564Steve Block 1716d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1717d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1718d0825bca7fe65beaee391d30da42e937db621564Steve Block 1719d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isSmallKanaLetter(UChar character) 1720d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1721d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(isKanaLetter(character)); 1722d0825bca7fe65beaee391d30da42e937db621564Steve Block 1723d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1724d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3041: // HIRAGANA LETTER SMALL A 1725d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3043: // HIRAGANA LETTER SMALL I 1726d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3045: // HIRAGANA LETTER SMALL U 1727d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3047: // HIRAGANA LETTER SMALL E 1728d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3049: // HIRAGANA LETTER SMALL O 1729d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3063: // HIRAGANA LETTER SMALL TU 1730d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3083: // HIRAGANA LETTER SMALL YA 1731d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3085: // HIRAGANA LETTER SMALL YU 1732d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3087: // HIRAGANA LETTER SMALL YO 1733d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x308E: // HIRAGANA LETTER SMALL WA 1734d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3095: // HIRAGANA LETTER SMALL KA 1735d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3096: // HIRAGANA LETTER SMALL KE 1736d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A1: // KATAKANA LETTER SMALL A 1737d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A3: // KATAKANA LETTER SMALL I 1738d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A5: // KATAKANA LETTER SMALL U 1739d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A7: // KATAKANA LETTER SMALL E 1740d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A9: // KATAKANA LETTER SMALL O 1741d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C3: // KATAKANA LETTER SMALL TU 1742d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E3: // KATAKANA LETTER SMALL YA 1743d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E5: // KATAKANA LETTER SMALL YU 1744d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E7: // KATAKANA LETTER SMALL YO 1745d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30EE: // KATAKANA LETTER SMALL WA 1746d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F5: // KATAKANA LETTER SMALL KA 1747d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F6: // KATAKANA LETTER SMALL KE 1748d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F0: // KATAKANA LETTER SMALL KU 1749d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F1: // KATAKANA LETTER SMALL SI 1750d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F2: // KATAKANA LETTER SMALL SU 1751d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F3: // KATAKANA LETTER SMALL TO 1752d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F4: // KATAKANA LETTER SMALL NU 1753d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F5: // KATAKANA LETTER SMALL HA 1754d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F6: // KATAKANA LETTER SMALL HI 1755d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F7: // KATAKANA LETTER SMALL HU 1756d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F8: // KATAKANA LETTER SMALL HE 1757d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F9: // KATAKANA LETTER SMALL HO 1758d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FA: // KATAKANA LETTER SMALL MU 1759d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FB: // KATAKANA LETTER SMALL RA 1760d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FC: // KATAKANA LETTER SMALL RI 1761d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FD: // KATAKANA LETTER SMALL RU 1762d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FE: // KATAKANA LETTER SMALL RE 1763d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FF: // KATAKANA LETTER SMALL RO 1764d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF67: // HALFWIDTH KATAKANA LETTER SMALL A 1765d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF68: // HALFWIDTH KATAKANA LETTER SMALL I 1766d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF69: // HALFWIDTH KATAKANA LETTER SMALL U 1767d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6A: // HALFWIDTH KATAKANA LETTER SMALL E 1768d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6B: // HALFWIDTH KATAKANA LETTER SMALL O 1769d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6C: // HALFWIDTH KATAKANA LETTER SMALL YA 1770d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6D: // HALFWIDTH KATAKANA LETTER SMALL YU 1771d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6E: // HALFWIDTH KATAKANA LETTER SMALL YO 1772d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6F: // HALFWIDTH KATAKANA LETTER SMALL TU 1773d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1774d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1775d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1776d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1777d0825bca7fe65beaee391d30da42e937db621564Steve Block 1778d0825bca7fe65beaee391d30da42e937db621564Steve Blockenum VoicedSoundMarkType { NoVoicedSoundMark, VoicedSoundMark, SemiVoicedSoundMark }; 1779d0825bca7fe65beaee391d30da42e937db621564Steve Block 1780d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline VoicedSoundMarkType composedVoicedSoundMark(UChar character) 1781d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1782d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(isKanaLetter(character)); 1783d0825bca7fe65beaee391d30da42e937db621564Steve Block 1784d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1785d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x304C: // HIRAGANA LETTER GA 1786d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x304E: // HIRAGANA LETTER GI 1787d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3050: // HIRAGANA LETTER GU 1788d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3052: // HIRAGANA LETTER GE 1789d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3054: // HIRAGANA LETTER GO 1790d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3056: // HIRAGANA LETTER ZA 1791d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3058: // HIRAGANA LETTER ZI 1792d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305A: // HIRAGANA LETTER ZU 1793d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305C: // HIRAGANA LETTER ZE 1794d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305E: // HIRAGANA LETTER ZO 1795d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3060: // HIRAGANA LETTER DA 1796d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3062: // HIRAGANA LETTER DI 1797d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3065: // HIRAGANA LETTER DU 1798d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3067: // HIRAGANA LETTER DE 1799d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3069: // HIRAGANA LETTER DO 1800d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3070: // HIRAGANA LETTER BA 1801d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3073: // HIRAGANA LETTER BI 1802d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3076: // HIRAGANA LETTER BU 1803d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3079: // HIRAGANA LETTER BE 1804d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307C: // HIRAGANA LETTER BO 1805d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3094: // HIRAGANA LETTER VU 1806d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30AC: // KATAKANA LETTER GA 1807d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30AE: // KATAKANA LETTER GI 1808d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B0: // KATAKANA LETTER GU 1809d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B2: // KATAKANA LETTER GE 1810d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B4: // KATAKANA LETTER GO 1811d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B6: // KATAKANA LETTER ZA 1812d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B8: // KATAKANA LETTER ZI 1813d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BA: // KATAKANA LETTER ZU 1814d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BC: // KATAKANA LETTER ZE 1815d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BE: // KATAKANA LETTER ZO 1816d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C0: // KATAKANA LETTER DA 1817d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C2: // KATAKANA LETTER DI 1818d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C5: // KATAKANA LETTER DU 1819d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C7: // KATAKANA LETTER DE 1820d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C9: // KATAKANA LETTER DO 1821d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D0: // KATAKANA LETTER BA 1822d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D3: // KATAKANA LETTER BI 1823d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D6: // KATAKANA LETTER BU 1824d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D9: // KATAKANA LETTER BE 1825d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DC: // KATAKANA LETTER BO 1826d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F4: // KATAKANA LETTER VU 1827d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F7: // KATAKANA LETTER VA 1828d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F8: // KATAKANA LETTER VI 1829d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F9: // KATAKANA LETTER VE 1830d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30FA: // KATAKANA LETTER VO 1831d0825bca7fe65beaee391d30da42e937db621564Steve Block return VoicedSoundMark; 1832d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3071: // HIRAGANA LETTER PA 1833d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3074: // HIRAGANA LETTER PI 1834d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3077: // HIRAGANA LETTER PU 1835d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307A: // HIRAGANA LETTER PE 1836d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307D: // HIRAGANA LETTER PO 1837d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D1: // KATAKANA LETTER PA 1838d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D4: // KATAKANA LETTER PI 1839d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D7: // KATAKANA LETTER PU 1840d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DA: // KATAKANA LETTER PE 1841d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DD: // KATAKANA LETTER PO 1842d0825bca7fe65beaee391d30da42e937db621564Steve Block return SemiVoicedSoundMark; 1843d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1844d0825bca7fe65beaee391d30da42e937db621564Steve Block return NoVoicedSoundMark; 1845d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1846d0825bca7fe65beaee391d30da42e937db621564Steve Block 1847d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isCombiningVoicedSoundMark(UChar character) 1848d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1849d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1850d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3099: // COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK 1851d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x309A: // COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK 1852d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1853d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1854d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1855d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1856d0825bca7fe65beaee391d30da42e937db621564Steve Block 1857d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool containsKanaLetters(const String& pattern) 1858d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1859d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* characters = pattern.characters(); 1860d0825bca7fe65beaee391d30da42e937db621564Steve Block unsigned length = pattern.length(); 1861d0825bca7fe65beaee391d30da42e937db621564Steve Block for (unsigned i = 0; i < length; ++i) { 1862d0825bca7fe65beaee391d30da42e937db621564Steve Block if (isKanaLetter(characters[i])) 1863d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1864d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1865d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1866d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1867d0825bca7fe65beaee391d30da42e937db621564Steve Block 1868d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic void normalizeCharacters(const UChar* characters, unsigned length, Vector<UChar>& buffer) 1869d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1870d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(length); 1871d0825bca7fe65beaee391d30da42e937db621564Steve Block 1872d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.resize(length); 1873d0825bca7fe65beaee391d30da42e937db621564Steve Block 1874d0825bca7fe65beaee391d30da42e937db621564Steve Block UErrorCode status = U_ZERO_ERROR; 1875d0825bca7fe65beaee391d30da42e937db621564Steve Block size_t bufferSize = unorm_normalize(characters, length, UNORM_NFC, 0, buffer.data(), length, &status); 1876d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_ZERO_ERROR || status == U_STRING_NOT_TERMINATED_WARNING || status == U_BUFFER_OVERFLOW_ERROR); 1877d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(bufferSize); 1878d0825bca7fe65beaee391d30da42e937db621564Steve Block 1879d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.resize(bufferSize); 1880d0825bca7fe65beaee391d30da42e937db621564Steve Block 1881d0825bca7fe65beaee391d30da42e937db621564Steve Block if (status == U_ZERO_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) 1882d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1883d0825bca7fe65beaee391d30da42e937db621564Steve Block 1884d0825bca7fe65beaee391d30da42e937db621564Steve Block status = U_ZERO_ERROR; 1885d0825bca7fe65beaee391d30da42e937db621564Steve Block unorm_normalize(characters, length, UNORM_NFC, 0, buffer.data(), bufferSize, &status); 1886d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); 1887d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1888d0825bca7fe65beaee391d30da42e937db621564Steve Block 1889f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic bool isNonLatin1Separator(UChar32 character) 1890f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1891f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT_ARG(character, character >= 256); 1892f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1893f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return U_GET_GC_MASK(character) & (U_GC_S_MASK | U_GC_P_MASK | U_GC_Z_MASK | U_GC_CF_MASK); 1894f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1895f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1896f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic inline bool isSeparator(UChar32 character) 1897f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1898f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch static const bool latin1SeparatorTable[256] = { 1899f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1900f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1901f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // space ! " # $ % & ' ( ) * + , - . / 1902f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // : ; < = > ? 1903f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // @ 1904f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, // [ \ ] ^ _ 1905f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ` 1906f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // { | } ~ 1907f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1908f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1909f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1910f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1911f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1912f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1913f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1914f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 1915f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch }; 1916f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1917f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (character < 256) 1918f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return latin1SeparatorTable[character]; 1919f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1920f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return isNonLatin1Separator(character); 1921f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1922f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1923f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline SearchBuffer::SearchBuffer(const String& target, FindOptions options) 1924635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project : m_target(target) 1925f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_options(options) 1926f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_prefixLength(0) 1927635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_atBreak(true) 1928f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_needsMoreContext(options & AtWordStarts) 1929d0825bca7fe65beaee391d30da42e937db621564Steve Block , m_targetRequiresKanaWorkaround(containsKanaLetters(m_target)) 1930635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1931635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!m_target.isEmpty()); 1932635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 19330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // FIXME: We'd like to tailor the searcher to fold quote marks for us instead 19340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // of doing it in a separate replacement pass here, but ICU doesn't offer a way 19350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // to add tailoring on top of the locale-specific tailoring as of this writing. 1936bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_target); 19370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t targetLength = m_target.length(); 19398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_buffer.reserveInitialCapacity(max(targetLength * 8, minimumSearchBufferSize)); 1940635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_overlap = m_buffer.capacity() / 4; 1941635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1942f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if ((m_options & AtWordStarts) && targetLength) { 1943f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 targetFirstCharacter; 1944f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_target.characters(), 0, 0, targetLength, targetFirstCharacter); 1945f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Characters in the separator category never really occur at the beginning of a word, 1946f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // so if the target begins with such a character, we just ignore the AtWordStart option. 1947f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isSeparator(targetFirstCharacter)) { 1948f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_options &= ~AtWordStarts; 1949f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_needsMoreContext = false; 1950f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 1951f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 1952f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1953635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Grab the single global searcher. 1954635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If we ever have a reason to do more than once search buffer at once, we'll have 1955635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to move to multiple searchers. 1956635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project lockSearcher(); 1957635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1958635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UStringSearch* searcher = WebCore::searcher(); 1959635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UCollator* collator = usearch_getCollator(searcher); 1960635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1961f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UCollationStrength strength = m_options & CaseInsensitive ? UCOL_PRIMARY : UCOL_TERTIARY; 1962635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (ucol_getStrength(collator) != strength) { 1963635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ucol_setStrength(collator, strength); 1964635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_reset(searcher); 1965635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 1966635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1967635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 1968635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_setPattern(searcher, m_target.characters(), targetLength, &status); 1969635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 1970d0825bca7fe65beaee391d30da42e937db621564Steve Block 1971d0825bca7fe65beaee391d30da42e937db621564Steve Block // The kana workaround requires a normalized copy of the target string. 1972d0825bca7fe65beaee391d30da42e937db621564Steve Block if (m_targetRequiresKanaWorkaround) 1973d0825bca7fe65beaee391d30da42e937db621564Steve Block normalizeCharacters(m_target.characters(), m_target.length(), m_normalizedTarget); 1974635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1975635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1976635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline SearchBuffer::~SearchBuffer() 1977635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 19782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Leave the static object pointing to a valid string. 19792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block UErrorCode status = U_ZERO_ERROR; 19802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block usearch_setPattern(WebCore::searcher(), &newlineCharacter, 1, &status); 19812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(status == U_ZERO_ERROR); 19822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1983635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unlockSearcher(); 1984635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1985635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1986635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::append(const UChar* characters, size_t length) 1987635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1988635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(length); 1989635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1990635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_atBreak) { 1991635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(0); 1992f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength = 0; 1993635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_atBreak = false; 1994635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (m_buffer.size() == m_buffer.capacity()) { 1995635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memcpy(m_buffer.data(), m_buffer.data() + m_buffer.size() - m_overlap, m_overlap * sizeof(UChar)); 1996f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min(m_prefixLength, m_buffer.size() - m_overlap); 1997635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(m_overlap); 1998635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 1999635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 20000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t oldLength = m_buffer.size(); 20010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t usableLength = min(m_buffer.capacity() - oldLength, length); 2002635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(usableLength); 2003635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.append(characters, usableLength); 2004bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_buffer.data() + oldLength, usableLength); 2005635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return usableLength; 2006635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2007635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2008f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::needsMoreContext() const 2009f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2010f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return m_needsMoreContext; 2011f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2012f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2013f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline void SearchBuffer::prependContext(const UChar* characters, size_t length) 2014f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2015f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_needsMoreContext); 2016f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_prefixLength == m_buffer.size()); 2017f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2018f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!length) 2019f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 2020f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2021f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_atBreak = false; 2022f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2023f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t wordBoundaryContextStart = length; 2024f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (wordBoundaryContextStart) { 2025f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_BACK_1(characters, 0, wordBoundaryContextStart); 2026f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBoundaryContextStart = startOfLastWordBoundaryContext(characters, wordBoundaryContextStart); 2027f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2028f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2029f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t usableLength = min(m_buffer.capacity() - m_prefixLength, length - wordBoundaryContextStart); 2030f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_buffer.prepend(characters + length - usableLength, usableLength); 2031f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength += usableLength; 2032f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2033f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (wordBoundaryContextStart || m_prefixLength == m_buffer.capacity()) 2034f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_needsMoreContext = false; 2035f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2036f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2037635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline bool SearchBuffer::atBreak() const 2038635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2039635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return m_atBreak; 2040635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2041635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2042635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::reachedBreak() 2043635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2044635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_atBreak = true; 2045635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2046635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2047d0825bca7fe65beaee391d30da42e937db621564Steve Blockinline bool SearchBuffer::isBadMatch(const UChar* match, size_t matchLength) const 2048d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 2049d0825bca7fe65beaee391d30da42e937db621564Steve Block // This function implements the kana workaround. If usearch treats 2050d0825bca7fe65beaee391d30da42e937db621564Steve Block // it as a match, but we do not want to, then it's a "bad match". 2051d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!m_targetRequiresKanaWorkaround) 2052d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 2053d0825bca7fe65beaee391d30da42e937db621564Steve Block 2054d0825bca7fe65beaee391d30da42e937db621564Steve Block // Normalize into a match buffer. We reuse a single buffer rather than 2055d0825bca7fe65beaee391d30da42e937db621564Steve Block // creating a new one each time. 2056d0825bca7fe65beaee391d30da42e937db621564Steve Block normalizeCharacters(match, matchLength, m_normalizedMatch); 2057d0825bca7fe65beaee391d30da42e937db621564Steve Block 2058d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* a = m_normalizedTarget.begin(); 2059d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* aEnd = m_normalizedTarget.end(); 2060d0825bca7fe65beaee391d30da42e937db621564Steve Block 2061d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* b = m_normalizedMatch.begin(); 2062d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* bEnd = m_normalizedMatch.end(); 2063d0825bca7fe65beaee391d30da42e937db621564Steve Block 2064d0825bca7fe65beaee391d30da42e937db621564Steve Block while (true) { 2065d0825bca7fe65beaee391d30da42e937db621564Steve Block // Skip runs of non-kana-letter characters. This is necessary so we can 2066d0825bca7fe65beaee391d30da42e937db621564Steve Block // correctly handle strings where the target and match have different-length 2067d0825bca7fe65beaee391d30da42e937db621564Steve Block // runs of characters that match, while still double checking the correctness 2068d0825bca7fe65beaee391d30da42e937db621564Steve Block // of matches of kana letters with other kana letters. 2069d0825bca7fe65beaee391d30da42e937db621564Steve Block while (a != aEnd && !isKanaLetter(*a)) 2070d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2071d0825bca7fe65beaee391d30da42e937db621564Steve Block while (b != bEnd && !isKanaLetter(*b)) 2072d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2073d0825bca7fe65beaee391d30da42e937db621564Steve Block 2074d0825bca7fe65beaee391d30da42e937db621564Steve Block // If we reached the end of either the target or the match, we should have 2075d0825bca7fe65beaee391d30da42e937db621564Steve Block // reached the end of both; both should have the same number of kana letters. 2076d0825bca7fe65beaee391d30da42e937db621564Steve Block if (a == aEnd || b == bEnd) { 2077d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(a == aEnd); 2078d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(b == bEnd); 2079d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 2080d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2081d0825bca7fe65beaee391d30da42e937db621564Steve Block 2082d0825bca7fe65beaee391d30da42e937db621564Steve Block // Check for differences in the kana letter character itself. 2083d0825bca7fe65beaee391d30da42e937db621564Steve Block if (isSmallKanaLetter(*a) != isSmallKanaLetter(*b)) 2084d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2085d0825bca7fe65beaee391d30da42e937db621564Steve Block if (composedVoicedSoundMark(*a) != composedVoicedSoundMark(*b)) 2086d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2087d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2088d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2089d0825bca7fe65beaee391d30da42e937db621564Steve Block 2090d0825bca7fe65beaee391d30da42e937db621564Steve Block // Check for differences in combining voiced sound marks found after the letter. 2091d0825bca7fe65beaee391d30da42e937db621564Steve Block while (1) { 2092d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!(a != aEnd && isCombiningVoicedSoundMark(*a))) { 2093d0825bca7fe65beaee391d30da42e937db621564Steve Block if (b != bEnd && isCombiningVoicedSoundMark(*b)) 2094d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2095d0825bca7fe65beaee391d30da42e937db621564Steve Block break; 2096d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2097d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!(b != bEnd && isCombiningVoicedSoundMark(*b))) 2098d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2099d0825bca7fe65beaee391d30da42e937db621564Steve Block if (*a != *b) 2100d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2101d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2102d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2103d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2104d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2105d0825bca7fe65beaee391d30da42e937db621564Steve Block} 2106d0825bca7fe65beaee391d30da42e937db621564Steve Block 2107f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::isWordStartMatch(size_t start, size_t length) const 2108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2109f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_options & AtWordStarts); 2110f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!start) 2112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_options & TreatMedialCapitalAsWordStart) { 2115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int size = m_buffer.size(); 2116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int offset = start; 2117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 firstCharacter; 2118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_buffer.data(), 0, offset, size, firstCharacter); 2119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 previousCharacter; 2120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_PREV(m_buffer.data(), 0, offset, previousCharacter); 2121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isSeparator(firstCharacter)) { 2123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a separator run is a word start (".org" in "webkit.org"). 2124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isSeparator(previousCharacter)) 2125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isASCIIUpper(firstCharacter)) { 2127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of an uppercase run is a word start ("Kit" in "WebKit"). 2128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIUpper(previousCharacter)) 2129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The last character of an uppercase run followed by a non-separator, non-digit 2131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // is a word start ("Request" in "XMLHTTPRequest"). 2132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch offset = start; 2133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_FWD_1(m_buffer.data(), offset, size); 2134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 nextCharacter = 0; 2135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (offset < size) 2136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_buffer.data(), 0, offset, size, nextCharacter); 2137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIUpper(nextCharacter) && !isASCIIDigit(nextCharacter) && !isSeparator(nextCharacter)) 2138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isASCIIDigit(firstCharacter)) { 2140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a digit run is a word start ("2" in "WebKit2"). 2141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIDigit(previousCharacter)) 2142f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2143f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isSeparator(previousCharacter) || isASCIIDigit(previousCharacter)) { 2144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a non-separator, non-uppercase, non-digit run is a word start, 2145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // except after an uppercase. ("org" in "webkit.org", but not "ore" in "WebCore"). 2146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2149f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t wordBreakSearchStart = start + length; 2151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch while (wordBreakSearchStart > start) 2152f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBreakSearchStart = findNextWordFromIndex(m_buffer.data(), m_buffer.size(), wordBreakSearchStart, false /* backwards */); 2153f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return wordBreakSearchStart == start; 2154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2156635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::search(size_t& start) 2157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t size = m_buffer.size(); 2159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_atBreak) { 2160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!size) 2161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 2163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (size != m_buffer.capacity()) 2164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UStringSearch* searcher = WebCore::searcher(); 2168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 2170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_setText(searcher, m_buffer.data(), size, &status); 2171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 2172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch usearch_setOffset(searcher, m_prefixLength, &status); 2174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(status == U_ZERO_ERROR); 2175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int matchStart = usearch_next(searcher, &status); 2177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 2178d0825bca7fe65beaee391d30da42e937db621564Steve Block 2179d0825bca7fe65beaee391d30da42e937db621564Steve BlocknextMatch: 2180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!(matchStart >= 0 && static_cast<size_t>(matchStart) < size)) { 2181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(matchStart == USEARCH_DONE); 2182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Matches that start in the overlap area are only tentative. 2186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The same match may appear later, matching more characters, 2187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // possibly including a combining character that's not yet in the buffer. 2188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_atBreak && static_cast<size_t>(matchStart) >= size - m_overlap) { 2189f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t overlap = m_overlap; 2190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_options & AtWordStarts) { 2191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Ensure that there is sufficient context before matchStart the next time around for 2192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // determining if it is at a word boundary. 2193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int wordBoundaryContextStart = matchStart; 2194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_BACK_1(m_buffer.data(), 0, wordBoundaryContextStart); 2195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBoundaryContextStart = startOfLastWordBoundaryContext(m_buffer.data(), wordBoundaryContextStart); 2196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch overlap = min(size - 1, max(overlap, size - wordBoundaryContextStart)); 2197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2198f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch memcpy(m_buffer.data(), m_buffer.data() + size - overlap, overlap * sizeof(UChar)); 2199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min(m_prefixLength, size - overlap); 2200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_buffer.shrink(overlap); 2201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2203635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2204d0825bca7fe65beaee391d30da42e937db621564Steve Block size_t matchedLength = usearch_getMatchedLength(searcher); 2205d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(matchStart + matchedLength <= size); 2206d0825bca7fe65beaee391d30da42e937db621564Steve Block 2207d0825bca7fe65beaee391d30da42e937db621564Steve Block // If this match is "bad", move on to the next match. 2208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isBadMatch(m_buffer.data() + matchStart, matchedLength) || ((m_options & AtWordStarts) && !isWordStartMatch(matchStart, matchedLength))) { 2209d0825bca7fe65beaee391d30da42e937db621564Steve Block matchStart = usearch_next(searcher, &status); 2210d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_ZERO_ERROR); 2211d0825bca7fe65beaee391d30da42e937db621564Steve Block goto nextMatch; 2212d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2213d0825bca7fe65beaee391d30da42e937db621564Steve Block 2214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t newSize = size - (matchStart + 1); 2215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memmove(m_buffer.data(), m_buffer.data() + matchStart + 1, newSize * sizeof(UChar)); 2216f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min<size_t>(m_prefixLength, matchStart + 1); 2217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(newSize); 2218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2219635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start = size - matchStart; 2220d0825bca7fe65beaee391d30da42e937db621564Steve Block return matchedLength; 2221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2223635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else // !ICU_UNICODE 2224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2225f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline SearchBuffer::SearchBuffer(const String& target, FindOptions options) 2226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch : m_target(options & CaseInsensitive ? target.foldCase() : target) 2227f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_options(options) 2228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_buffer(m_target.length()) 22298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_isCharacterStartBuffer(m_target.length()) 22308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_isBufferFull(false) 22318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_cursor(0) 22328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 22338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_target.isEmpty()); 22348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_target.replace(noBreakSpace, ' '); 2235bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_target); 22368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline SearchBuffer::~SearchBuffer() 22398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::reachedBreak() 2243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_cursor = 0; 2245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_isBufferFull = false; 2246635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline bool SearchBuffer::atBreak() const 2249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2250635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return !m_cursor && !m_isBufferFull; 2251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::append(UChar c, bool isStart) 2254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2255bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_buffer[m_cursor] = c == noBreakSpace ? ' ' : foldQuoteMarkOrSoftHyphen(c); 22568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isCharacterStartBuffer[m_cursor] = isStart; 22578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (++m_cursor == m_target.length()) { 22588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_cursor = 0; 22598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isBufferFull = true; 22608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 22618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2263635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::append(const UChar* characters, size_t length) 22648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2265635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(length); 2266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!(m_options & CaseInsensitive)) { 2267635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project append(characters[0], true); 2268635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 1; 22698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 22708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const int maxFoldedCharacters = 16; // sensible maximum is 3, this should be more than enough 22718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar foldedCharacters[maxFoldedCharacters]; 22728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool error; 2273635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int numFoldedCharacters = foldCase(foldedCharacters, maxFoldedCharacters, characters, 1, &error); 22748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!error); 22758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(numFoldedCharacters); 22768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(numFoldedCharacters <= maxFoldedCharacters); 22778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!error && numFoldedCharacters) { 22788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project numFoldedCharacters = min(numFoldedCharacters, maxFoldedCharacters); 22798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(foldedCharacters[0], true); 22808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 1; i < numFoldedCharacters; ++i) 22818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(foldedCharacters[i], false); 22828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 1; 22848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2286f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::needsMoreContext() const 2287f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2288f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 2289f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2290f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2291f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid SearchBuffer::prependContext(const UChar*, size_t) 2292f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2293f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT_NOT_REACHED(); 2294f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2295f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::search(size_t& start) 22978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 22988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isBufferFull) 2299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 23008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isCharacterStartBuffer[m_cursor]) 2301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t tailSpace = m_target.length() - m_cursor; 2304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (memcmp(&m_buffer[m_cursor], m_target.characters(), tailSpace * sizeof(UChar)) != 0) 2305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2306635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (memcmp(&m_buffer[0], m_target.characters() + tailSpace, m_cursor * sizeof(UChar)) != 0) 2307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start = length(); 2310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Now that we've found a match once, we don't want to find it again, because those 2312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // are the SearchBuffer semantics, allowing for a buffer where you append more than one 2313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // character at a time. To do this we take advantage of m_isCharacterStartBuffer, but if 2314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we want to get rid of that in the future we could track this with a separate boolean 2315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // or even move the characters to the start of the buffer and set m_isBufferFull to false. 2316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_isCharacterStartBuffer[m_cursor] = false; 23178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2318635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return start; 23198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 23208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the number of characters that were appended to the buffer (what we are searching in). 23228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// That's not necessarily the same length as the passed-in target string, because case folding 23238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// can make two strings match even though they're not the same length. 2324635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectsize_t SearchBuffer::length() const 23258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2326635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t bufferSize = m_target.length(); 2327635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t length = 0; 2328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t i = 0; i < bufferSize; ++i) 23298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length += m_isCharacterStartBuffer[i]; 23308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return length; 23318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 23328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif // !ICU_UNICODE 2334635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 23358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 23368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint TextIterator::rangeLength(const Range* r, bool forSelectionPreservation) 23388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 23398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int length = 0; 234021939df44de1705786c545cd1bf519d47250322dBen Murdoch for (TextIterator it(r, forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); !it.atEnd(); it.advance()) 23418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length += it.length(); 23428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return length; 23448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 23458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> TextIterator::subrange(Range* entireRange, int characterOffset, int characterCount) 23478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharacterIterator entireRangeIterator(entireRange); 2349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return characterSubrange(entireRangeIterator, characterOffset, characterCount); 23508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 23518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<Range> TextIterator::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, bool forSelectionPreservation) 23538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 23548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> resultRange = scope->document()->createRange(); 23558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int docTextPosition = 0; 23578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int rangeEnd = rangeLocation + rangeLength; 23588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool startRangeFound = false; 23598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> textRunRange; 23618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 236221939df44de1705786c545cd1bf519d47250322dBen Murdoch TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); 23638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>. 23658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLocation == 0 && rangeLength == 0 && it.atEnd()) { 23668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textRunRange = it.range(); 23678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ExceptionCode ec = 0; 2369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), 0, ec); 2370635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2371635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), 0, ec); 2372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 23738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return resultRange.release(); 23758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (; !it.atEnd(); it.advance()) { 23788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int len = it.length(); 23798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textRunRange = it.range(); 23808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool foundStart = rangeLocation >= docTextPosition && rangeLocation <= docTextPosition + len; 23828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool foundEnd = rangeEnd >= docTextPosition && rangeEnd <= docTextPosition + len; 23838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Fix textRunRange->endPosition(), but only if foundStart || foundEnd, because it is only 23858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // in those cases that textRunRange is used. 2386dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (foundEnd) { 23878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This is a workaround for the fact that the end of a run is often at the wrong 23888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // position for emitted '\n's. 2389635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (len == 1 && it.characters()[0] == '\n') { 2390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scope->document()->updateLayoutIgnorePendingStylesheets(); 2391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block it.advance(); 2392dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!it.atEnd()) { 2393dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<Range> range = it.range(); 23948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec = 0; 2395dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block textRunRange->setEnd(range->startContainer(), range->startOffset(), ec); 2396635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 2398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Position runStart = textRunRange->startPosition(); 2399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Position runEnd = VisiblePosition(runStart).next().deepEquivalent(); 2400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (runEnd.isNotNull()) { 2401dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ExceptionCode ec = 0; 24022bde8e466a4451c7319e3a072d118917957d6554Steve Block textRunRange->setEnd(runEnd.containerNode(), runEnd.computeOffsetInContainerNode(), ec); 2403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(!ec); 2404dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 24058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (foundStart) { 24108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startRangeFound = true; 24118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2412635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (textRunRange->startContainer()->isTextNode()) { 24138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = rangeLocation - docTextPosition; 2414635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), offset + textRunRange->startOffset(), exception); 24158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 24168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLocation == docTextPosition) 2417635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), textRunRange->startOffset(), exception); 24188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2419635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->endContainer(), textRunRange->endOffset(), exception); 24208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (foundEnd) { 24248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2425635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (textRunRange->startContainer()->isTextNode()) { 24268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = rangeEnd - docTextPosition; 2427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), offset + textRunRange->startOffset(), exception); 24288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 24298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeEnd == docTextPosition) 2430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), textRunRange->startOffset(), exception); 24318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2432635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset(), exception); 24338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project docTextPosition += len; 24358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 24368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project docTextPosition += len; 24388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startRangeFound) 24418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 24428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLength != 0 && rangeEnd > docTextPosition) { // rangeEnd is out of bounds 24448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2445635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset(), exception); 24468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return resultRange.release(); 24498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 24508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool TextIterator::locationAndLengthFromRange(const Range* range, size_t& location, size_t& length) 24522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 24532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch location = notFound; 24542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch length = 0; 24552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!range->startContainer()) 24572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 24582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement(); 24602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement(); 24612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // The critical assumption is that this only gets called with ranges that 24632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // concentrate on a given area containing the selection root. This is done 24642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // because of text fields and textareas. The DOM for those is not 24652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // directly in the document DOM, so ensure that the range does not cross a 24662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // boundary of one of those. 24672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope)) 24682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 24692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope)) 24702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 24712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); 24732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(testRange->startContainer() == scope); 24742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch location = TextIterator::rangeLength(testRange.get()); 24752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ExceptionCode ec; 24772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch testRange->setEnd(range->endContainer(), range->endOffset(), ec); 24782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(testRange->startContainer() == scope); 24792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch length = TextIterator::rangeLength(testRange.get()) - location; 24802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return true; 24812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 24822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 24838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 24848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 248568513a70bcd92384395513322f1b801e7bf9c729Steve BlockUChar* plainTextToMallocAllocatedBuffer(const Range* r, unsigned& bufferLength, bool isDisplayString, TextIteratorBehavior defaultBehavior) 24868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 24878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* result = 0; 24888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Do this in pieces to avoid massive reallocations if there is a large amount of text. 24908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Use system malloc for buffers since they can consume lots of memory and current TCMalloc is unable return it back to OS. 24918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static const unsigned cMaxSegmentSize = 1 << 16; 24928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferLength = 0; 24938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project typedef pair<UChar*, unsigned> TextSegment; 2494e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block OwnPtr<Vector<TextSegment> > textSegments; 24958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> textBuffer; 24968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian textBuffer.reserveInitialCapacity(cMaxSegmentSize); 249768513a70bcd92384395513322f1b801e7bf9c729Steve Block TextIteratorBehavior behavior = defaultBehavior; 249868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!isDisplayString) 249968513a70bcd92384395513322f1b801e7bf9c729Steve Block behavior = static_cast<TextIteratorBehavior>(behavior | TextIteratorEmitsTextsWithoutTranscoding); 250068513a70bcd92384395513322f1b801e7bf9c729Steve Block 250168513a70bcd92384395513322f1b801e7bf9c729Steve Block for (TextIterator it(r, behavior); !it.atEnd(); it.advance()) { 25028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textBuffer.size() && textBuffer.size() + it.length() > cMaxSegmentSize) { 25038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* newSegmentBuffer = static_cast<UChar*>(malloc(textBuffer.size() * sizeof(UChar))); 25048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!newSegmentBuffer) 25058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto exit; 25068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(newSegmentBuffer, textBuffer.data(), textBuffer.size() * sizeof(UChar)); 25078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!textSegments) 2508e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block textSegments = adoptPtr(new Vector<TextSegment>); 25098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textSegments->append(make_pair(newSegmentBuffer, (unsigned)textBuffer.size())); 25108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textBuffer.clear(); 25118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textBuffer.append(it.characters(), it.length()); 25138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferLength += it.length(); 25148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 25168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!bufferLength) 25178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 25188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 25198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Since we know the size now, we can make a single buffer out of the pieces with one big alloc 25208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result = static_cast<UChar*>(malloc(bufferLength * sizeof(UChar))); 25218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!result) 25228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto exit; 25238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 25248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 25258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* resultPos = result; 25268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textSegments) { 25278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned size = textSegments->size(); 25288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < size; ++i) { 25298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const TextSegment& segment = textSegments->at(i); 25308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(resultPos, segment.first, segment.second * sizeof(UChar)); 25318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project resultPos += segment.second; 25328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(resultPos, textBuffer.data(), textBuffer.size() * sizeof(UChar)); 25358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 25378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectexit: 25388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textSegments) { 25398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned size = textSegments->size(); 25408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < size; ++i) 25418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project free(textSegments->at(i).first); 25428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2543635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2544635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isDisplayString && r->ownerDocument()) 2545635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->ownerDocument()->displayBufferModifiedByEncoding(result, bufferLength); 2546635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 25478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return result; 25488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 25498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 255068513a70bcd92384395513322f1b801e7bf9c729Steve BlockString plainText(const Range* r, TextIteratorBehavior defaultBehavior) 25518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 25528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length; 255368513a70bcd92384395513322f1b801e7bf9c729Steve Block UChar* buf = plainTextToMallocAllocatedBuffer(r, length, false, defaultBehavior); 25548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!buf) 25558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ""; 25568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String result(buf, length); 25578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project free(buf); 25588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return result; 25598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 25608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline bool isAllCollapsibleWhitespace(const String& string) 25628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2563635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const UChar* characters = string.characters(); 2564635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned length = string.length(); 2565635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (unsigned i = 0; i < length; ++i) { 2566635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!isCollapsibleWhitespace(characters[i])) 2567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return false; 2568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return true; 2570635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 25718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2572635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PassRefPtr<Range> collapsedToBoundary(const Range* range, bool forward) 2573635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 25748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec = 0; 25758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> result = range->cloneRange(ec); 2576635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 25778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result->collapse(!forward, ec); 2578635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2579635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return result.release(); 2580635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 25818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2582f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic size_t findPlainText(CharacterIterator& it, const String& target, FindOptions options, size_t& matchStart) 2583635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2584635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchStart = 0; 2585635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchLength = 0; 2586635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2587f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch SearchBuffer buffer(target, options); 2588f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2589f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (buffer.needsMoreContext()) { 2590f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RefPtr<Range> startRange = it.range(); 2591f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RefPtr<Range> beforeStartRange = startRange->ownerDocument()->createRange(); 2592f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ExceptionCode ec = 0; 2593f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch beforeStartRange->setEnd(startRange->startContainer(), startRange->startOffset(), ec); 2594f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (SimplifiedBackwardsTextIterator backwardsIterator(beforeStartRange.get()); !backwardsIterator.atEnd(); backwardsIterator.advance()) { 2595f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch buffer.prependContext(backwardsIterator.characters(), backwardsIterator.length()); 2596f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!buffer.needsMoreContext()) 2597f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch break; 2598f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2599f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2600635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2601635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (!it.atEnd()) { 2602635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(buffer.append(it.characters(), it.length())); 2603635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjecttryAgain: 2604635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchStartOffset; 2605635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (size_t newMatchLength = buffer.search(matchStartOffset)) { 2606635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Note that we found a match, and where we found it. 2607635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t lastCharacterInBufferOffset = it.characterOffset(); 2608635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(lastCharacterInBufferOffset >= matchStartOffset); 2609635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchStart = lastCharacterInBufferOffset - matchStartOffset; 2610635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchLength = newMatchLength; 2611635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If searching forward, stop on the first match. 2612635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If searching backward, don't stop, so we end up with the last match. 2613f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!(options & Backwards)) 2614635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 2615635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto tryAgain; 2616635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2617635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (it.atBreak() && !buffer.atBreak()) { 2618635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer.reachedBreak(); 2619635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto tryAgain; 26208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 26218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 26228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2623635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return matchLength; 2624635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2625635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2626f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochPassRefPtr<Range> findPlainText(const Range* range, const String& target, FindOptions options) 2627f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // First, find the text. 2629635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchStart; 2630635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchLength; 2631635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project { 263221939df44de1705786c545cd1bf519d47250322dBen Murdoch CharacterIterator findIterator(range, TextIteratorEntersTextControls); 2633f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch matchLength = findPlainText(findIterator, target, options, matchStart); 2634635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!matchLength) 2635f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return collapsedToBoundary(range, !(options & Backwards)); 26368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 26378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2638635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Then, find the document position of the start and the end of the text. 263921939df44de1705786c545cd1bf519d47250322dBen Murdoch CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls); 2640635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return characterSubrange(computeRangeIterator, matchStart, matchLength); 26418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 26428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 26438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2644