TextIterator.cpp revision ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb
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 "CharacterNames.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.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" 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "TextBreakIteratorInternalICU.h" 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <unicode/usearch.h> 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF::Unicode; 52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectusing namespace std; 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Buffer that knows how to compare with a search target. 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Keeps enough of the previous text to be able to search in the future, but no more. 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// Non-breaking spaces are always equal to normal spaces. 61f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Case folding is also done if the CaseInsensitive option is specified. 62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Matches are further filtered if the AtWordStarts option is specified, although some 63f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// matches inside a word are permitted if TreatMedialCapitalAsWordStart is specified as well. 64ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochclass SearchBuffer { 65ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch WTF_MAKE_NONCOPYABLE(SearchBuffer); 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic: 67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch SearchBuffer(const String& target, FindOptions); 68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ~SearchBuffer(); 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Returns number of characters appended; guaranteed to be in the range [1, length]. 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t append(const UChar*, size_t length); 72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool needsMoreContext() const; 73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch void prependContext(const UChar*, size_t length); 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project void reachedBreak(); 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 76635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Result is the size in characters of what was found. 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // And <startOffset> is the number of characters back to the start of what was found. 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t search(size_t& startOffset); 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool atBreak() const; 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 81635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectprivate: 84d0825bca7fe65beaee391d30da42e937db621564Steve Block bool isBadMatch(const UChar*, size_t length) const; 85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool isWordStartMatch(size_t start, size_t length) const; 86d0825bca7fe65beaee391d30da42e937db621564Steve Block 87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project String m_target; 88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FindOptions m_options; 89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<UChar> m_buffer; 91635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t m_overlap; 92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t m_prefixLength; 93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bool m_atBreak; 94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool m_needsMoreContext; 95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 96d0825bca7fe65beaee391d30da42e937db621564Steve Block bool m_targetRequiresKanaWorkaround; 97d0825bca7fe65beaee391d30da42e937db621564Steve Block Vector<UChar> m_normalizedTarget; 98d0825bca7fe65beaee391d30da42e937db621564Steve Block mutable Vector<UChar> m_normalizedMatch; 99d0825bca7fe65beaee391d30da42e937db621564Steve Block 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate: 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void append(UChar, bool isCharacterStart); 104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t length() const; 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String m_target; 107f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FindOptions m_options; 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Vector<UChar> m_buffer; 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<bool> m_isCharacterStartBuffer; 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool m_isBufferFull; 112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t m_cursor; 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned bitsInWord = sizeof(unsigned) * 8; 1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned bitInWordMask = bitsInWord - 1; 1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochBitStack::BitStack() 1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_size(0) 1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 127a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochBitStack::~BitStack() 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid BitStack::push(bool bit) 1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned index = m_size / bitsInWord; 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned shift = m_size & bitInWordMask; 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!shift && index == m_words.size()) { 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_words.grow(index + 1); 1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_words[index] = 0; 1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned& word = m_words[index]; 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned mask = 1U << shift; 1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (bit) 1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch word |= mask; 1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else 1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch word &= ~mask; 1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ++m_size; 1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid BitStack::pop() 1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_size) 1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch --m_size; 1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool BitStack::top() const 1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!m_size) 1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned shift = (m_size - 1) & bitInWordMask; 1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return m_words.last() & (1U << shift); 1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochunsigned BitStack::size() const 1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return m_size; 1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// -------- 1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 169d0825bca7fe65beaee391d30da42e937db621564Steve Block#if !ASSERT_DISABLED 1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic unsigned depthCrossingShadowBoundaries(Node* node) 1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned depth = 0; 174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* parent = node->parentOrHostNode(); parent; parent = parent->parentOrHostNode()) 1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ++depth; 1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return depth; 1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// This function is like Range::pastLastNode, except for the fact that it can climb up out of shadow trees. 1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic Node* nextInPreOrderCrossingShadowBoundaries(Node* rangeEndContainer, int rangeEndOffset) 1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!rangeEndContainer) 1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (rangeEndOffset >= 0 && !rangeEndContainer->offsetInCharacters()) { 1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* next = rangeEndContainer->childNode(rangeEndOffset)) 1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return next; 1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* node = rangeEndContainer; node; node = node->parentOrHostNode()) { 1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* next = node->nextSibling()) 1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return next; 1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic Node* previousInPostOrderCrossingShadowBoundaries(Node* rangeStartContainer, int rangeStartOffset) 1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!rangeStartContainer) 2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 2010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (rangeStartOffset > 0 && !rangeStartContainer->offsetInCharacters()) { 2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* previous = rangeStartContainer->childNode(rangeStartOffset - 1)) 2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return previous; 2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* node = rangeStartContainer; node; node = node->parentOrHostNode()) { 2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (Node* previous = node->previousSibling()) 2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return previous; 2080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// -------- 2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool fullyClipsContents(Node* node) 2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = node->renderer(); 2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!renderer || !renderer->isBox() || !renderer->hasOverflowClip()) 2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return toRenderBox(renderer)->size().isEmpty(); 2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool ignoresContainerClip(Node* node) 2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = node->renderer(); 2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!renderer || renderer->isText()) 2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch EPosition position = renderer->style()->position(); 2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return position == AbsolutePosition || position == FixedPosition; 2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void pushFullyClippedState(BitStack& stack, Node* node) 2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(stack.size() == depthCrossingShadowBoundaries(node)); 2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Push true if this node full clips its contents, or if a parent already has fully 2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // clipped and this is not a node that ignores its container's clip. 237643ca7872b450ea4efacab6188849e5aac2ba161Steve Block stack.push(fullyClipsContents(node) || (stack.top() && !ignoresContainerClip(node))); 2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void setUpFullyClippedStack(BitStack& stack, Node* node) 2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Put the nodes in a vector so we can iterate in reverse order. 2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Vector<Node*, 100> ancestry; 244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (Node* parent = node->parentOrHostNode(); parent; parent = parent->parentOrHostNode()) 2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ancestry.append(parent); 2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Call pushFullyClippedState on each node starting with the earliest ancestor. 2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t size = ancestry.size(); 2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (size_t i = 0; i < size; ++i) 2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(stack, ancestry[size - i - 1]); 2510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(stack, node); 2520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node)); 2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 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) 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockTextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) 278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block : m_startContainer(0) 279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_startOffset(0) 280dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_endContainer(0) 281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_endOffset(0) 282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_positionNode(0) 283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_textCharacters(0) 284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_textLength(0) 285dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_remainingTextBox(0) 286dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_firstLetterText(0) 28721939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_emitsCharactersBetweenAllVisiblePositions(behavior & TextIteratorEmitsCharactersBetweenAllVisiblePositions) 28821939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_entersTextControls(behavior & TextIteratorEntersTextControls) 28921939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding) 290dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_handledFirstLetter(false) 29168513a70bcd92384395513322f1b801e7bf9c729Steve Block , m_ignoresStyleVisibility(behavior & TextIteratorIgnoresStyleVisibility) 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 293dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609 294dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch ASSERT(behavior != TextIteratorEndsAtEditingBoundary); 295dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // get and validate the range endpoints 300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* startContainer = r->startContainer(); 301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!startContainer) 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int startOffset = r->startOffset(); 304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* endContainer = r->endContainer(); 305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int endOffset = r->endOffset(); 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Callers should be handing us well-formed ranges. If we discover that this isn't 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the case, we could consider changing this assertion to an early return. 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(r->boundaryPointsValid()); 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember range - this does not change 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startContainer = startContainer; 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startOffset = startOffset; 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endContainer = endContainer; 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endOffset = endOffset; 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // set up the current node for processing 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = r->firstNode(); 3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!m_node) 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch setUpFullyClippedStack(m_fullyClippedStack, m_node); 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = m_node == m_startContainer ? m_startOffset : 0; 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // calculate first out of bounds node 3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_pastEndNode = nextInPreOrderCrossingShadowBoundaries(endContainer, endOffset); 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // initialize node processing state 33021939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = false; 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = 0; 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // initialize record of previous node processing 33421939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = false; 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = 0; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = 0; 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // need this just because of the assert in advance() 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node; 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // identify the first run 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 348a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochTextIterator::~TextIterator() 349a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 350a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 351a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::advance() 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // reset the run information 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = 0; 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle remembered node that needed a newline after the text node's newline 35921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_needsAnotherNewline) { 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit the extra newline, and position it *inside* m_node, after m_node's 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // contents, in case it's a block, in the same way that we position the first 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // newline. The range for the emitted newline should start where the line 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // break begins. 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: It would be cleaner if we emitted two newlines during the last 36521939df44de1705786c545cd1bf519d47250322dBen Murdoch // iteration, instead of using m_needsAnotherNewline. 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 36821939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = false; 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 372dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_textBox && m_remainingTextBox) { 373dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = m_remainingTextBox; 374dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = 0; 375dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 376dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_offset = 0; 377dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle remembered text box 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textBox) { 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project handleTextBox(); 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_node && m_node != m_pastEndNode) { 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // if the range ends at offset 0 of an element, represent the 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // position, but not the content, of that element e.g. if the 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // node is a blockflow element, emit a newline that 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // precedes the element 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_node == m_endContainer && m_endOffset == 0) { 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project representNodeOffsetZero(); 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = 0; 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = m_node->renderer(); 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer) { 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle current node according to its type 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_handledNode) { 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) // FIXME: What about CDATA_SECTION_NODE? 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleTextNode(); 4058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else if (renderer && (renderer->isImage() || renderer->isWidget() || 4068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian (renderer->node() && renderer->node()->isElementNode() && 4078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian static_cast<Element*>(renderer->node())->isFormControlElement()))) 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleReplacedElement(); 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleNonTextNode(); 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // find a new current node to handle in depth-first manner, 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // calling exitNode() as we come back thru a parent node 4180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Node* next = m_handledChildren ? 0 : m_node->firstChild(); 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = 0; 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!next) { 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project next = m_node->nextSibling(); 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!next) { 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool pastEnd = m_node->traverseNextNode() == m_pastEndNode; 424f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Node* parentNode = m_node->parentOrHostNode(); 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!next && parentNode) { 4268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if ((pastEnd && parentNode == m_endContainer) || m_endContainer->isDescendantOf(parentNode)) 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool haveRenderer = m_node->renderer(); 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = parentNode; 4300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 431f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch parentNode = m_node->parentOrHostNode(); 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (haveRenderer) 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project next = m_node->nextSibling(); 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // set the new current node 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_node = next; 4470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_node) 4480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 451dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = false; 452dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // how would this ever be? 4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleTextNode() 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 46268513a70bcd92384395513322f1b801e7bf9c729Steve Block if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) 4630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 4640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RenderText* renderer = toRenderText(m_node->renderer()); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = m_node; 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // handle pre-formatted text 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->style()->collapseWhiteSpace()) { 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runStart = m_offset; 473dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer)) { 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart); 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 477dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment()) { 478dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 479dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_firstLetterText) { 480dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch String firstLetter = m_firstLetterText->text(); 4814576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang emitText(m_node, m_firstLetterText, m_offset, m_offset + firstLetter.length()); 482dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 483dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = 0; 484dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 485dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 486dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 48768513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 488dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int strLength = str.length(); 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runEnd = min(strLength, end); 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runStart >= runEnd) 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitText(m_node, runStart, runEnd); 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->firstTextBox() && str.length() > 0) { 501dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment()) { 502dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 503dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_firstLetterText) { 504dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextBox(); 505dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 506dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 507dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 50868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 509dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text) 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) { 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxes.clear(); 5170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (InlineTextBox* textBox = renderer->firstTextBox(); textBox; textBox = textBox->nextTextBox()) { 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxes.append(textBox); 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 520f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick std::sort(m_sortedTextBoxes.begin(), m_sortedTextBoxes.end(), InlineTextBox::compareByStart); 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_sortedTextBoxesPosition = 0; 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 52421939df44de1705786c545cd1bf519d47250322dBen Murdoch m_textBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox(); 525dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) 526dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project handleTextBox(); 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::handleTextBox() 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 533dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* renderer = m_firstLetterText ? m_firstLetterText : toRenderText(m_node->renderer()); 53468513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) { 535dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = 0; 536dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 537dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 539f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned start = m_offset; 5405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : UINT_MAX; 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_textBox) { 542f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned textBoxStart = m_textBox->start(); 543f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned runStart = max(textBoxStart, start); 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check for collapsed space at the start of this run. 5460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch InlineTextBox* firstTextBox = renderer->containsReversedText() ? m_sortedTextBoxes[0] : renderer->firstTextBox(); 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool needSpace = m_lastTextNodeEndedWithCollapsedSpace 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || (m_textBox == firstTextBox && textBoxStart == runStart && runStart > 0); 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (needSpace && !isCollapsibleWhitespace(m_lastCharacter) && m_lastCharacter) { 550635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1] == ' ') { 551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned spaceRunStart = runStart - 1; 552635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ') 553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project --spaceRunStart; 554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project emitText(m_node, spaceRunStart, spaceRunStart + 1); 555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else 556635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart); 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 559f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned textBoxEnd = textBoxStart + m_textBox->len(); 560f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned runEnd = min(textBoxEnd, end); 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Determine what the next text box will be, but don't advance yet 5630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch InlineTextBox* nextTextBox = 0; 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) { 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size()) 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition + 1]; 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextTextBox = m_textBox->nextTextBox(); 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runStart < runEnd) { 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle either a single newline character (which becomes a space), 5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // or a run of characters that does not include a newline. 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This effectively translates newlines to spaces without copying the text. 5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (str[runStart] == '\n') { 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node, 0, runStart, runStart + 1); 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = runStart + 1; 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 578f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t subrunEnd = str.find('\n', runStart); 579f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (subrunEnd == notFound || subrunEnd > runEnd) 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project subrunEnd = runEnd; 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = subrunEnd; 583dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch emitText(m_node, renderer, runStart, subrunEnd); 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we are doing a subrun that doesn't go to the end of the text box, 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // come back again to finish handling this text box; don't advance to the next one. 588f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (static_cast<unsigned>(m_positionEndOffset) < textBoxEnd) 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Advance and return 592f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned nextRunStart = nextTextBox ? nextTextBox->start() : str.length(); 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextRunStart > runEnd) 5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = nextTextBox; 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++m_sortedTextBoxesPosition; 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Advance and continue 6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textBox = nextTextBox; 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->containsReversedText()) 6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++m_sortedTextBoxesPosition; 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 605dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!m_textBox && m_remainingTextBox) { 606dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = m_remainingTextBox; 607dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = 0; 608dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = 0; 609dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_offset = 0; 610dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch handleTextBox(); 611dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 612dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 613dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 614dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) 615dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 616dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->firstLetter()) { 617dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderObject* r = renderer->firstLetter(); 61868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 619dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 620dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch for (RenderObject *currChild = r->firstChild(); currChild; currChild->nextSibling()) { 621dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (currChild->isText()) { 622dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* firstLetter = toRenderText(currChild); 623dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = true; 624dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_remainingTextBox = m_textBox; 625dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_textBox = firstLetter->firstTextBox(); 626dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_firstLetterText = firstLetter; 627dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return; 628dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 629dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 630dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 631dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_handledFirstLetter = true; 6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleReplacedElement() 6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_fullyClippedStack.top()) 6370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* renderer = m_node->renderer(); 64068513a70bcd92384395513322f1b801e7bf9c729Steve Block if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) 6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastTextNodeEndedWithCollapsedSpace) { 6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_lastTextNode->parentNode(), m_lastTextNode, 1, 1); 6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 64821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_entersTextControls && renderer->isTextControl()) { 6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (HTMLElement* innerTextElement = toRenderTextControl(renderer)->innerTextElement()) { 6500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_node = innerTextElement->shadowTreeRootNode(); 6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 6520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_offset = 0; 6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return false; 6540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 65721939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 65921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_emitsCharactersBetweenAllVisiblePositions) { 6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We want replaced elements to behave like punctuation for boundary 6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // finding, and to simply take up space for the selection preservation 6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // code in moveParagraphs, so we use a comma. 6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(',', m_node->parentNode(), m_node, 0, 1); 6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node->parentNode(); 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = m_node; 6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = 0; 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = 1; 6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = 0; 6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = 0; 6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 680dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochbool TextIterator::hasVisibleTextNode(RenderText* renderer) 681dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 682dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->style()->visibility() == VISIBLE) 683dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 684dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer->isTextFragment()) { 685dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderTextFragment* fragment = static_cast<RenderTextFragment*>(renderer); 686dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (fragment->firstLetter() && fragment->firstLetter()->style()->visibility() == VISIBLE) 687dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 688dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch } 689dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 690dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 691dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitTabBeforeNode(Node* node) 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Table cells are delimited by tabs. 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r || !isTableCell(node)) 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Want a tab before every cell other than the first one 7010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderTableCell* rc = toRenderTableCell(r); 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderTable* t = rc->table(); 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return t && (t->cellBefore(rc) || t->cellAbove(rc)); 7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineForNode(Node* node) 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // br elements are represented by a single newline. 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node->hasTagName(brTag); 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r->isBR(); 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlinesBeforeAndAfterNode(Node* node) 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Block flow (versus inline flow) is represented by having 7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // a newline both before and after the element. 7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) { 7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (node->hasTagName(blockquoteTag) 7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(ddTag) 7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(divTag) 7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(dlTag) 7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(dtTag) 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h1Tag) 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h2Tag) 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h3Tag) 7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h4Tag) 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h5Tag) 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h6Tag) 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(hrTag) 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(liTag) 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(listingTag) 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(olTag) 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(pTag) 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(preTag) 7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(trTag) 7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(ulTag)); 7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to make an exception for table cells, because they are blocks, but we 7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // want them tab-delimited rather than having newlines before and after. 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isTableCell(node)) 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need to make an exception for table row elements, because they are neither 7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // "inline" or "RenderBlock", but we want newlines for them. 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->isTableRow()) { 7510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderTable* t = toRenderTableRow(r)->table(); 7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (t && !t->isInline()) 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return !r->isInline() && r->isRenderBlock() && !r->isFloatingOrPositioned() && !r->isBody(); 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineAfterNode(Node* node) 7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: It should be better but slower to create a VisiblePosition here. 7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!shouldEmitNewlinesBeforeAndAfterNode(node)) 7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check if this is the very last renderer in the document. 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If so, then we should not emit a newline. 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while ((node = node->traverseNextSibling())) 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->renderer()) 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitNewlineBeforeNode(Node* node) 7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return shouldEmitNewlinesBeforeAndAfterNode(node); 7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool shouldEmitExtraNewlineForNode(Node* node) 7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When there is a significant collapsed bottom margin, emit an extra 7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // newline for a more realistic result. We end up getting the right 7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // result even without margin collapsing. For example: <div><p>text</p></div> 7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will work right even if both the <div> and the <p> have bottom margins. 7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* r = node->renderer(); 784635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!r || !r->isBox()) 7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears 7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // not to do this at all 7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->hasTagName(h1Tag) 7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h2Tag) 7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h3Tag) 7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h4Tag) 7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h5Tag) 7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(h6Tag) 7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || node->hasTagName(pTag)) { 7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle* style = r->style(); 7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (style) { 798bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen int bottomMargin = toRenderBox(r)->collapsedMarginAfter(); 7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int fontSize = style->fontDescription().computedPixelSize(); 8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (bottomMargin * 2 >= fontSize) 8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 808d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic int collapsedSpaceLength(RenderText* renderer, int textEnd) 809d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 810d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* characters = renderer->text()->characters(); 811d0825bca7fe65beaee391d30da42e937db621564Steve Block int length = renderer->text()->length(); 812d0825bca7fe65beaee391d30da42e937db621564Steve Block for (int i = textEnd; i < length; ++i) { 813d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!renderer->style()->isCollapsibleWhiteSpace(characters[i])) 814d0825bca7fe65beaee391d30da42e937db621564Steve Block return i - textEnd; 815d0825bca7fe65beaee391d30da42e937db621564Steve Block } 816d0825bca7fe65beaee391d30da42e937db621564Steve Block 817d0825bca7fe65beaee391d30da42e937db621564Steve Block return length - textEnd; 818d0825bca7fe65beaee391d30da42e937db621564Steve Block} 819d0825bca7fe65beaee391d30da42e937db621564Steve Block 820d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic int maxOffsetIncludingCollapsedSpaces(Node* node) 821d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 822d0825bca7fe65beaee391d30da42e937db621564Steve Block int offset = caretMaxOffset(node); 823d0825bca7fe65beaee391d30da42e937db621564Steve Block 824d0825bca7fe65beaee391d30da42e937db621564Steve Block if (node->renderer() && node->renderer()->isText()) 825d0825bca7fe65beaee391d30da42e937db621564Steve Block offset += collapsedSpaceLength(toRenderText(node->renderer()), offset); 826d0825bca7fe65beaee391d30da42e937db621564Steve Block 827d0825bca7fe65beaee391d30da42e937db621564Steve Block return offset; 828d0825bca7fe65beaee391d30da42e937db621564Steve Block} 829d0825bca7fe65beaee391d30da42e937db621564Steve Block 830635860845790a19bf50bbc51ba8fb66a96dde068The 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). 8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::shouldRepresentNodeOffsetZero() 8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 83321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isTable()) 8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Leave element positioned flush with start of a paragraph 8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // (e.g. do not insert tab before a table cell at the start of a paragraph) 8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastCharacter == '\n') 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Otherwise, show the position if we have emitted any characters 84221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (m_hasEmitted) 8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We've not emitted anything yet. Generally, there is no need for any positioning then. 8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The only exception is when the element is visually not in the same line as 8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the start of the range (e.g. the range starts at the end of the previous paragraph). 8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: Creating VisiblePositions and comparing them is relatively expensive, so we 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make quicker checks to possibly avoid that. Another check that we could make is 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is whether the inline vs block flow changed since the previous visible element. 8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // I think we're already in a special enough case that that won't be needed, tho. 8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 853635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // No character needed if this is the first node in the range. 8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_node == m_startContainer) 8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 857635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If we are outside the start container's subtree, assume we need to emit. 8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: m_startContainer could be an inline block 8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_node->isDescendantOf(m_startContainer)) 8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we started as m_startContainer offset 0 and the current node is a descendant of 8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the start container, we already had enough context to correctly decide whether to 86421939df44de1705786c545cd1bf519d47250322dBen Murdoch // emit after a preceding block. We chose not to emit (m_hasEmitted is false), 8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // so don't second guess that now. 8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: Is this really correct when m_node is not a leftmost descendant? Probably 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // immaterial since we likely would have already emitted something by now. 8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_startOffset == 0) 8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 870635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 871635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If this node is unrendered or invisible the VisiblePosition checks below won't have much meaning. 872635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Additionally, if the range we are iterating over contains huge sections of unrendered content, 873635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we would create VisiblePositions on every call to this function without this check. 874635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_node->renderer() || m_node->renderer()->style()->visibility() != VISIBLE) 875635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return false; 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The startPos.isNotNull() check is needed because the start could be before the body, 8785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // and in that case we'll get null. We don't want to put in newlines at the start in that case. 8795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The currPos.isNotNull() check is needed because positions in non-HTML content 8805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // (like SVG) do not have visible positions, and we don't want to emit for them either. 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPos = VisiblePosition(m_startContainer, m_startOffset, DOWNSTREAM); 8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition currPos = VisiblePosition(m_node, 0, DOWNSTREAM); 8835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return startPos.isNotNull() && currPos.isNotNull() && !inSameLine(startPos, currPos); 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::shouldEmitSpaceBeforeAndAfterNode(Node* node) 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 88821939df44de1705786c545cd1bf519d47250322dBen Murdoch return node->renderer() && node->renderer()->isTable() && (node->renderer()->isInline() || m_emitsCharactersBetweenAllVisiblePositions); 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::representNodeOffsetZero() 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit a character to show the positioning of m_node. 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // When we haven't been emitting any characters, shouldRepresentNodeOffsetZero() can 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // create VisiblePositions, which is expensive. So, we perform the inexpensive checks 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // on m_node to see if it necessitates emitting a character first and will early return 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldEmitTabBeforeNode(m_node)) { 9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); 9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (shouldEmitNewlineBeforeNode(m_node)) { 9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); 9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { 9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldRepresentNodeOffsetZero()) 9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool TextIterator::handleNonTextNode() 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shouldEmitNewlineForNode(m_node)) 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), m_node, 0, 1); 91521939df44de1705786c545cd1bf519d47250322dBen Murdoch else if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isHR()) 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', m_node->parentNode(), m_node, 0, 1); 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project representNodeOffsetZero(); 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TextIterator::exitNode() 9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // prevent emitting a newline when exiting a collapsed block at beginning of the range 92621939df44de1705786c545cd1bf519d47250322dBen Murdoch // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed block... it could 9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // have been an hr (e.g.). Also, a collapsed block could have height (e.g. a table) and 9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // therefore look like a blank line. 92921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!m_hasEmitted) 9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Emit with a position *inside* m_node, after m_node's contents, in 9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // case it is a block, because the run should start where the 9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // emitted character is positioned visually. 9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; 9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making 9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the logic in _web_attributedStringFromRange match. We'll get that for free when we switch to use 9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // TextIterator in _web_attributedStringFromRange. 9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // See <rdar://problem/5428427> for an example of how this mismatch will cause problems. 9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastTextNode && shouldEmitNewlineAfterNode(m_node)) { 9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // use extra newline to represent margin bottom, as needed 9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool addNewline = shouldEmitExtraNewlineForNode(m_node); 9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: We need to emit a '\n' as we leave an empty block(s) that 9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // contain a VisiblePosition when doing selection preservation. 9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_lastCharacter != '\n') { 9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // insert a newline with a position following this block's contents. 9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember whether to later add a newline for the current node 95021939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(!m_needsAnotherNewline); 95121939df44de1705786c545cd1bf519d47250322dBen Murdoch m_needsAnotherNewline = addNewline; 9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (addNewline) 9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // insert a newline with a position following this block's contents. 9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); 9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If nothing was emitted, see if we need to emit a space. 9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_positionNode && shouldEmitSpaceBeforeAndAfterNode(m_node)) 9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(' ', baseNode->parentNode(), baseNode, 1, 1); 9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode, int textStartOffset, int textEndOffset) 9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 96421939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember information with which to construct the TextIterator::range() 9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: textNode is often not a text node, so the range will specify child nodes of positionNode 9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = textNode; 9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = offsetBaseNode; 9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = textStartOffset; 9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = textEndOffset; 9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember information with which to construct the TextIterator::characters() and length() 9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_singleCharacterBuffer = c; 9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = &m_singleCharacterBuffer; 9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 1; 9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember some iteration state 9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = c; 9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 983dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::emitText(Node* textNode, RenderObject* renderObject, int textStartOffset, int textEndOffset) 9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 985dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderText* renderer = toRenderText(renderObject); 98621939df44de1705786c545cd1bf519d47250322dBen Murdoch m_text = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text(); 98721939df44de1705786c545cd1bf519d47250322dBen Murdoch ASSERT(m_text.characters()); 9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = textNode; 9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = 0; 9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = textStartOffset; 9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = textEndOffset; 99321939df44de1705786c545cd1bf519d47250322dBen Murdoch m_textCharacters = m_text.characters() + textStartOffset; 9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = textEndOffset - textStartOffset; 99521939df44de1705786c545cd1bf519d47250322dBen Murdoch m_lastCharacter = m_text[textEndOffset - 1]; 9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNodeEndedWithCollapsedSpace = false; 99821939df44de1705786c545cd1bf519d47250322dBen Murdoch m_hasEmitted = true; 9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1001dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset) 1002dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 1003dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch emitText(textNode, m_node->renderer(), textStartOffset, textEndOffset); 1004dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1005dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> TextIterator::range() const 10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // use the current run information, if we have it 10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionOffsetBaseNode) { 10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int index = m_positionOffsetBaseNode->nodeIndex(); 10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset += index; 10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset += index; 10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionOffsetBaseNode = 0; 10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset); 10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // otherwise, return the end of the overall range we were given 10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_endContainer) 10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_endContainer->document(), m_endContainer, m_endOffset, m_endContainer, m_endOffset); 10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* TextIterator::node() const 10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> textRange = range(); 10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!textRange) 10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* node = textRange->startContainer(); 10338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!node) 10348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 10358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (node->offsetInCharacters()) 10368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node; 10378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return node->childNode(textRange->startOffset()); 10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 10428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() 1044dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch : m_behavior(TextIteratorDefaultBehavior) 1045dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_node(0) 1046dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_positionNode(0) 10478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1050dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochSimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior) 1051dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch : m_behavior(behavior) 1052dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_node(0) 1053dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_positionNode(0) 10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1055dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary); 1056dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!r) 10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 10598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1060635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* startNode = r->startContainer(); 1061635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!startNode) 10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1063635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* endNode = r->endContainer(); 1064635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int startOffset = r->startOffset(); 1065635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int endOffset = r->endOffset(); 10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startNode->offsetInCharacters()) { 10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startOffset >= 0 && startOffset < static_cast<int>(startNode->childNodeCount())) { 10698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startNode = startNode->childNode(startOffset); 10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startOffset = 0; 10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!endNode->offsetInCharacters()) { 10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (endOffset > 0 && endOffset <= static_cast<int>(endNode->childNodeCount())) { 10758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endNode = endNode->childNode(endOffset - 1); 1076231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block endOffset = lastOffsetInNode(endNode); 10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1080dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch setCurrentNode(endNode); 10810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch setUpFullyClippedStack(m_fullyClippedStack, m_node); 10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = endOffset; 10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 10848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = endOffset == 0; 10858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startNode = startNode; 10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_startOffset = startOffset; 10888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endNode = endNode; 10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_endOffset = endOffset; 10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG 10928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Need this just because of the assert. 10938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = endNode; 10948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 10958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = 0; 10978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = '\n'; 10980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_pastStartNode = previousInPostOrderCrossingShadowBoundaries(startNode, startOffset); 11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(); 11028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimplifiedBackwardsTextIterator::advance() 11058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_positionNode); 11078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = 0; 11098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 0; 11108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_node && m_node != m_pastStartNode) { 11128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Don't handle node if we start iterating at [node, 0]. 11138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_handledNode && !(m_node == m_endNode && m_endOffset == 0)) { 11140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* renderer = m_node->renderer(); 11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer && renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) { 11168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: What about CDATA_SECTION_NODE? 11178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->style()->visibility() == VISIBLE && m_offset > 0) 11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleTextNode(); 11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (renderer && (renderer->isImage() || renderer->isWidget())) { 11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (renderer->style()->visibility() == VISIBLE && m_offset > 0) 11218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleReplacedElement(); 11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = handleNonTextNode(); 11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* next = m_handledChildren ? 0 : m_node->lastChild(); 11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!next) { 11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Exit empty containers as we pass over them or containers 11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // where [container, 0] is where we started iterating. 1132ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch if (!m_handledNode 1133ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && canHaveChildrenForEditing(m_node) 1134ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && m_node->parentNode() 1135ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch && (!m_node->lastChild() || (m_node == m_endNode && !m_endOffset))) { 11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Exit all other containers. 1144dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch while (!m_node->previousSibling()) { 1145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!setCurrentNode(m_node->parentOrHostNode())) 11468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 11470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project exitNode(); 11498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) { 11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = true; 11518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = true; 11528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1155dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 1156dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch next = m_node->previousSibling(); 11570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fullyClippedStack.pop(); 11588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1160dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_node && setCurrentNode(next)) 11610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pushFullyClippedState(m_fullyClippedStack, m_node); 1162dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch else 1163dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch clearCurrentNode(); 1164dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 1165d0825bca7fe65beaee391d30da42e937db621564Steve Block // For the purpose of word boundary detection, 1166d0825bca7fe65beaee391d30da42e937db621564Steve Block // we should iterate all visible text and trailing (collapsed) whitespaces. 1167d0825bca7fe65beaee391d30da42e937db621564Steve Block m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0; 11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledNode = false; 11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_handledChildren = false; 11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleTextNode() 11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastTextNode = m_node; 11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderText* renderer = toRenderText(m_node->renderer()); 11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String str = renderer->text(); 11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!renderer->firstTextBox() && str.length() > 0) 11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = m_offset; 11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset = (m_node == m_startNode) ? m_startOffset : 0; 11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = m_node; 11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = m_offset; 11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = m_positionEndOffset - m_positionStartOffset; 11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = str.characters() + m_positionStartOffset; 11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = str[m_positionEndOffset - 1]; 11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleReplacedElement() 12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned index = m_node->nodeIndex(); 12028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We want replaced elements to behave like punctuation for boundary 12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // finding, and to simply take up space for the selection preservation 12048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // code in moveParagraphs, so we use a comma. Unconditionally emit 12058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // here because this iterator is only used for boundary finding. 12068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter(',', m_node->parentNode(), index, index + 1); 12078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SimplifiedBackwardsTextIterator::handleNonTextNode() 12118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We can use a linefeed in place of a tab because this simple iterator is only used to 12138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. 12140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineAfterNode(m_node) || shouldEmitTabBeforeNode(m_node)) { 12158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned index = m_node->nodeIndex(); 12160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The start of this emitted range is wrong. Ensuring correctness would require 12170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // VisiblePositions and so would be slow. previousBoundary expects this. 12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); 12198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 12208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 12218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SimplifiedBackwardsTextIterator::exitNode() 12248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (shouldEmitNewlineForNode(m_node) || shouldEmitNewlineBeforeNode(m_node) || shouldEmitTabBeforeNode(m_node)) { 12260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The start of this emitted range is wrong. Ensuring correctness would require 12270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // VisiblePositions and so would be slow. previousBoundary expects this. 12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project emitCharacter('\n', m_node, 0, 0); 12290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int startOffset, int endOffset) 12338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_singleCharacterBuffer = c; 12358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionNode = node; 12368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionStartOffset = startOffset; 12378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_positionEndOffset = endOffset; 12388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textCharacters = &m_singleCharacterBuffer; 12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textLength = 1; 12408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastCharacter = c; 12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1243dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochbool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const 1244dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 1245dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return m_node && m_node->isContentEditable() != node->isContentEditable(); 1246dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1247dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 1248dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochbool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node) 1249dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 1250dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!node) 1251dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 1252dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node)) 1253dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return false; 1254dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_node = node; 1255dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return true; 1256dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1257dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 1258dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochvoid SimplifiedBackwardsTextIterator::clearCurrentNode() 1259dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 1260dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch m_node = 0; 1261dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 1262dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 12638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const 12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_positionNode) 12668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset); 12678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return Range::create(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset); 12698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 12728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectCharacterIterator::CharacterIterator() 12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_offset(0) 12758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_runOffset(0) 12768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_atBreak(true) 12778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 128021939df44de1705786c545cd1bf519d47250322dBen MurdochCharacterIterator::CharacterIterator(const Range* r, TextIteratorBehavior behavior) 12818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_offset(0) 12828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_runOffset(0) 12838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_atBreak(true) 128421939df44de1705786c545cd1bf519d47250322dBen Murdoch , m_textIterator(r, behavior) 12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!atEnd() && m_textIterator.length() == 0) 12878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 12888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 12898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> CharacterIterator::range() const 12918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> r = m_textIterator.range(); 12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_textIterator.atEnd()) { 12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.length() <= 1) { 12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_runOffset == 0); 12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 1297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Node* n = r->startContainer(); 1298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(n == r->endContainer()); 1299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int offset = r->startOffset() + m_runOffset; 1300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ExceptionCode ec = 0; 1301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->setStart(n, offset, ec); 1302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->setEnd(n, offset + 1, ec); 1303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 13048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r.release(); 13078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid CharacterIterator::advance(int count) 13108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count <= 0) { 13128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(count == 0); 13138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = false; 13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // easy if there is enough left in the current m_textIterator run 13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int remaining = m_textIterator.length() - m_runOffset; 13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count < remaining) { 13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset += count; 13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += count; 13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // exhaust the current m_textIterator run 13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project count -= remaining; 13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += remaining; 13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // move to a subsequent m_textIterator run 13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) { 13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runLength = m_textIterator.length(); 13338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (runLength == 0) 13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = true; 13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // see whether this is m_textIterator to use 13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (count < runLength) { 13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset = count; 13398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += count; 13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // exhaust this m_textIterator run 13448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project count -= runLength; 13458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_offset += runLength; 13468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ran to the end of the m_textIterator... no more runs left 13508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_atBreak = true; 13518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_runOffset = 0; 13528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString CharacterIterator::string(int numChars) 13558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 13568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> result; 13578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian result.reserveInitialCapacity(numChars); 13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (numChars > 0 && !atEnd()) { 13598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int runSize = min(numChars, length()); 13608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(characters(), runSize); 13618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project numChars -= runSize; 13628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance(runSize); 13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String::adopt(result); 13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 13668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PassRefPtr<Range> characterSubrange(CharacterIterator& it, int offset, int length) 1368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(offset); 1370635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Range> start = it.range(); 1371635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (length > 1) 1373635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(length - 1); 1374635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Range> end = it.range(); 1375635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1376635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return Range::create(start->startContainer()->document(), 1377635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start->startContainer(), start->startOffset(), 1378635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project end->endContainer(), end->endOffset()); 1379635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1380635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 13818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianBackwardsCharacterIterator::BackwardsCharacterIterator() 13828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian : m_offset(0) 13838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_runOffset(0) 13848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_atBreak(true) 13858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 13868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 13878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1388dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochBackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior) 13898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian : m_offset(0) 13908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_runOffset(0) 13918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian , m_atBreak(true) 1392dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch , m_textIterator(range, behavior) 13938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 13948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (!atEnd() && !m_textIterator.length()) 13958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_textIterator.advance(); 13968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 13978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 13988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<Range> BackwardsCharacterIterator::range() const 13998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian RefPtr<Range> r = m_textIterator.range(); 14018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!m_textIterator.atEnd()) { 14028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_textIterator.length() <= 1) 14038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(m_runOffset == 0); 14048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 14058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Node* n = r->startContainer(); 14068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(n == r->endContainer()); 14078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int offset = r->endOffset() - m_runOffset; 14088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ExceptionCode ec = 0; 14098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian r->setStart(n, offset - 1, ec); 14108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian r->setEnd(n, offset, ec); 14118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!ec); 14128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return r.release(); 14158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 14168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid BackwardsCharacterIterator::advance(int count) 14188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 14198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count <= 0) { 14208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian ASSERT(!count); 14218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = false; 14258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int remaining = m_textIterator.length() - m_runOffset; 14278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count < remaining) { 14288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset += count; 14298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += count; 14308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian count -= remaining; 14348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += remaining; 14358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) { 14378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian int runLength = m_textIterator.length(); 14388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (runLength == 0) 14398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = true; 14408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian else { 14418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (count < runLength) { 14428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset = count; 14438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += count; 14448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return; 14458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian count -= runLength; 14488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_offset += runLength; 14498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 14518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_atBreak = true; 14538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_runOffset = 0; 14548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 14558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 14568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 14578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWordAwareIterator::WordAwareIterator() 14590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_previousText(0) 14600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_didLookAhead(false) 14618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochWordAwareIterator::WordAwareIterator(const Range* r) 14650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_previousText(0) 14660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_didLookAhead(true) // so we consider the first chunk from the text iterator 14670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_textIterator(r) 14688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch advance(); // get in position over the first chunk of text 14708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 14718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1472a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochWordAwareIterator::~WordAwareIterator() 1473a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 1474a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 1475a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 14768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We're always in one of these modes: 14778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - The current chunk in the text iterator is our current chunk 14788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// (typically its a piece of whitespace, or text that ended with whitespace) 14798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - The previous chunk in the text iterator is our current chunk 14808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// (we looked ahead to the next chunk and found a word boundary) 14818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - We built up our own chunk of text from many chunks from the text iterator 14828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// FIXME: Performance could be bad for huge spans next to each other that don't fall on word boundaries. 14848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WordAwareIterator::advance() 14868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 14878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = 0; 14888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.clear(); // toss any old buffer we built up 14898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If last time we did a look-ahead, start with that looked-ahead chunk now 14918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_didLookAhead) { 14928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_textIterator.atEnd()); 14938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 14948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 14958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_didLookAhead = false; 14968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Go to next non-empty chunk 14988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (!m_textIterator.atEnd() && m_textIterator.length() == 0) 14998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 15008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_range = m_textIterator.range(); 15018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.atEnd()) 15038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (1) { 15068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If this chunk ends in whitespace we can just use it as our chunk. 15078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSpaceOrNewline(m_textIterator.characters()[m_textIterator.length() - 1])) 15088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If this is the first chunk that failed, save it in previousText before look ahead 15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_buffer.isEmpty()) { 15128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = m_textIterator.characters(); 15138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousLength = m_textIterator.length(); 15148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Look ahead to next chunk. If it is whitespace or a break, we can use the previous stuff 15178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_textIterator.advance(); 15188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_textIterator.atEnd() || m_textIterator.length() == 0 || isSpaceOrNewline(m_textIterator.characters()[0])) { 15198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_didLookAhead = true; 15208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 15218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_buffer.isEmpty()) { 15248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Start gobbling chunks until we get to a suitable stopping point 15258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.append(m_previousText, m_previousLength); 15268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_previousText = 0; 15278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_buffer.append(m_textIterator.characters(), m_textIterator.length()); 15298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 1530635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.range()->endOffset(), exception); 15318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 15328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint WordAwareIterator::length() const 15358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_buffer.isEmpty()) 15378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_buffer.size(); 15388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_previousText) 15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_previousLength; 15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_textIterator.length(); 15418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst UChar* WordAwareIterator::characters() const 15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 15458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_buffer.isEmpty()) 15468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_buffer.data(); 15478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_previousText) 15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_previousText; 15498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_textIterator.characters(); 15508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 15518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 15528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 15538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1554bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline UChar foldQuoteMarkOrSoftHyphen(UChar c) 15550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 15560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch (c) { 15570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case hebrewPunctuationGershayim: 15580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case leftDoubleQuotationMark: 15590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case rightDoubleQuotationMark: 15600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '"'; 15610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case hebrewPunctuationGeresh: 15620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case leftSingleQuotationMark: 15630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch case rightSingleQuotationMark: 15640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '\''; 1565bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case softHyphen: 1566bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Replace soft hyphen with an ignorable character so that their presence or absence will 1567bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // not affect string comparison. 1568bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return 0; 15690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch default: 15700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return c; 15710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 15720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 15730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1574bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline void foldQuoteMarksAndSoftHyphens(String& s) 15750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 15760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(hebrewPunctuationGeresh, '\''); 15770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(hebrewPunctuationGershayim, '"'); 15780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(leftDoubleQuotationMark, '"'); 15790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(leftSingleQuotationMark, '\''); 15800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(rightDoubleQuotationMark, '"'); 15810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch s.replace(rightSingleQuotationMark, '\''); 1582bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Replace soft hyphen with an ignorable character so that their presence or absence will 1583bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // not affect string comparison. 1584bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen s.replace(softHyphen, 0); 15850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 15860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1587635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION 1588635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1589bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenstatic inline void foldQuoteMarksAndSoftHyphens(UChar* data, size_t length) 15900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 15910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (size_t i = 0; i < length; ++i) 1592bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen data[i] = foldQuoteMarkOrSoftHyphen(data[i]); 15930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 15940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1595635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic const size_t minimumSearchBufferSize = 8192; 1596635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1597635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1598635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool searcherInUse; 1599635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1600635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1601635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic UStringSearch* createSearcher() 1602635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1603635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Provide a non-empty pattern and non-empty text so usearch_open will not fail, 1604635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // but it doesn't matter exactly what it is, since we don't perform any searches 1605635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // without setting both the pattern and the text. 1606635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 16070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch UStringSearch* searcher = usearch_open(&newlineCharacter, 1, &newlineCharacter, 1, currentSearchLocaleID(), 0, &status); 16080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING); 1609635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return searcher; 1610635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1611635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1612635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic UStringSearch* searcher() 1613635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1614635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project static UStringSearch* searcher = createSearcher(); 1615635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return searcher; 1616635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1617635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1618635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void lockSearcher() 1619635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1620635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1621635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!searcherInUse); 1622635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project searcherInUse = true; 1623635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1624635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1625635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1626635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline void unlockSearcher() 1627635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef NDEBUG 1629635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(searcherInUse); 1630635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project searcherInUse = false; 1631635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1632635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1633635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1634d0825bca7fe65beaee391d30da42e937db621564Steve Block// ICU's search ignores the distinction between small kana letters and ones 1635d0825bca7fe65beaee391d30da42e937db621564Steve Block// that are not small, and also characters that differ only in the voicing 1636d0825bca7fe65beaee391d30da42e937db621564Steve Block// marks when considering only primary collation strength diffrences. 1637d0825bca7fe65beaee391d30da42e937db621564Steve Block// This is not helpful for end users, since these differences make words 1638d0825bca7fe65beaee391d30da42e937db621564Steve Block// distinct, so for our purposes we need these to be considered. 1639d0825bca7fe65beaee391d30da42e937db621564Steve Block// The Unicode folks do not think the collation algorithm should be 1640d0825bca7fe65beaee391d30da42e937db621564Steve Block// changed. To work around this, we would like to tailor the ICU searcher, 1641d0825bca7fe65beaee391d30da42e937db621564Steve Block// but we can't get that to work yet. So instead, we check for cases where 1642d0825bca7fe65beaee391d30da42e937db621564Steve Block// these differences occur, and skip those matches. 1643d0825bca7fe65beaee391d30da42e937db621564Steve Block 1644d0825bca7fe65beaee391d30da42e937db621564Steve Block// We refer to the above technique as the "kana workaround". The next few 1645d0825bca7fe65beaee391d30da42e937db621564Steve Block// functions are helper functinos for the kana workaround. 1646d0825bca7fe65beaee391d30da42e937db621564Steve Block 1647d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isKanaLetter(UChar character) 1648d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1649d0825bca7fe65beaee391d30da42e937db621564Steve Block // Hiragana letters. 1650d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x3041 && character <= 0x3096) 1651d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1652d0825bca7fe65beaee391d30da42e937db621564Steve Block 1653d0825bca7fe65beaee391d30da42e937db621564Steve Block // Katakana letters. 1654d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x30A1 && character <= 0x30FA) 1655d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1656d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0x31F0 && character <= 0x31FF) 1657d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1658d0825bca7fe65beaee391d30da42e937db621564Steve Block 1659d0825bca7fe65beaee391d30da42e937db621564Steve Block // Halfwidth katakana letters. 1660d0825bca7fe65beaee391d30da42e937db621564Steve Block if (character >= 0xFF66 && character <= 0xFF9D && character != 0xFF70) 1661d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1662d0825bca7fe65beaee391d30da42e937db621564Steve Block 1663d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1664d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1665d0825bca7fe65beaee391d30da42e937db621564Steve Block 1666d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isSmallKanaLetter(UChar character) 1667d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1668d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(isKanaLetter(character)); 1669d0825bca7fe65beaee391d30da42e937db621564Steve Block 1670d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1671d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3041: // HIRAGANA LETTER SMALL A 1672d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3043: // HIRAGANA LETTER SMALL I 1673d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3045: // HIRAGANA LETTER SMALL U 1674d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3047: // HIRAGANA LETTER SMALL E 1675d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3049: // HIRAGANA LETTER SMALL O 1676d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3063: // HIRAGANA LETTER SMALL TU 1677d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3083: // HIRAGANA LETTER SMALL YA 1678d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3085: // HIRAGANA LETTER SMALL YU 1679d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3087: // HIRAGANA LETTER SMALL YO 1680d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x308E: // HIRAGANA LETTER SMALL WA 1681d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3095: // HIRAGANA LETTER SMALL KA 1682d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3096: // HIRAGANA LETTER SMALL KE 1683d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A1: // KATAKANA LETTER SMALL A 1684d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A3: // KATAKANA LETTER SMALL I 1685d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A5: // KATAKANA LETTER SMALL U 1686d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A7: // KATAKANA LETTER SMALL E 1687d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30A9: // KATAKANA LETTER SMALL O 1688d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C3: // KATAKANA LETTER SMALL TU 1689d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E3: // KATAKANA LETTER SMALL YA 1690d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E5: // KATAKANA LETTER SMALL YU 1691d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30E7: // KATAKANA LETTER SMALL YO 1692d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30EE: // KATAKANA LETTER SMALL WA 1693d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F5: // KATAKANA LETTER SMALL KA 1694d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F6: // KATAKANA LETTER SMALL KE 1695d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F0: // KATAKANA LETTER SMALL KU 1696d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F1: // KATAKANA LETTER SMALL SI 1697d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F2: // KATAKANA LETTER SMALL SU 1698d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F3: // KATAKANA LETTER SMALL TO 1699d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F4: // KATAKANA LETTER SMALL NU 1700d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F5: // KATAKANA LETTER SMALL HA 1701d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F6: // KATAKANA LETTER SMALL HI 1702d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F7: // KATAKANA LETTER SMALL HU 1703d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F8: // KATAKANA LETTER SMALL HE 1704d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31F9: // KATAKANA LETTER SMALL HO 1705d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FA: // KATAKANA LETTER SMALL MU 1706d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FB: // KATAKANA LETTER SMALL RA 1707d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FC: // KATAKANA LETTER SMALL RI 1708d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FD: // KATAKANA LETTER SMALL RU 1709d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FE: // KATAKANA LETTER SMALL RE 1710d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x31FF: // KATAKANA LETTER SMALL RO 1711d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF67: // HALFWIDTH KATAKANA LETTER SMALL A 1712d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF68: // HALFWIDTH KATAKANA LETTER SMALL I 1713d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF69: // HALFWIDTH KATAKANA LETTER SMALL U 1714d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6A: // HALFWIDTH KATAKANA LETTER SMALL E 1715d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6B: // HALFWIDTH KATAKANA LETTER SMALL O 1716d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6C: // HALFWIDTH KATAKANA LETTER SMALL YA 1717d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6D: // HALFWIDTH KATAKANA LETTER SMALL YU 1718d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6E: // HALFWIDTH KATAKANA LETTER SMALL YO 1719d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0xFF6F: // HALFWIDTH KATAKANA LETTER SMALL TU 1720d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1721d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1722d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1723d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1724d0825bca7fe65beaee391d30da42e937db621564Steve Block 1725d0825bca7fe65beaee391d30da42e937db621564Steve Blockenum VoicedSoundMarkType { NoVoicedSoundMark, VoicedSoundMark, SemiVoicedSoundMark }; 1726d0825bca7fe65beaee391d30da42e937db621564Steve Block 1727d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline VoicedSoundMarkType composedVoicedSoundMark(UChar character) 1728d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1729d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(isKanaLetter(character)); 1730d0825bca7fe65beaee391d30da42e937db621564Steve Block 1731d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1732d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x304C: // HIRAGANA LETTER GA 1733d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x304E: // HIRAGANA LETTER GI 1734d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3050: // HIRAGANA LETTER GU 1735d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3052: // HIRAGANA LETTER GE 1736d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3054: // HIRAGANA LETTER GO 1737d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3056: // HIRAGANA LETTER ZA 1738d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3058: // HIRAGANA LETTER ZI 1739d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305A: // HIRAGANA LETTER ZU 1740d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305C: // HIRAGANA LETTER ZE 1741d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x305E: // HIRAGANA LETTER ZO 1742d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3060: // HIRAGANA LETTER DA 1743d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3062: // HIRAGANA LETTER DI 1744d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3065: // HIRAGANA LETTER DU 1745d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3067: // HIRAGANA LETTER DE 1746d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3069: // HIRAGANA LETTER DO 1747d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3070: // HIRAGANA LETTER BA 1748d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3073: // HIRAGANA LETTER BI 1749d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3076: // HIRAGANA LETTER BU 1750d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3079: // HIRAGANA LETTER BE 1751d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307C: // HIRAGANA LETTER BO 1752d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3094: // HIRAGANA LETTER VU 1753d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30AC: // KATAKANA LETTER GA 1754d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30AE: // KATAKANA LETTER GI 1755d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B0: // KATAKANA LETTER GU 1756d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B2: // KATAKANA LETTER GE 1757d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B4: // KATAKANA LETTER GO 1758d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B6: // KATAKANA LETTER ZA 1759d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30B8: // KATAKANA LETTER ZI 1760d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BA: // KATAKANA LETTER ZU 1761d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BC: // KATAKANA LETTER ZE 1762d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30BE: // KATAKANA LETTER ZO 1763d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C0: // KATAKANA LETTER DA 1764d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C2: // KATAKANA LETTER DI 1765d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C5: // KATAKANA LETTER DU 1766d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C7: // KATAKANA LETTER DE 1767d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30C9: // KATAKANA LETTER DO 1768d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D0: // KATAKANA LETTER BA 1769d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D3: // KATAKANA LETTER BI 1770d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D6: // KATAKANA LETTER BU 1771d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D9: // KATAKANA LETTER BE 1772d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DC: // KATAKANA LETTER BO 1773d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F4: // KATAKANA LETTER VU 1774d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F7: // KATAKANA LETTER VA 1775d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F8: // KATAKANA LETTER VI 1776d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30F9: // KATAKANA LETTER VE 1777d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30FA: // KATAKANA LETTER VO 1778d0825bca7fe65beaee391d30da42e937db621564Steve Block return VoicedSoundMark; 1779d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3071: // HIRAGANA LETTER PA 1780d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3074: // HIRAGANA LETTER PI 1781d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3077: // HIRAGANA LETTER PU 1782d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307A: // HIRAGANA LETTER PE 1783d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x307D: // HIRAGANA LETTER PO 1784d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D1: // KATAKANA LETTER PA 1785d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D4: // KATAKANA LETTER PI 1786d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30D7: // KATAKANA LETTER PU 1787d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DA: // KATAKANA LETTER PE 1788d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x30DD: // KATAKANA LETTER PO 1789d0825bca7fe65beaee391d30da42e937db621564Steve Block return SemiVoicedSoundMark; 1790d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1791d0825bca7fe65beaee391d30da42e937db621564Steve Block return NoVoicedSoundMark; 1792d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1793d0825bca7fe65beaee391d30da42e937db621564Steve Block 1794d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool isCombiningVoicedSoundMark(UChar character) 1795d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1796d0825bca7fe65beaee391d30da42e937db621564Steve Block switch (character) { 1797d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x3099: // COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK 1798d0825bca7fe65beaee391d30da42e937db621564Steve Block case 0x309A: // COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK 1799d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1800d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1801d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1802d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1803d0825bca7fe65beaee391d30da42e937db621564Steve Block 1804d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool containsKanaLetters(const String& pattern) 1805d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1806d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* characters = pattern.characters(); 1807d0825bca7fe65beaee391d30da42e937db621564Steve Block unsigned length = pattern.length(); 1808d0825bca7fe65beaee391d30da42e937db621564Steve Block for (unsigned i = 0; i < length; ++i) { 1809d0825bca7fe65beaee391d30da42e937db621564Steve Block if (isKanaLetter(characters[i])) 1810d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1811d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1812d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1813d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1814d0825bca7fe65beaee391d30da42e937db621564Steve Block 1815d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic void normalizeCharacters(const UChar* characters, unsigned length, Vector<UChar>& buffer) 1816d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1817d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(length); 1818d0825bca7fe65beaee391d30da42e937db621564Steve Block 1819d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.resize(length); 1820d0825bca7fe65beaee391d30da42e937db621564Steve Block 1821d0825bca7fe65beaee391d30da42e937db621564Steve Block UErrorCode status = U_ZERO_ERROR; 1822d0825bca7fe65beaee391d30da42e937db621564Steve Block size_t bufferSize = unorm_normalize(characters, length, UNORM_NFC, 0, buffer.data(), length, &status); 1823d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_ZERO_ERROR || status == U_STRING_NOT_TERMINATED_WARNING || status == U_BUFFER_OVERFLOW_ERROR); 1824d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(bufferSize); 1825d0825bca7fe65beaee391d30da42e937db621564Steve Block 1826d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.resize(bufferSize); 1827d0825bca7fe65beaee391d30da42e937db621564Steve Block 1828d0825bca7fe65beaee391d30da42e937db621564Steve Block if (status == U_ZERO_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) 1829d0825bca7fe65beaee391d30da42e937db621564Steve Block return; 1830d0825bca7fe65beaee391d30da42e937db621564Steve Block 1831d0825bca7fe65beaee391d30da42e937db621564Steve Block status = U_ZERO_ERROR; 1832d0825bca7fe65beaee391d30da42e937db621564Steve Block unorm_normalize(characters, length, UNORM_NFC, 0, buffer.data(), bufferSize, &status); 1833d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); 1834d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1835d0825bca7fe65beaee391d30da42e937db621564Steve Block 1836f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic bool isNonLatin1Separator(UChar32 character) 1837f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1838f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT_ARG(character, character >= 256); 1839f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1840f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return U_GET_GC_MASK(character) & (U_GC_S_MASK | U_GC_P_MASK | U_GC_Z_MASK | U_GC_CF_MASK); 1841f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1842f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1843f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic inline bool isSeparator(UChar32 character) 1844f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1845f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch static const bool latin1SeparatorTable[256] = { 1846f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1847f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1848f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // space ! " # $ % & ' ( ) * + , - . / 1849f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // : ; < = > ? 1850f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // @ 1851f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, // [ \ ] ^ _ 1852f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ` 1853f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // { | } ~ 1854f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1855f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1856f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1857f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1858f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1859f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1860f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1861f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 1862f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch }; 1863f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1864f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (character < 256) 1865f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return latin1SeparatorTable[character]; 1866f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1867f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return isNonLatin1Separator(character); 1868f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1869f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1870f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline SearchBuffer::SearchBuffer(const String& target, FindOptions options) 1871635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project : m_target(target) 1872f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_options(options) 1873f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_prefixLength(0) 1874635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_atBreak(true) 1875f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_needsMoreContext(options & AtWordStarts) 1876d0825bca7fe65beaee391d30da42e937db621564Steve Block , m_targetRequiresKanaWorkaround(containsKanaLetters(m_target)) 1877635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1878635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!m_target.isEmpty()); 1879635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 18800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // FIXME: We'd like to tailor the searcher to fold quote marks for us instead 18810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // of doing it in a separate replacement pass here, but ICU doesn't offer a way 18820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // to add tailoring on top of the locale-specific tailoring as of this writing. 1883bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_target); 18840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t targetLength = m_target.length(); 18868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_buffer.reserveInitialCapacity(max(targetLength * 8, minimumSearchBufferSize)); 1887635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_overlap = m_buffer.capacity() / 4; 1888635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1889f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if ((m_options & AtWordStarts) && targetLength) { 1890f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 targetFirstCharacter; 1891f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_target.characters(), 0, 0, targetLength, targetFirstCharacter); 1892f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Characters in the separator category never really occur at the beginning of a word, 1893f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // so if the target begins with such a character, we just ignore the AtWordStart option. 1894f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isSeparator(targetFirstCharacter)) { 1895f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_options &= ~AtWordStarts; 1896f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_needsMoreContext = false; 1897f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 1898f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 1899f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1900635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Grab the single global searcher. 1901635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If we ever have a reason to do more than once search buffer at once, we'll have 1902635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to move to multiple searchers. 1903635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project lockSearcher(); 1904635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1905635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UStringSearch* searcher = WebCore::searcher(); 1906635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UCollator* collator = usearch_getCollator(searcher); 1907635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1908f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UCollationStrength strength = m_options & CaseInsensitive ? UCOL_PRIMARY : UCOL_TERTIARY; 1909635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (ucol_getStrength(collator) != strength) { 1910635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ucol_setStrength(collator, strength); 1911635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_reset(searcher); 1912635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 1913635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1914635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 1915635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_setPattern(searcher, m_target.characters(), targetLength, &status); 1916635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 1917d0825bca7fe65beaee391d30da42e937db621564Steve Block 1918d0825bca7fe65beaee391d30da42e937db621564Steve Block // The kana workaround requires a normalized copy of the target string. 1919d0825bca7fe65beaee391d30da42e937db621564Steve Block if (m_targetRequiresKanaWorkaround) 1920d0825bca7fe65beaee391d30da42e937db621564Steve Block normalizeCharacters(m_target.characters(), m_target.length(), m_normalizedTarget); 1921635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1922635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1923635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline SearchBuffer::~SearchBuffer() 1924635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1925635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unlockSearcher(); 1926635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1927635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1928635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::append(const UChar* characters, size_t length) 1929635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1930635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(length); 1931635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1932635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_atBreak) { 1933635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(0); 1934f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength = 0; 1935635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_atBreak = false; 1936635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (m_buffer.size() == m_buffer.capacity()) { 1937635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memcpy(m_buffer.data(), m_buffer.data() + m_buffer.size() - m_overlap, m_overlap * sizeof(UChar)); 1938f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min(m_prefixLength, m_buffer.size() - m_overlap); 1939635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(m_overlap); 1940635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 1941635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 19420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t oldLength = m_buffer.size(); 19430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t usableLength = min(m_buffer.capacity() - oldLength, length); 1944635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(usableLength); 1945635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.append(characters, usableLength); 1946bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_buffer.data() + oldLength, usableLength); 1947635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return usableLength; 1948635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1949635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1950f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::needsMoreContext() const 1951f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1952f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return m_needsMoreContext; 1953f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1954f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1955f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline void SearchBuffer::prependContext(const UChar* characters, size_t length) 1956f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 1957f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_needsMoreContext); 1958f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_prefixLength == m_buffer.size()); 1959f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1960f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!length) 1961f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 1962f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1963f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_atBreak = false; 1964f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1965f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t wordBoundaryContextStart = length; 1966f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (wordBoundaryContextStart) { 1967f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_BACK_1(characters, 0, wordBoundaryContextStart); 1968f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBoundaryContextStart = startOfLastWordBoundaryContext(characters, wordBoundaryContextStart); 1969f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 1970f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1971f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t usableLength = min(m_buffer.capacity() - m_prefixLength, length - wordBoundaryContextStart); 1972f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_buffer.prepend(characters + length - usableLength, usableLength); 1973f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength += usableLength; 1974f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1975f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (wordBoundaryContextStart || m_prefixLength == m_buffer.capacity()) 1976f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_needsMoreContext = false; 1977f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 1978f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1979635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline bool SearchBuffer::atBreak() const 1980635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1981635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return m_atBreak; 1982635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1983635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1984635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::reachedBreak() 1985635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1986635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_atBreak = true; 1987635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 1988635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1989d0825bca7fe65beaee391d30da42e937db621564Steve Blockinline bool SearchBuffer::isBadMatch(const UChar* match, size_t matchLength) const 1990d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1991d0825bca7fe65beaee391d30da42e937db621564Steve Block // This function implements the kana workaround. If usearch treats 1992d0825bca7fe65beaee391d30da42e937db621564Steve Block // it as a match, but we do not want to, then it's a "bad match". 1993d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!m_targetRequiresKanaWorkaround) 1994d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1995d0825bca7fe65beaee391d30da42e937db621564Steve Block 1996d0825bca7fe65beaee391d30da42e937db621564Steve Block // Normalize into a match buffer. We reuse a single buffer rather than 1997d0825bca7fe65beaee391d30da42e937db621564Steve Block // creating a new one each time. 1998d0825bca7fe65beaee391d30da42e937db621564Steve Block normalizeCharacters(match, matchLength, m_normalizedMatch); 1999d0825bca7fe65beaee391d30da42e937db621564Steve Block 2000d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* a = m_normalizedTarget.begin(); 2001d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* aEnd = m_normalizedTarget.end(); 2002d0825bca7fe65beaee391d30da42e937db621564Steve Block 2003d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* b = m_normalizedMatch.begin(); 2004d0825bca7fe65beaee391d30da42e937db621564Steve Block const UChar* bEnd = m_normalizedMatch.end(); 2005d0825bca7fe65beaee391d30da42e937db621564Steve Block 2006d0825bca7fe65beaee391d30da42e937db621564Steve Block while (true) { 2007d0825bca7fe65beaee391d30da42e937db621564Steve Block // Skip runs of non-kana-letter characters. This is necessary so we can 2008d0825bca7fe65beaee391d30da42e937db621564Steve Block // correctly handle strings where the target and match have different-length 2009d0825bca7fe65beaee391d30da42e937db621564Steve Block // runs of characters that match, while still double checking the correctness 2010d0825bca7fe65beaee391d30da42e937db621564Steve Block // of matches of kana letters with other kana letters. 2011d0825bca7fe65beaee391d30da42e937db621564Steve Block while (a != aEnd && !isKanaLetter(*a)) 2012d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2013d0825bca7fe65beaee391d30da42e937db621564Steve Block while (b != bEnd && !isKanaLetter(*b)) 2014d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2015d0825bca7fe65beaee391d30da42e937db621564Steve Block 2016d0825bca7fe65beaee391d30da42e937db621564Steve Block // If we reached the end of either the target or the match, we should have 2017d0825bca7fe65beaee391d30da42e937db621564Steve Block // reached the end of both; both should have the same number of kana letters. 2018d0825bca7fe65beaee391d30da42e937db621564Steve Block if (a == aEnd || b == bEnd) { 2019d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(a == aEnd); 2020d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(b == bEnd); 2021d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 2022d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2023d0825bca7fe65beaee391d30da42e937db621564Steve Block 2024d0825bca7fe65beaee391d30da42e937db621564Steve Block // Check for differences in the kana letter character itself. 2025d0825bca7fe65beaee391d30da42e937db621564Steve Block if (isSmallKanaLetter(*a) != isSmallKanaLetter(*b)) 2026d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2027d0825bca7fe65beaee391d30da42e937db621564Steve Block if (composedVoicedSoundMark(*a) != composedVoicedSoundMark(*b)) 2028d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2029d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2030d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2031d0825bca7fe65beaee391d30da42e937db621564Steve Block 2032d0825bca7fe65beaee391d30da42e937db621564Steve Block // Check for differences in combining voiced sound marks found after the letter. 2033d0825bca7fe65beaee391d30da42e937db621564Steve Block while (1) { 2034d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!(a != aEnd && isCombiningVoicedSoundMark(*a))) { 2035d0825bca7fe65beaee391d30da42e937db621564Steve Block if (b != bEnd && isCombiningVoicedSoundMark(*b)) 2036d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2037d0825bca7fe65beaee391d30da42e937db621564Steve Block break; 2038d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2039d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!(b != bEnd && isCombiningVoicedSoundMark(*b))) 2040d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2041d0825bca7fe65beaee391d30da42e937db621564Steve Block if (*a != *b) 2042d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 2043d0825bca7fe65beaee391d30da42e937db621564Steve Block ++a; 2044d0825bca7fe65beaee391d30da42e937db621564Steve Block ++b; 2045d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2046d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2047d0825bca7fe65beaee391d30da42e937db621564Steve Block} 2048d0825bca7fe65beaee391d30da42e937db621564Steve Block 2049f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::isWordStartMatch(size_t start, size_t length) const 2050f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2051f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(m_options & AtWordStarts); 2052f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2053f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!start) 2054f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2055f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2056f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_options & TreatMedialCapitalAsWordStart) { 2057f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int size = m_buffer.size(); 2058f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int offset = start; 2059f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 firstCharacter; 2060f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_buffer.data(), 0, offset, size, firstCharacter); 2061f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 previousCharacter; 2062f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_PREV(m_buffer.data(), 0, offset, previousCharacter); 2063f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2064f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isSeparator(firstCharacter)) { 2065f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a separator run is a word start (".org" in "webkit.org"). 2066f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isSeparator(previousCharacter)) 2067f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2068f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isASCIIUpper(firstCharacter)) { 2069f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of an uppercase run is a word start ("Kit" in "WebKit"). 2070f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIUpper(previousCharacter)) 2071f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2072f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The last character of an uppercase run followed by a non-separator, non-digit 2073f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // is a word start ("Request" in "XMLHTTPRequest"). 2074f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch offset = start; 2075f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_FWD_1(m_buffer.data(), offset, size); 2076f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 nextCharacter = 0; 2077f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (offset < size) 2078f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_GET(m_buffer.data(), 0, offset, size, nextCharacter); 2079f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIUpper(nextCharacter) && !isASCIIDigit(nextCharacter) && !isSeparator(nextCharacter)) 2080f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2081f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isASCIIDigit(firstCharacter)) { 2082f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a digit run is a word start ("2" in "WebKit2"). 2083f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!isASCIIDigit(previousCharacter)) 2084f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2085f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (isSeparator(previousCharacter) || isASCIIDigit(previousCharacter)) { 2086f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The start of a non-separator, non-uppercase, non-digit run is a word start, 2087f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // except after an uppercase. ("org" in "webkit.org", but not "ore" in "WebCore"). 2088f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 2089f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2090f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2091f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2092f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t wordBreakSearchStart = start + length; 2093f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch while (wordBreakSearchStart > start) 2094f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBreakSearchStart = findNextWordFromIndex(m_buffer.data(), m_buffer.size(), wordBreakSearchStart, false /* backwards */); 2095f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return wordBreakSearchStart == start; 2096f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2097f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2098635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::search(size_t& start) 2099635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t size = m_buffer.size(); 2101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_atBreak) { 2102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!size) 2103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 2105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (size != m_buffer.capacity()) 2106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UStringSearch* searcher = WebCore::searcher(); 2110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UErrorCode status = U_ZERO_ERROR; 2112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project usearch_setText(searcher, m_buffer.data(), size, &status); 2113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 2114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch usearch_setOffset(searcher, m_prefixLength, &status); 2116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(status == U_ZERO_ERROR); 2117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int matchStart = usearch_next(searcher, &status); 2119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(status == U_ZERO_ERROR); 2120d0825bca7fe65beaee391d30da42e937db621564Steve Block 2121d0825bca7fe65beaee391d30da42e937db621564Steve BlocknextMatch: 2122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!(matchStart >= 0 && static_cast<size_t>(matchStart) < size)) { 2123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(matchStart == USEARCH_DONE); 2124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Matches that start in the overlap area are only tentative. 2128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // The same match may appear later, matching more characters, 2129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // possibly including a combining character that's not yet in the buffer. 2130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_atBreak && static_cast<size_t>(matchStart) >= size - m_overlap) { 2131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t overlap = m_overlap; 2132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_options & AtWordStarts) { 2133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Ensure that there is sufficient context before matchStart the next time around for 2134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // determining if it is at a word boundary. 2135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int wordBoundaryContextStart = matchStart; 2136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch U16_BACK_1(m_buffer.data(), 0, wordBoundaryContextStart); 2137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wordBoundaryContextStart = startOfLastWordBoundaryContext(m_buffer.data(), wordBoundaryContextStart); 2138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch overlap = min(size - 1, max(overlap, size - wordBoundaryContextStart)); 2139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch memcpy(m_buffer.data(), m_buffer.data() + size - overlap, overlap * sizeof(UChar)); 2141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min(m_prefixLength, size - overlap); 2142f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_buffer.shrink(overlap); 2143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2146d0825bca7fe65beaee391d30da42e937db621564Steve Block size_t matchedLength = usearch_getMatchedLength(searcher); 2147d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(matchStart + matchedLength <= size); 2148d0825bca7fe65beaee391d30da42e937db621564Steve Block 2149d0825bca7fe65beaee391d30da42e937db621564Steve Block // If this match is "bad", move on to the next match. 2150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (isBadMatch(m_buffer.data() + matchStart, matchedLength) || ((m_options & AtWordStarts) && !isWordStartMatch(matchStart, matchedLength))) { 2151d0825bca7fe65beaee391d30da42e937db621564Steve Block matchStart = usearch_next(searcher, &status); 2152d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(status == U_ZERO_ERROR); 2153d0825bca7fe65beaee391d30da42e937db621564Steve Block goto nextMatch; 2154d0825bca7fe65beaee391d30da42e937db621564Steve Block } 2155d0825bca7fe65beaee391d30da42e937db621564Steve Block 2156635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t newSize = size - (matchStart + 1); 2157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project memmove(m_buffer.data(), m_buffer.data() + matchStart + 1, newSize * sizeof(UChar)); 2158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_prefixLength -= min<size_t>(m_prefixLength, matchStart + 1); 2159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_buffer.shrink(newSize); 2160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start = size - matchStart; 2162d0825bca7fe65beaee391d30da42e937db621564Steve Block return matchedLength; 2163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else // !ICU_UNICODE 2166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline SearchBuffer::SearchBuffer(const String& target, FindOptions options) 2168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch : m_target(options & CaseInsensitive ? target.foldCase() : target) 2169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_options(options) 2170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_buffer(m_target.length()) 21718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_isCharacterStartBuffer(m_target.length()) 21728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_isBufferFull(false) 21738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_cursor(0) 21748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 21758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_target.isEmpty()); 21768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_target.replace(noBreakSpace, ' '); 2177bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen foldQuoteMarksAndSoftHyphens(m_target); 21788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 21798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline SearchBuffer::~SearchBuffer() 21818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::reachedBreak() 2185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_cursor = 0; 2187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_isBufferFull = false; 2188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2189635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2190635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline bool SearchBuffer::atBreak() const 2191635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return !m_cursor && !m_isBufferFull; 2193635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2195635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void SearchBuffer::append(UChar c, bool isStart) 2196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2197bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_buffer[m_cursor] = c == noBreakSpace ? ' ' : foldQuoteMarkOrSoftHyphen(c); 21988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isCharacterStartBuffer[m_cursor] = isStart; 21998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (++m_cursor == m_target.length()) { 22008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_cursor = 0; 22018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isBufferFull = true; 22028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 22038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::append(const UChar* characters, size_t length) 22068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(length); 2208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!(m_options & CaseInsensitive)) { 2209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project append(characters[0], true); 2210635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 1; 22118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 22128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const int maxFoldedCharacters = 16; // sensible maximum is 3, this should be more than enough 22138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar foldedCharacters[maxFoldedCharacters]; 22148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool error; 2215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int numFoldedCharacters = foldCase(foldedCharacters, maxFoldedCharacters, characters, 1, &error); 22168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!error); 22178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(numFoldedCharacters); 22188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(numFoldedCharacters <= maxFoldedCharacters); 22198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!error && numFoldedCharacters) { 22208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project numFoldedCharacters = min(numFoldedCharacters, maxFoldedCharacters); 22218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(foldedCharacters[0], true); 22228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 1; i < numFoldedCharacters; ++i) 22238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project append(foldedCharacters[i], false); 22248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 1; 22268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline bool SearchBuffer::needsMoreContext() const 2229f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2230f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 2231f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid SearchBuffer::prependContext(const UChar*, size_t) 2234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2235f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT_NOT_REACHED(); 2236f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2237f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline size_t SearchBuffer::search(size_t& start) 22398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 22408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isBufferFull) 2241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 22428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_isCharacterStartBuffer[m_cursor]) 2243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t tailSpace = m_target.length() - m_cursor; 2246635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (memcmp(&m_buffer[m_cursor], m_target.characters(), tailSpace * sizeof(UChar)) != 0) 2247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (memcmp(&m_buffer[0], m_target.characters() + tailSpace, m_cursor * sizeof(UChar)) != 0) 2249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 2250635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project start = length(); 2252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Now that we've found a match once, we don't want to find it again, because those 2254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // are the SearchBuffer semantics, allowing for a buffer where you append more than one 2255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // character at a time. To do this we take advantage of m_isCharacterStartBuffer, but if 2256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // we want to get rid of that in the future we could track this with a separate boolean 2257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // or even move the characters to the start of the buffer and set m_isBufferFull to false. 2258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_isCharacterStartBuffer[m_cursor] = false; 22598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2260635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return start; 22618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the number of characters that were appended to the buffer (what we are searching in). 22648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// That's not necessarily the same length as the passed-in target string, because case folding 22658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// can make two strings match even though they're not the same length. 2266635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectsize_t SearchBuffer::length() const 22678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2268635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t bufferSize = m_target.length(); 2269635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t length = 0; 2270635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (size_t i = 0; i < bufferSize; ++i) 22718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length += m_isCharacterStartBuffer[i]; 22728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return length; 22738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2275635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif // !ICU_UNICODE 2276635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 22778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 22788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint TextIterator::rangeLength(const Range* r, bool forSelectionPreservation) 22808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 22818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int length = 0; 228221939df44de1705786c545cd1bf519d47250322dBen Murdoch for (TextIterator it(r, forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); !it.atEnd(); it.advance()) 22838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length += it.length(); 22848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return length; 22868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> TextIterator::subrange(Range* entireRange, int characterOffset, int characterCount) 22898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CharacterIterator entireRangeIterator(entireRange); 2291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return characterSubrange(entireRangeIterator, characterOffset, characterCount); 22928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 22938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<Range> TextIterator::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, bool forSelectionPreservation) 22958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 22968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> resultRange = scope->document()->createRange(); 22978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 22988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int docTextPosition = 0; 22998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int rangeEnd = rangeLocation + rangeLength; 23008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool startRangeFound = false; 23018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> textRunRange; 23038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 230421939df44de1705786c545cd1bf519d47250322dBen Murdoch TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); 23058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>. 23078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLocation == 0 && rangeLength == 0 && it.atEnd()) { 23088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textRunRange = it.range(); 23098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ExceptionCode ec = 0; 2311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), 0, ec); 2312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), 0, ec); 2314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 23158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return resultRange.release(); 23178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (; !it.atEnd(); it.advance()) { 23208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int len = it.length(); 23218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textRunRange = it.range(); 23228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool foundStart = rangeLocation >= docTextPosition && rangeLocation <= docTextPosition + len; 23248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool foundEnd = rangeEnd >= docTextPosition && rangeEnd <= docTextPosition + len; 23258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Fix textRunRange->endPosition(), but only if foundStart || foundEnd, because it is only 23278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // in those cases that textRunRange is used. 2328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (foundEnd) { 23298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This is a workaround for the fact that the end of a run is often at the wrong 23308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // position for emitted '\n's. 2331635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (len == 1 && it.characters()[0] == '\n') { 2332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block scope->document()->updateLayoutIgnorePendingStylesheets(); 2333dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block it.advance(); 2334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!it.atEnd()) { 2335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RefPtr<Range> range = it.range(); 23368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec = 0; 2337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block textRunRange->setEnd(range->startContainer(), range->startOffset(), ec); 2338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2339dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 2340dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Position runStart = textRunRange->startPosition(); 2341dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Position runEnd = VisiblePosition(runStart).next().deepEquivalent(); 2342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (runEnd.isNotNull()) { 2343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ExceptionCode ec = 0; 2344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block textRunRange->setEnd(runEnd.node(), runEnd.deprecatedEditingOffset(), ec); 2345dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(!ec); 2346dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 23478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (foundStart) { 23528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startRangeFound = true; 23538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2354635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (textRunRange->startContainer()->isTextNode()) { 23558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = rangeLocation - docTextPosition; 2356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), offset + textRunRange->startOffset(), exception); 23578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 23588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLocation == docTextPosition) 2359635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->startContainer(), textRunRange->startOffset(), exception); 23608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2361635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setStart(textRunRange->endContainer(), textRunRange->endOffset(), exception); 23628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (foundEnd) { 23668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (textRunRange->startContainer()->isTextNode()) { 23688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = rangeEnd - docTextPosition; 2369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), offset + textRunRange->startOffset(), exception); 23708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 23718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeEnd == docTextPosition) 2372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->startContainer(), textRunRange->startOffset(), exception); 23738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2374635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset(), exception); 23758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project docTextPosition += len; 23778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 23788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project docTextPosition += len; 23808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!startRangeFound) 23838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 23848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (rangeLength != 0 && rangeEnd > docTextPosition) { // rangeEnd is out of bounds 23868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 2387635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset(), exception); 23888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 23898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return resultRange.release(); 23918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 23928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// -------- 23948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 239568513a70bcd92384395513322f1b801e7bf9c729Steve BlockUChar* plainTextToMallocAllocatedBuffer(const Range* r, unsigned& bufferLength, bool isDisplayString, TextIteratorBehavior defaultBehavior) 23968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 23978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* result = 0; 23988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 23998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Do this in pieces to avoid massive reallocations if there is a large amount of text. 24008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The 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. 24018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static const unsigned cMaxSegmentSize = 1 << 16; 24028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferLength = 0; 24038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project typedef pair<UChar*, unsigned> TextSegment; 2404e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block OwnPtr<Vector<TextSegment> > textSegments; 24058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<UChar> textBuffer; 24068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian textBuffer.reserveInitialCapacity(cMaxSegmentSize); 240768513a70bcd92384395513322f1b801e7bf9c729Steve Block TextIteratorBehavior behavior = defaultBehavior; 240868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!isDisplayString) 240968513a70bcd92384395513322f1b801e7bf9c729Steve Block behavior = static_cast<TextIteratorBehavior>(behavior | TextIteratorEmitsTextsWithoutTranscoding); 241068513a70bcd92384395513322f1b801e7bf9c729Steve Block 241168513a70bcd92384395513322f1b801e7bf9c729Steve Block for (TextIterator it(r, behavior); !it.atEnd(); it.advance()) { 24128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textBuffer.size() && textBuffer.size() + it.length() > cMaxSegmentSize) { 24138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* newSegmentBuffer = static_cast<UChar*>(malloc(textBuffer.size() * sizeof(UChar))); 24148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!newSegmentBuffer) 24158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto exit; 24168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(newSegmentBuffer, textBuffer.data(), textBuffer.size() * sizeof(UChar)); 24178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!textSegments) 2418e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block textSegments = adoptPtr(new Vector<TextSegment>); 24198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textSegments->append(make_pair(newSegmentBuffer, (unsigned)textBuffer.size())); 24208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textBuffer.clear(); 24218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project textBuffer.append(it.characters(), it.length()); 24238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bufferLength += it.length(); 24248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!bufferLength) 24278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 24288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Since we know the size now, we can make a single buffer out of the pieces with one big alloc 24308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result = static_cast<UChar*>(malloc(bufferLength * sizeof(UChar))); 24318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!result) 24328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto exit; 24338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 24358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar* resultPos = result; 24368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textSegments) { 24378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned size = textSegments->size(); 24388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < size; ++i) { 24398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const TextSegment& segment = textSegments->at(i); 24408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(resultPos, segment.first, segment.second * sizeof(UChar)); 24418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project resultPos += segment.second; 24428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memcpy(resultPos, textBuffer.data(), textBuffer.size() * sizeof(UChar)); 24458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 24468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 24478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectexit: 24488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (textSegments) { 24498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned size = textSegments->size(); 24508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < size; ++i) 24518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project free(textSegments->at(i).first); 24528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2453635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isDisplayString && r->ownerDocument()) 2455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r->ownerDocument()->displayBufferModifiedByEncoding(result, bufferLength); 2456635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 24578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return result; 24588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 24598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 246068513a70bcd92384395513322f1b801e7bf9c729Steve BlockString plainText(const Range* r, TextIteratorBehavior defaultBehavior) 24618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 24628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned length; 246368513a70bcd92384395513322f1b801e7bf9c729Steve Block UChar* buf = plainTextToMallocAllocatedBuffer(r, length, false, defaultBehavior); 24648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!buf) 24658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ""; 24668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String result(buf, length); 24678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project free(buf); 24688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return result; 24698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 24708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline bool isAllCollapsibleWhitespace(const String& string) 24728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2473635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const UChar* characters = string.characters(); 2474635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned length = string.length(); 2475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (unsigned i = 0; i < length; ++i) { 2476635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!isCollapsibleWhitespace(characters[i])) 2477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return false; 2478635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2479635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return true; 2480635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 24818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2482635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PassRefPtr<Range> collapsedToBoundary(const Range* range, bool forward) 2483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 24848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec = 0; 24858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> result = range->cloneRange(ec); 2486635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 24878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result->collapse(!forward, ec); 2488635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!ec); 2489635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return result.release(); 2490635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 24918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2492f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic size_t findPlainText(CharacterIterator& it, const String& target, FindOptions options, size_t& matchStart) 2493635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2494635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchStart = 0; 2495635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchLength = 0; 2496635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2497f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch SearchBuffer buffer(target, options); 2498f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2499f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (buffer.needsMoreContext()) { 2500f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RefPtr<Range> startRange = it.range(); 2501f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RefPtr<Range> beforeStartRange = startRange->ownerDocument()->createRange(); 2502f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ExceptionCode ec = 0; 2503f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch beforeStartRange->setEnd(startRange->startContainer(), startRange->startOffset(), ec); 2504f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (SimplifiedBackwardsTextIterator backwardsIterator(beforeStartRange.get()); !backwardsIterator.atEnd(); backwardsIterator.advance()) { 2505f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch buffer.prependContext(backwardsIterator.characters(), backwardsIterator.length()); 2506f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!buffer.needsMoreContext()) 2507f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch break; 2508f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2509f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 2510635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2511635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (!it.atEnd()) { 2512635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(buffer.append(it.characters(), it.length())); 2513635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjecttryAgain: 2514635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchStartOffset; 2515635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (size_t newMatchLength = buffer.search(matchStartOffset)) { 2516635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Note that we found a match, and where we found it. 2517635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t lastCharacterInBufferOffset = it.characterOffset(); 2518635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(lastCharacterInBufferOffset >= matchStartOffset); 2519635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchStart = lastCharacterInBufferOffset - matchStartOffset; 2520635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project matchLength = newMatchLength; 2521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If searching forward, stop on the first match. 2522635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // If searching backward, don't stop, so we end up with the last match. 2523f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!(options & Backwards)) 2524635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 2525635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto tryAgain; 2526635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 2527635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (it.atBreak() && !buffer.atBreak()) { 2528635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project buffer.reachedBreak(); 2529635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto tryAgain; 25308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2533635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return matchLength; 2534635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 2535635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2536635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<Range> findPlainText(const Range* range, const String& target, bool forward, bool caseSensitive) 2537635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2538f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return findPlainText(range, target, (forward ? 0 : Backwards) | (caseSensitive ? 0 : CaseInsensitive)); 2539f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 2540f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2541f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochPassRefPtr<Range> findPlainText(const Range* range, const String& target, FindOptions options) 2542f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 2543635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // First, find the text. 2544635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchStart; 2545635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project size_t matchLength; 2546635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project { 254721939df44de1705786c545cd1bf519d47250322dBen Murdoch CharacterIterator findIterator(range, TextIteratorEntersTextControls); 2548f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch matchLength = findPlainText(findIterator, target, options, matchStart); 2549635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!matchLength) 2550f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return collapsedToBoundary(range, !(options & Backwards)); 25518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 25528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2553635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Then, find the document position of the start and the end of the text. 255421939df44de1705786c545cd1bf519d47250322dBen Murdoch CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls); 2555635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return characterSubrange(computeRangeIterator, matchStart, matchLength); 25568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 25578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 25588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2559