WebCore:
[WebKit-https.git] / WebCore / editing / TextIterator.h
1 /*
2  * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef TextIterator_h
27 #define TextIterator_h
28
29 #include "DeprecatedString.h"
30 #include "InlineTextBox.h"
31 #include "Range.h"
32 #include <wtf/Vector.h>
33
34 namespace WebCore {
35
36 // FIXME: Can't really answer this question correctly without knowing the white-space mode.
37 // FIXME: Move this along with the white-space position functions above
38 // somewhere else in the editing directory. It doesn't belong here.
39 inline bool isCollapsibleWhitespace(UChar c)
40 {
41     switch (c) {
42         case ' ':
43         case '\n':
44             return true;
45         default:
46             return false;
47     }
48 }
49
50 DeprecatedString plainText(const Range*);
51 UChar* plainTextToMallocAllocatedBuffer(const Range*, unsigned& bufferLength);
52 PassRefPtr<Range> findPlainText(const Range*, const String&, bool forward, bool caseSensitive);
53
54 // Iterates through the DOM range, returning all the text, and 0-length boundaries
55 // at points where replaced elements break up the text flow.  The text comes back in
56 // chunks so as to optimize for performance of the iteration.
57
58 class TextIterator
59 {
60 public:
61     TextIterator();
62     explicit TextIterator(const Range*, bool emitForReplacedElements = false);
63     
64     bool atEnd() const { return !m_positionNode; }
65     void advance();
66     
67     int length() const { return m_textLength; }
68     const UChar* characters() const { return m_textCharacters; }
69     
70     PassRefPtr<Range> range() const;
71      
72     static int rangeLength(const Range*, bool spacesForReplacedElements = false);
73     static PassRefPtr<Range> rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, bool spacesForReplacedElements = false);
74     static PassRefPtr<Range> subrange(Range* entireRange, int characterOffset, int characterCount);
75     
76 private:
77     void exitNode();
78     bool shouldRepresentNodeOffsetZero();
79     bool shouldEmitSpaceBeforeAndAfterNode(Node*);
80     void representNodeOffsetZero();
81     bool handleTextNode();
82     bool handleReplacedElement();
83     bool handleNonTextNode();
84     void handleTextBox();
85     void emitCharacter(UChar, Node *textNode, Node *offsetBaseNode, int textStartOffset, int textEndOffset);
86     void emitText(Node *textNode, int textStartOffset, int textEndOffset);
87     
88     // Current position, not necessarily of the text being returned, but position
89     // as we walk through the DOM tree.
90     Node *m_node;
91     int m_offset;
92     bool m_handledNode;
93     bool m_handledChildren;
94     
95     // The range.
96     Node *m_startContainer;
97     int m_startOffset;
98     Node *m_endContainer;
99     int m_endOffset;
100     Node *m_pastEndNode;
101     
102     // The current text and its position, in the form to be returned from the iterator.
103     Node *m_positionNode;
104     mutable Node *m_positionOffsetBaseNode;
105     mutable int m_positionStartOffset;
106     mutable int m_positionEndOffset;
107     const UChar* m_textCharacters;
108     int m_textLength;
109     
110     // Used when there is still some pending text from the current node; when these
111     // are false and 0, we go back to normal iterating.
112     bool m_needAnotherNewline;
113     InlineTextBox *m_textBox;
114     
115     // Used to do the whitespace collapsing logic.
116     Node *m_lastTextNode;    
117     bool m_lastTextNodeEndedWithCollapsedSpace;
118     UChar m_lastCharacter;
119     
120     // Used for whitespace characters that aren't in the DOM, so we can point at them.
121     UChar m_singleCharacterBuffer;
122     
123     // Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text)
124     Vector<InlineTextBox*> m_sortedTextBoxes;
125     size_t m_sortedTextBoxesPosition;
126     
127     // Used when deciding whether to emit a "positioning" (e.g. newline) before any other content
128     bool m_haveEmitted;
129     
130     // Used by selection preservation code.  There should be one character emitted between every VisiblePosition
131     // in the Range used to create the TextIterator.
132     bool m_emitForSelectionPreservation;
133 };
134
135 // Iterates through the DOM range, returning all the text, and 0-length boundaries
136 // at points where replaced elements break up the text flow.  The text comes back in
137 // chunks so as to optimize for performance of the iteration.
138 class SimplifiedBackwardsTextIterator
139 {
140 public:
141     SimplifiedBackwardsTextIterator();
142     explicit SimplifiedBackwardsTextIterator(const Range *);
143     
144     bool atEnd() const { return !m_positionNode; }
145     void advance();
146     
147     int length() const { return m_textLength; }
148     const UChar* characters() const { return m_textCharacters; }
149     
150     PassRefPtr<Range> range() const;
151         
152 private:
153     void exitNode();
154     bool handleTextNode();
155     bool handleReplacedElement();
156     bool handleNonTextNode();
157     void emitCharacter(UChar, Node *Node, int startOffset, int endOffset);
158     
159     // Current position, not necessarily of the text being returned, but position
160     // as we walk through the DOM tree.
161     Node* m_node;
162     int m_offset;
163     bool m_handledNode;
164     bool m_handledChildren;
165     
166     // End of the range.
167     Node* m_startNode;
168     int m_startOffset;
169     // Start of the range.
170     Node* m_endNode;
171     int m_endOffset;
172     
173     // The current text and its position, in the form to be returned from the iterator.
174     Node* m_positionNode;
175     int m_positionStartOffset;
176     int m_positionEndOffset;
177     const UChar* m_textCharacters;
178     int m_textLength;
179
180     // Used to do the whitespace logic.
181     Node* m_lastTextNode;    
182     UChar m_lastCharacter;
183     
184     // Used for whitespace characters that aren't in the DOM, so we can point at them.
185     UChar m_singleCharacterBuffer;
186     
187     // The node after the last node this iterator should process.
188     Node* m_pastStartNode;
189 };
190
191 // Builds on the text iterator, adding a character position so we can walk one
192 // character at a time, or faster, as needed. Useful for searching.
193 class CharacterIterator {
194 public:
195     CharacterIterator();
196     explicit CharacterIterator(const Range* r, bool emitForReplacedElements = false);
197     
198     void advance(int numCharacters);
199     
200     bool atBreak() const { return m_atBreak; }
201     bool atEnd() const { return m_textIterator.atEnd(); }
202     
203     int length() const { return m_textIterator.length() - m_runOffset; }
204     const UChar* characters() const { return m_textIterator.characters() + m_runOffset; }
205     DeprecatedString string(int numChars);
206     
207     int characterOffset() const { return m_offset; }
208     PassRefPtr<Range> range() const;
209         
210 private:
211     int m_offset;
212     int m_runOffset;
213     bool m_atBreak;
214     
215     TextIterator m_textIterator;
216 };
217     
218 // Very similar to the TextIterator, except that the chunks of text returned are "well behaved",
219 // meaning they never end split up a word.  This is useful for spellcheck or (perhaps one day) searching.
220 class WordAwareIterator {
221 public:
222     WordAwareIterator();
223     explicit WordAwareIterator(const Range *r);
224
225     bool atEnd() const { return !m_didLookAhead && m_textIterator.atEnd(); }
226     void advance();
227     
228     int length() const;
229     const UChar* characters() const;
230     
231     // Range of the text we're currently returning
232     PassRefPtr<Range> range() const { return m_range; }
233
234 private:
235     // text from the previous chunk from the textIterator
236     const UChar* m_previousText;
237     int m_previousLength;
238
239     // many chunks from textIterator concatenated
240     DeprecatedString m_buffer;
241     
242     // Did we have to look ahead in the textIterator to confirm the current chunk?
243     bool m_didLookAhead;
244
245     RefPtr<Range> m_range;
246
247     TextIterator m_textIterator;
248 };
249
250 }
251
252 #endif