88b96808650ed290ea328208157d2f965089d39e
[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 // #define DEBUG_TEXT_ITERATORS
30 #ifdef DEBUG_TEXT_ITERATORS
31 #define DEBUG qDebug
32 #else
33 #define DEBUG if (1) {} else qDebug
34 #endif
35
36 namespace WebCore {
37
38     class TextBreakIterator : public QTextBoundaryFinder
39     {
40     };
41     static QTextBoundaryFinder* iterator = 0;
42     static unsigned char buffer[1024];
43
44     TextBreakIterator* wordBreakIterator(const UChar* string, int length)
45     {
46         if (!string)
47             return 0;
48         if (!iterator)
49             iterator = new QTextBoundaryFinder;
50
51         *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Word, (const QChar *)string, length, buffer, sizeof(buffer));
52         return static_cast<TextBreakIterator*>(iterator);
53     }
54
55     TextBreakIterator* characterBreakIterator(const UChar* string, int length)
56     {
57         if (!string)
58             return 0;
59         if (!iterator)
60             iterator = new QTextBoundaryFinder;
61
62         *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Grapheme, (const QChar *)string, length, buffer, sizeof(buffer));
63         return static_cast<TextBreakIterator*>(iterator);
64     }
65
66     TextBreakIterator* lineBreakIterator(const UChar* string, int length)
67     {
68         static QTextBoundaryFinder *iterator = 0;
69         if (!string)
70             return 0;
71         if (!iterator)
72             iterator = new QTextBoundaryFinder;
73
74         *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Line, (const QChar *)string, length, buffer, sizeof(buffer));
75         return static_cast<TextBreakIterator*>(iterator);
76     }
77
78     TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
79     {
80         if (!string)
81             return 0;
82         if (!iterator)
83             iterator = new QTextBoundaryFinder;
84
85         *iterator = QTextBoundaryFinder(QTextBoundaryFinder::Sentence, (const QChar *)string, length, buffer, sizeof(buffer));
86         return static_cast<TextBreakIterator*>(iterator);
87     }
88
89     int textBreakFirst(TextBreakIterator* bi)
90     {
91         bi->toStart();
92         DEBUG() << "textBreakFirst" << bi->position();
93         return bi->position();
94     }
95
96     int textBreakNext(TextBreakIterator* bi)
97     {
98         int pos = bi->toNextBoundary();
99         DEBUG() << "textBreakNext" << pos;
100         return pos;
101     }
102
103     int textBreakPreceding(TextBreakIterator* bi, int pos)
104     {
105         bi->setPosition(pos);
106         int newpos = bi->toPreviousBoundary();
107         DEBUG() << "textBreakPreceding" << pos << newpos;
108         return newpos;
109     }
110
111     int textBreakFollowing(TextBreakIterator* bi, int pos)
112     {
113         bi->setPosition(pos);
114         int newpos = bi->toNextBoundary();
115         DEBUG() << "textBreakFollowing" << pos << newpos;
116         return newpos;
117     }
118
119     int textBreakCurrent(TextBreakIterator* bi)
120     {
121         return bi->position();
122     }
123
124     bool isTextBreak(TextBreakIterator*, int)
125     {
126         return true;
127     }
128
129 }
130 #else
131 #include <qtextlayout.h>
132
133 namespace WebCore {
134
135     class TextBreakIterator
136     {
137     public:
138         virtual int first() = 0;
139         virtual int next() = 0;
140         virtual int previous() = 0;
141         inline int following(int pos) {
142             currentPos = pos;
143             return next();
144         }
145         inline int preceding(int pos) {
146             currentPos = pos;
147             return previous();
148         }
149         int currentPos;
150         const UChar *string;
151         int length;
152     };
153
154     class WordBreakIteratorQt : public TextBreakIterator
155     {
156     public:
157         virtual int first();
158         virtual int next();
159         virtual int previous();
160     };
161
162     class CharBreakIteratorQt : public TextBreakIterator
163     {
164     public:
165         virtual int first();
166         virtual int next();
167         virtual int previous();
168         QTextLayout layout;
169     };
170
171     int WordBreakIteratorQt::first() {
172         currentPos = 0;
173         return currentPos;
174     }
175
176     int WordBreakIteratorQt::next() {
177         if (currentPos >= length) {
178             currentPos = -1;
179             return currentPos;
180         }
181         bool haveSpace = false;
182         while (currentPos < length) {
183             if (haveSpace && !QChar(string[currentPos]).isSpace())
184                 break;
185             if (QChar(string[currentPos]).isSpace())
186                 haveSpace = true;
187             ++currentPos;
188         }
189         return currentPos;
190     }
191     int WordBreakIteratorQt::previous() {
192         if (currentPos <= 0) {
193             currentPos = -1;
194             return currentPos;
195         }
196         bool haveSpace = false;
197         while (currentPos > 0) {
198             if (haveSpace && !QChar(string[currentPos]).isSpace())
199                 break;
200             if (QChar(string[currentPos]).isSpace())
201                 haveSpace = true;
202             --currentPos;
203         }
204         return currentPos;
205     }
206
207     int CharBreakIteratorQt::first() {
208         currentPos = 0;
209         return currentPos;
210     }
211
212     int CharBreakIteratorQt::next() {
213         if (currentPos >= length)
214             return -1;
215         currentPos = layout.nextCursorPosition(currentPos);
216         return currentPos;
217     }
218     int CharBreakIteratorQt::previous() {
219         if (currentPos <= 0)
220             return -1;
221         currentPos = layout.previousCursorPosition(currentPos);
222         return currentPos;
223     }
224
225
226 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
227 {
228     static WordBreakIteratorQt *iterator = 0;
229     if (!iterator)
230         iterator = new WordBreakIteratorQt;
231
232     iterator->string = string;
233     iterator->length = length;
234     iterator->currentPos = 0;
235
236     return iterator;
237 }
238
239 TextBreakIterator* characterBreakIterator(const UChar* string, int length)
240 {
241     static CharBreakIteratorQt *iterator = 0;
242     if (!iterator)
243         iterator = new CharBreakIteratorQt;
244
245     iterator->string = string;
246     iterator->length = length;
247     iterator->currentPos = 0;
248     iterator->layout.setText(QString(reinterpret_cast<const QChar*>(string), length));
249     
250     return iterator;
251 }
252
253 TextBreakIterator* lineBreakIterator(const UChar*, int)
254 {
255     // not yet implemented
256     return 0;
257 }
258
259 TextBreakIterator* sentenceBreakIterator(const UChar*, int)
260 {
261     // not yet implemented
262     return 0;
263 }
264
265 int textBreakFirst(TextBreakIterator* bi)
266 {
267     return bi->first();
268 }
269
270 int textBreakNext(TextBreakIterator* bi)
271 {
272     return bi->next();
273 }
274
275 int textBreakPreceding(TextBreakIterator* bi, int pos)
276 {
277     return bi->preceding(pos);
278 }
279
280 int textBreakFollowing(TextBreakIterator* bi, int pos)
281 {
282     return bi->following(pos);
283 }
284
285 int textBreakCurrent(TextBreakIterator* bi)
286 {
287     return bi->currentPos;
288 }
289
290 bool isTextBreak(TextBreakIterator*, int)
291 {
292     return true;
293 }
294
295 }
296
297 #endif