63f20eab107d352ff4ab0ef81cf0d62816fca238
[WebKit-https.git] / WebCore / platform / qt / TextBreakIteratorQt.cpp
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 2006 Lars Knoll <lars@trolltech.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "TextBreakIterator.h"
24
25 #if QT_VERSION >= 0x040400
26 #include <QtCore/qtextboundaryfinder.h>
27 #include <qdebug.h>
28
29 #ifdef DEBUG_TEXT_ITERATORS
30 #define DEBUG qDebug
31 #else
32 #define DEBUG if (1) {} else qDebug
33 #endif
34
35 namespace WebCore {
36
37     class TextBreakIterator : public QTextBoundaryFinder
38     {
39     };
40
41
42     TextBreakIterator* wordBreakIterator(const UChar* string, int length)
43     {
44         static QTextBoundaryFinder* iterator = 0;
45         static const UChar* cachedString = 0;
46         static int cachedLength = 0;
47         if (!string)
48             return 0;
49         if (string != cachedString || length != cachedLength) {
50             if (!iterator)
51                 iterator = new QTextBoundaryFinder;
52
53             QString s((const QChar*)string, length);
54             DEBUG() << "wordBreakIterator" << length << s;
55             *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Word, s);
56             cachedString = string;
57             cachedLength = length;
58         } else {
59             iterator->setPosition(0);
60         }
61         return static_cast<TextBreakIterator*>(iterator);
62     }
63
64     TextBreakIterator* characterBreakIterator(const UChar* string, int length)
65     {
66         static QTextBoundaryFinder* iterator = 0;
67         static const UChar* cachedString = 0;
68         static int cachedLength = 0;
69         if (!string)
70             return 0;
71         if (string != cachedString || length != cachedLength) {
72             if (!iterator)
73                 iterator = new QTextBoundaryFinder;
74
75             QString s((const QChar*)string, length);
76             DEBUG() << "characterBreakIterator" << length << s;
77             *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Grapheme, s);
78             cachedString = string;
79             cachedLength = length;
80         } else {
81             iterator->setPosition(0);
82         }
83         return static_cast<TextBreakIterator*>(iterator);
84     }
85
86     TextBreakIterator* lineBreakIterator(const UChar* string, int length)
87     {
88         static QTextBoundaryFinder *iterator = 0;
89         static const UChar *cachedString = 0;
90         static int cachedLength = 0;
91         if (!string)
92             return 0;
93         if (string != cachedString || length != cachedLength) {
94             if (!iterator)
95                 iterator = new QTextBoundaryFinder;
96
97             QString s((const QChar *)string, length);
98             DEBUG() << "lineBreakIterator" << length << s;
99             *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Line, s);
100             cachedString = string;
101             cachedLength = length;
102         } else {
103             iterator->setPosition(0);
104         }
105         return static_cast<TextBreakIterator*>(iterator);
106     }
107
108     TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
109     {
110         static QTextBoundaryFinder* iterator = 0;
111         static const UChar* cachedString = 0;
112         static int cachedLength = 0;
113         if (!string)
114             return 0;
115         if (string != cachedString || length != cachedLength) {
116             if (!iterator)
117                 iterator = new QTextBoundaryFinder;
118
119             QString s((const QChar*)string, length);
120             DEBUG() << "sentenceBreakIterator" << length << s;
121             *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Sentence, s);
122             cachedString = string;
123             cachedLength = length;
124         } else {
125             iterator->setPosition(0);
126         }
127         return static_cast<TextBreakIterator*>(iterator);
128     }
129
130     int textBreakFirst(TextBreakIterator* bi)
131     {
132         bi->toStart();
133         DEBUG() << "textBreakFirst" << bi->position();
134         return bi->position();
135     }
136
137     int textBreakNext(TextBreakIterator* bi)
138     {
139         int pos = bi->toNextBoundary();
140         DEBUG() << "textBreakNext" << pos;
141         return pos;
142     }
143
144     int textBreakPreceding(TextBreakIterator* bi, int pos)
145     {
146         bi->setPosition(pos);
147         int newpos = bi->toPreviousBoundary();
148         DEBUG() << "textBreakPreceding" << pos << newpos;
149         return newpos;
150     }
151
152     int textBreakFollowing(TextBreakIterator* bi, int pos)
153     {
154         bi->setPosition(pos);
155         int newpos = bi->toNextBoundary();
156         DEBUG() << "textBreakFollowing" << pos << newpos;
157         return newpos;
158     }
159
160     int textBreakCurrent(TextBreakIterator* bi)
161     {
162         return bi->position();
163     }
164
165     bool isTextBreak(TextBreakIterator*, int)
166     {
167         return true;
168     }
169
170 }
171 #else
172 #include <qtextlayout.h>
173
174 namespace WebCore {
175
176     class TextBreakIterator
177     {
178     public:
179         virtual int first() = 0;
180         virtual int next() = 0;
181         virtual int previous() = 0;
182         inline int following(int pos) {
183             currentPos = pos;
184             return next();
185         }
186         inline int preceding(int pos) {
187             currentPos = pos;
188             return previous();
189         }
190         int currentPos;
191         const UChar *string;
192         int length;
193     };
194
195     class WordBreakIteratorQt : public TextBreakIterator
196     {
197     public:
198         virtual int first();
199         virtual int next();
200         virtual int previous();
201     };
202
203     class CharBreakIteratorQt : public TextBreakIterator
204     {
205     public:
206         virtual int first();
207         virtual int next();
208         virtual int previous();
209         QTextLayout layout;
210     };
211
212     int WordBreakIteratorQt::first() {
213         currentPos = 0;
214         return currentPos;
215     }
216
217     int WordBreakIteratorQt::next() {
218         if (currentPos >= length) {
219             currentPos = -1;
220             return currentPos;
221         }
222         bool haveSpace = false;
223         while (currentPos < length) {
224             if (haveSpace && !QChar(string[currentPos]).isSpace())
225                 break;
226             if (QChar(string[currentPos]).isSpace())
227                 haveSpace = true;
228             ++currentPos;
229         }
230         return currentPos;
231     }
232     int WordBreakIteratorQt::previous() {
233         if (currentPos <= 0) {
234             currentPos = -1;
235             return currentPos;
236         }
237         bool haveSpace = false;
238         while (currentPos > 0) {
239             if (haveSpace && !QChar(string[currentPos]).isSpace())
240                 break;
241             if (QChar(string[currentPos]).isSpace())
242                 haveSpace = true;
243             --currentPos;
244         }
245         return currentPos;
246     }
247
248     int CharBreakIteratorQt::first() {
249         currentPos = 0;
250         return currentPos;
251     }
252
253     int CharBreakIteratorQt::next() {
254         if (currentPos >= length)
255             return -1;
256         currentPos = layout.nextCursorPosition(currentPos);
257         return currentPos;
258     }
259     int CharBreakIteratorQt::previous() {
260         if (currentPos <= 0)
261             return -1;
262         currentPos = layout.previousCursorPosition(currentPos);
263         return currentPos;
264     }
265
266
267 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
268 {
269     static WordBreakIteratorQt *iterator = 0;
270     if (!iterator)
271         iterator = new WordBreakIteratorQt;
272
273     iterator->string = string;
274     iterator->length = length;
275     iterator->currentPos = 0;
276
277     return iterator;
278 }
279
280 TextBreakIterator* characterBreakIterator(const UChar* string, int length)
281 {
282     static CharBreakIteratorQt *iterator = 0;
283     if (!iterator)
284         iterator = new CharBreakIteratorQt;
285
286     iterator->string = string;
287     iterator->length = length;
288     iterator->currentPos = 0;
289     iterator->layout.setText(QString(reinterpret_cast<const QChar*>(string), length));
290     
291     return iterator;
292 }
293
294 TextBreakIterator* lineBreakIterator(const UChar*, int)
295 {
296     // not yet implemented
297     return 0;
298 }
299
300 TextBreakIterator* sentenceBreakIterator(const UChar*, int)
301 {
302     // not yet implemented
303     return 0;
304 }
305
306 int textBreakFirst(TextBreakIterator* bi)
307 {
308     return bi->first();
309 }
310
311 int textBreakNext(TextBreakIterator* bi)
312 {
313     return bi->next();
314 }
315
316 int textBreakPreceding(TextBreakIterator* bi, int pos)
317 {
318     return bi->preceding(pos);
319 }
320
321 int textBreakFollowing(TextBreakIterator* bi, int pos)
322 {
323     return bi->following(pos);
324 }
325
326 int textBreakCurrent(TextBreakIterator* bi)
327 {
328     return bi->currentPos;
329 }
330
331 bool isTextBreak(TextBreakIterator*, int)
332 {
333     return true;
334 }
335
336 }
337
338 #endif