1 /*
2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22 #include "TextBreakIterator.h"
23
24 #include <QtCore/qtextboundaryfinder.h>
25 #include <algorithm>
26 #include <qdebug.h>
27
28 // #define DEBUG_TEXT_ITERATORS
29 #ifdef DEBUG_TEXT_ITERATORS
30 #define DEBUG qDebug
31 #else
32 #define DEBUG if (1) {} else qDebug
33 #endif
34
35 using namespace std;
36
37 namespace WebCore {
38
39 #if USE(QT_ICU_TEXT_BREAKING)
currentTextBreakLocaleID()40 const char* currentTextBreakLocaleID()
41 {
42 return QLocale::system().name().toLatin1();
43 }
44 #else
45 class TextBreakIterator : public QTextBoundaryFinder {
46 public:
47 TextBreakIterator(QTextBoundaryFinder::BoundaryType type, const QString& string)
48 : QTextBoundaryFinder(type, string)
49 { }
50 TextBreakIterator()
51 : QTextBoundaryFinder()
52 { }
53 };
54
55 TextBreakIterator* setUpIterator(TextBreakIterator& iterator, QTextBoundaryFinder::BoundaryType type, const UChar* characters, int length)
56 {
57 if (!characters || !length)
58 return 0;
59
60 if (iterator.isValid() && type == iterator.type() && iterator.string() == QString::fromRawData(reinterpret_cast<const QChar*>(characters), length)) {
61 iterator.toStart();
62 return &iterator;
63 }
64
65 iterator = TextBreakIterator(type, QString(reinterpret_cast<const QChar*>(characters), length));
66 return &iterator;
67 }
68
69 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
70 {
71 static TextBreakIterator staticWordBreakIterator;
72 return setUpIterator(staticWordBreakIterator, QTextBoundaryFinder::Word, string, length);
73 }
74
75 TextBreakIterator* characterBreakIterator(const UChar* string, int length)
76 {
77 static TextBreakIterator staticCharacterBreakIterator;
78 return setUpIterator(staticCharacterBreakIterator, QTextBoundaryFinder::Grapheme, string, length);
79 }
80
81 TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
82 {
83 return characterBreakIterator(string, length);
84 }
85
86 static TextBreakIterator* staticLineBreakIterator;
87
88 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
89 {
90 TextBreakIterator* lineBreakIterator = 0;
91 if (staticLineBreakIterator) {
92 setUpIterator(*staticLineBreakIterator, QTextBoundaryFinder::Line, string, length);
93 std::swap(staticLineBreakIterator, lineBreakIterator);
94 }
95
96 if (!lineBreakIterator && string && length)
97 lineBreakIterator = new TextBreakIterator(QTextBoundaryFinder::Line, QString(reinterpret_cast<const QChar*>(string), length));
98
99 return lineBreakIterator;
100 }
101
102 void releaseLineBreakIterator(TextBreakIterator* iterator)
103 {
104 ASSERT(iterator);
105
106 if (!staticLineBreakIterator)
107 staticLineBreakIterator = iterator;
108 else
109 delete iterator;
110 }
111
112 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
113 {
114 static TextBreakIterator staticSentenceBreakIterator;
115 return setUpIterator(staticSentenceBreakIterator, QTextBoundaryFinder::Sentence, string, length);
116
117 }
118
119 int textBreakFirst(TextBreakIterator* bi)
120 {
121 bi->toStart();
122 DEBUG() << "textBreakFirst" << bi->position();
123 return bi->position();
124 }
125
126 int textBreakNext(TextBreakIterator* bi)
127 {
128 int pos = bi->toNextBoundary();
129 DEBUG() << "textBreakNext" << pos;
130 return pos;
131 }
132
133 int textBreakPreceding(TextBreakIterator* bi, int pos)
134 {
135 bi->setPosition(pos);
136 int newpos = bi->toPreviousBoundary();
137 DEBUG() << "textBreakPreceding" << pos << newpos;
138 return newpos;
139 }
140
141 int textBreakFollowing(TextBreakIterator* bi, int pos)
142 {
143 bi->setPosition(pos);
144 int newpos = bi->toNextBoundary();
145 DEBUG() << "textBreakFollowing" << pos << newpos;
146 return newpos;
147 }
148
149 int textBreakCurrent(TextBreakIterator* bi)
150 {
151 return bi->position();
152 }
153
154 bool isTextBreak(TextBreakIterator*, int)
155 {
156 return true;
157 }
158 #endif
159
160 }
161