Rename TextBreakIteratorWinCE to TextBreakIteratorWchar
[WebKit-https.git] / Source / WebCore / platform / text / wchar / TextBreakIteratorWchar.cpp
1 /*
2  * Copyright (C) 2006 Lars Knoll <lars@trolltech.com>
3  * Copyright (C) 2007-2009 Torch Mobile, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "TextBreakIterator.h"
24
25 #include <wtf/Atomics.h>
26 #include <wtf/StdLibExtras.h>
27 #include <wtf/text/WTFString.h>
28 #include <wtf/unicode/Unicode.h>
29
30 using namespace WTF;
31 using namespace WTF::Unicode;
32 using namespace std;
33
34 namespace WebCore {
35
36 // Hack, not entirely correct
37 static inline bool isCharStop(UChar c)
38 {
39     CharCategory charCategory = category(c);
40     return charCategory != Mark_NonSpacing && (charCategory != Other_Surrogate || (c < 0xd800 || c >= 0xdc00));
41 }
42
43 static inline bool isLineStop(UChar c)
44 {
45     return category(c) != Separator_Line;
46 }
47
48 static inline bool isSentenceStop(UChar c)
49 {
50     return isPunct(c);
51 }
52
53 class TextBreakIterator {
54 public:
55     void reset(const UChar* str, int len)
56     {
57         string = str;
58         length = len;
59         currentPos = 0;
60     }
61     int first()
62     {
63         currentPos = 0;
64         return currentPos;
65     }
66     int last()
67     {
68         currentPos = length;
69         return currentPos;
70     }
71     virtual int next() = 0;
72     virtual int previous() = 0;
73     int following(int position)
74     {
75         currentPos = position;
76         return next();
77     }
78     int preceding(int position)
79     {
80         currentPos = position;
81         return previous();
82     }
83
84     int currentPos;
85     const UChar* string;
86     int length;
87 };
88
89 struct WordBreakIterator: TextBreakIterator {
90     virtual int next();
91     virtual int previous();
92 };
93
94 struct CharBreakIterator: TextBreakIterator {
95     virtual int next();
96     virtual int previous();
97 };
98
99 struct LineBreakIterator: TextBreakIterator {
100     virtual int next();
101     virtual int previous();
102 };
103
104 struct SentenceBreakIterator : TextBreakIterator {
105     virtual int next();
106     virtual int previous();
107 };
108
109 int WordBreakIterator::next()
110 {
111     if (currentPos == length) {
112         currentPos = -1;
113         return currentPos;
114     }
115     bool haveSpace = false;
116     while (currentPos < length) {
117         if (haveSpace && !isSpace(string[currentPos]))
118             break;
119         if (isSpace(string[currentPos]))
120             haveSpace = true;
121         ++currentPos;
122     }
123     return currentPos;
124 }
125
126 int WordBreakIterator::previous()
127 {
128     if (!currentPos) {
129         currentPos = -1;
130         return currentPos;
131     }
132     bool haveSpace = false;
133     while (currentPos > 0) {
134         if (haveSpace && !isSpace(string[currentPos]))
135             break;
136         if (isSpace(string[currentPos]))
137             haveSpace = true;
138         --currentPos;
139     }
140     return currentPos;
141 }
142
143 int CharBreakIterator::next()
144 {
145     if (currentPos >= length)
146         return -1;
147     ++currentPos;
148     while (currentPos < length && !isCharStop(string[currentPos]))
149         ++currentPos;
150     return currentPos;
151 }
152
153 int CharBreakIterator::previous()
154 {
155     if (currentPos <= 0)
156         return -1;
157     if (currentPos > length)
158         currentPos = length;
159     --currentPos;
160     while (currentPos > 0 && !isCharStop(string[currentPos]))
161         --currentPos;
162     return currentPos;
163 }
164
165 int LineBreakIterator::next()
166 {
167     if (currentPos == length) {
168         currentPos = -1;
169         return currentPos;
170     }
171     bool haveSpace = false;
172     while (currentPos < length) {
173         if (haveSpace && !isLineStop(string[currentPos]))
174             break;
175         if (isLineStop(string[currentPos]))
176             haveSpace = true;
177         ++currentPos;
178     }
179     return currentPos;
180 }
181
182 int LineBreakIterator::previous()
183 {
184     if (!currentPos) {
185         currentPos = -1;
186         return currentPos;
187     }
188     bool haveSpace = false;
189     while (currentPos > 0) {
190         if (haveSpace && !isLineStop(string[currentPos]))
191             break;
192         if (isLineStop(string[currentPos]))
193             haveSpace = true;
194         --currentPos;
195     }
196     return currentPos;
197 }
198
199 int SentenceBreakIterator::next()
200 {
201     if (currentPos == length) {
202         currentPos = -1;
203         return currentPos;
204     }
205     bool haveSpace = false;
206     while (currentPos < length) {
207         if (haveSpace && !isSentenceStop(string[currentPos]))
208             break;
209         if (isSentenceStop(string[currentPos]))
210             haveSpace = true;
211         ++currentPos;
212     }
213     return currentPos;
214 }
215
216 int SentenceBreakIterator::previous()
217 {
218     if (!currentPos) {
219         currentPos = -1;
220         return currentPos;
221     }
222     bool haveSpace = false;
223     while (currentPos > 0) {
224         if (haveSpace && !isSentenceStop(string[currentPos]))
225             break;
226         if (isSentenceStop(string[currentPos]))
227             haveSpace = true;
228         --currentPos;
229     }
230     return currentPos;
231 }
232
233 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
234 {
235     DEFINE_STATIC_LOCAL(WordBreakIterator, iterator, ());
236     iterator.reset(string, length);
237     return &iterator;
238 }
239
240 static CharBreakIterator* nonSharedCharacterBreakIterator;
241
242 NonSharedCharacterBreakIterator::NonSharedCharacterBreakIterator(const UChar* buffer, int length)
243 {
244     m_iterator = nonSharedCharacterBreakIterator;
245     bool createdIterator = m_iterator && weakCompareAndSwap(reinterpret_cast<void**>(&nonSharedCharacterBreakIterator), m_iterator, 0);
246     if (!createdIterator)
247         m_iterator = new CharBreakIterator;
248     m_iterator->reset(buffer, length);
249 }
250
251 NonSharedCharacterBreakIterator::~NonSharedCharacterBreakIterator()
252 {
253     if (!weakCompareAndSwap(reinterpret_cast<void**>(&nonSharedCharacterBreakIterator), 0, m_iterator))
254         delete m_iterator;
255 }
256
257 static TextBreakIterator* staticLineBreakIterator;
258
259 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
260 {
261     TextBreakIterator* lineBreakIterator = 0;
262     if (staticLineBreakIterator) {
263         staticLineBreakIterator->reset(string, length);
264         swap(staticLineBreakIterator, lineBreakIterator);
265     }
266
267     if (!lineBreakIterator && string && length) {
268         lineBreakIterator = new LineBreakIterator;
269         lineBreakIterator->reset(string, length);
270     }
271
272     return lineBreakIterator;
273 }
274
275 void releaseLineBreakIterator(TextBreakIterator* iterator)
276 {
277     ASSERT(iterator);
278
279     if (!staticLineBreakIterator)
280         staticLineBreakIterator = iterator;
281     else
282         delete iterator;
283 }
284
285 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
286 {
287     DEFINE_STATIC_LOCAL(SentenceBreakIterator, iterator, ());
288     iterator.reset(string, length);
289     return &iterator;
290 }
291
292 int textBreakFirst(TextBreakIterator* breakIterator)
293 {
294     return breakIterator->first();
295 }
296
297 int textBreakLast(TextBreakIterator* breakIterator)
298 {
299     return breakIterator->last();
300 }
301
302 int textBreakNext(TextBreakIterator* breakIterator)
303 {
304     return breakIterator->next();
305 }
306
307 int textBreakPrevious(TextBreakIterator* breakIterator)
308 {
309     return breakIterator->previous();
310 }
311
312 int textBreakPreceding(TextBreakIterator* breakIterator, int position)
313 {
314     return breakIterator->preceding(position);
315 }
316
317 int textBreakFollowing(TextBreakIterator* breakIterator, int position)
318 {
319     return breakIterator->following(position);
320 }
321
322 int textBreakCurrent(TextBreakIterator* breakIterator)
323 {
324     return breakIterator->currentPos;
325 }
326
327 bool isTextBreak(TextBreakIterator*, int)
328 {
329     return true;
330 }
331
332 bool isWordTextBreak(TextBreakIterator*)
333 {
334     return true;
335 }
336
337 TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
338 {
339     DEFINE_STATIC_LOCAL(CharBreakIterator, iterator, ());
340     iterator.reset(string, length);
341     return &iterator;
342 }
343
344 } // namespace WebCore