2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com>
3 * Copyright (C) 2007-2009 Torch Mobile, Inc.
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.
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.
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.
23 #include "TextBreakIterator.h"
25 #include <wtf/Atomics.h>
26 #include <wtf/StdLibExtras.h>
27 #include <wtf/text/WTFString.h>
28 #include <wtf/unicode/Unicode.h>
31 using namespace WTF::Unicode;
36 // Hack, not entirely correct
37 static inline bool isCharStop(UChar c)
39 CharCategory charCategory = category(c);
40 return charCategory != Mark_NonSpacing && (charCategory != Other_Surrogate || (c < 0xd800 || c >= 0xdc00));
43 static inline bool isLineStop(UChar c)
45 return category(c) != Separator_Line;
48 static inline bool isSentenceStop(UChar c)
53 class TextBreakIterator {
55 void reset(const UChar* str, int len)
71 virtual int next() = 0;
72 virtual int previous() = 0;
73 int following(int position)
75 currentPos = position;
78 int preceding(int position)
80 currentPos = position;
89 struct WordBreakIterator: TextBreakIterator {
91 virtual int previous();
94 struct CharBreakIterator: TextBreakIterator {
96 virtual int previous();
99 struct LineBreakIterator: TextBreakIterator {
101 virtual int previous();
104 struct SentenceBreakIterator : TextBreakIterator {
106 virtual int previous();
109 int WordBreakIterator::next()
111 if (currentPos == length) {
115 bool haveSpace = false;
116 while (currentPos < length) {
117 if (haveSpace && !isSpace(string[currentPos]))
119 if (isSpace(string[currentPos]))
126 int WordBreakIterator::previous()
132 bool haveSpace = false;
133 while (currentPos > 0) {
134 if (haveSpace && !isSpace(string[currentPos]))
136 if (isSpace(string[currentPos]))
143 int CharBreakIterator::next()
145 if (currentPos >= length)
148 while (currentPos < length && !isCharStop(string[currentPos]))
153 int CharBreakIterator::previous()
157 if (currentPos > length)
160 while (currentPos > 0 && !isCharStop(string[currentPos]))
165 int LineBreakIterator::next()
167 if (currentPos == length) {
171 bool haveSpace = false;
172 while (currentPos < length) {
173 if (haveSpace && !isLineStop(string[currentPos]))
175 if (isLineStop(string[currentPos]))
182 int LineBreakIterator::previous()
188 bool haveSpace = false;
189 while (currentPos > 0) {
190 if (haveSpace && !isLineStop(string[currentPos]))
192 if (isLineStop(string[currentPos]))
199 int SentenceBreakIterator::next()
201 if (currentPos == length) {
205 bool haveSpace = false;
206 while (currentPos < length) {
207 if (haveSpace && !isSentenceStop(string[currentPos]))
209 if (isSentenceStop(string[currentPos]))
216 int SentenceBreakIterator::previous()
222 bool haveSpace = false;
223 while (currentPos > 0) {
224 if (haveSpace && !isSentenceStop(string[currentPos]))
226 if (isSentenceStop(string[currentPos]))
233 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
235 DEFINE_STATIC_LOCAL(WordBreakIterator, iterator, ());
236 iterator.reset(string, length);
240 static CharBreakIterator* nonSharedCharacterBreakIterator;
242 NonSharedCharacterBreakIterator::NonSharedCharacterBreakIterator(const UChar* buffer, int length)
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);
251 NonSharedCharacterBreakIterator::~NonSharedCharacterBreakIterator()
253 if (!weakCompareAndSwap(reinterpret_cast<void**>(&nonSharedCharacterBreakIterator), 0, m_iterator))
257 static TextBreakIterator* staticLineBreakIterator;
259 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
261 TextBreakIterator* lineBreakIterator = 0;
262 if (staticLineBreakIterator) {
263 staticLineBreakIterator->reset(string, length);
264 swap(staticLineBreakIterator, lineBreakIterator);
267 if (!lineBreakIterator && string && length) {
268 lineBreakIterator = new LineBreakIterator;
269 lineBreakIterator->reset(string, length);
272 return lineBreakIterator;
275 void releaseLineBreakIterator(TextBreakIterator* iterator)
279 if (!staticLineBreakIterator)
280 staticLineBreakIterator = iterator;
285 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
287 DEFINE_STATIC_LOCAL(SentenceBreakIterator, iterator, ());
288 iterator.reset(string, length);
292 int textBreakFirst(TextBreakIterator* breakIterator)
294 return breakIterator->first();
297 int textBreakLast(TextBreakIterator* breakIterator)
299 return breakIterator->last();
302 int textBreakNext(TextBreakIterator* breakIterator)
304 return breakIterator->next();
307 int textBreakPrevious(TextBreakIterator* breakIterator)
309 return breakIterator->previous();
312 int textBreakPreceding(TextBreakIterator* breakIterator, int position)
314 return breakIterator->preceding(position);
317 int textBreakFollowing(TextBreakIterator* breakIterator, int position)
319 return breakIterator->following(position);
322 int textBreakCurrent(TextBreakIterator* breakIterator)
324 return breakIterator->currentPos;
327 bool isTextBreak(TextBreakIterator*, int)
332 bool isWordTextBreak(TextBreakIterator*)
337 TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
339 DEFINE_STATIC_LOCAL(CharBreakIterator, iterator, ());
340 iterator.reset(string, length);
344 } // namespace WebCore