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