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