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