Home | History | Annotate | Download | only in wince
      1 /*
      2  * Copyright (C) 2006 Lars Knoll <lars (at) trolltech.com>
      3  * Copyright (C) 2007-2009 Torch Mobile, Inc.
      4  *
      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.
      9  *
     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.
     14  *
     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.
     19  *
     20  */
     21 
     22 #include "config.h"
     23 #include "TextBreakIterator.h"
     24 
     25 #include "PlatformString.h"
     26 #include <wtf/StdLibExtras.h>
     27 #include <wtf/unicode/Unicode.h>
     28 
     29 using namespace std;
     30 using namespace WTF::Unicode;
     31 
     32 namespace WebCore {
     33 
     34 // Hack, not entirely correct
     35 static inline bool isCharStop(UChar c)
     36 {
     37     CharCategory charCategory = category(c);
     38     return charCategory != Mark_NonSpacing && (charCategory != Other_Surrogate || (c < 0xd800 || c >= 0xdc00));
     39 }
     40 
     41 static inline bool isLineStop(UChar c)
     42 {
     43     return category(c) != Separator_Line;
     44 }
     45 
     46 static inline bool isSentenceStop(UChar c)
     47 {
     48     return isPunct(c);
     49 }
     50 
     51 class TextBreakIterator {
     52 public:
     53     void reset(const UChar* str, int len)
     54     {
     55         string = str;
     56         length = len;
     57         currentPos = 0;
     58     }
     59     int first()
     60     {
     61         currentPos = 0;
     62         return currentPos;
     63     }
     64     int last()
     65     {
     66         currentPos = length;
     67         return currentPos;
     68     }
     69     virtual int next() = 0;
     70     virtual int previous() = 0;
     71     int following(int position)
     72     {
     73         currentPos = position;
     74         return next();
     75     }
     76     int preceding(int position)
     77     {
     78         currentPos = position;
     79         return previous();
     80     }
     81 
     82     int currentPos;
     83     const UChar* string;
     84     int length;
     85 };
     86 
     87 struct WordBreakIterator: TextBreakIterator {
     88     virtual int next();
     89     virtual int previous();
     90 };
     91 
     92 struct CharBreakIterator: TextBreakIterator {
     93     virtual int next();
     94     virtual int previous();
     95 };
     96 
     97 struct LineBreakIterator: TextBreakIterator {
     98     virtual int next();
     99     virtual int previous();
    100 };
    101 
    102 struct SentenceBreakIterator : TextBreakIterator {
    103     virtual int next();
    104     virtual int previous();
    105 };
    106 
    107 int WordBreakIterator::next()
    108 {
    109     if (currentPos == length) {
    110         currentPos = -1;
    111         return currentPos;
    112     }
    113     bool haveSpace = false;
    114     while (currentPos < length) {
    115         if (haveSpace && !isSpace(string[currentPos]))
    116             break;
    117         if (isSpace(string[currentPos]))
    118             haveSpace = true;
    119         ++currentPos;
    120     }
    121     return currentPos;
    122 }
    123 
    124 int WordBreakIterator::previous()
    125 {
    126     if (!currentPos) {
    127         currentPos = -1;
    128         return currentPos;
    129     }
    130     bool haveSpace = false;
    131     while (currentPos > 0) {
    132         if (haveSpace && !isSpace(string[currentPos]))
    133             break;
    134         if (isSpace(string[currentPos]))
    135             haveSpace = true;
    136         --currentPos;
    137     }
    138     return currentPos;
    139 }
    140 
    141 int CharBreakIterator::next()
    142 {
    143     if (currentPos >= length)
    144         return -1;
    145     ++currentPos;
    146     while (currentPos < length && !isCharStop(string[currentPos]))
    147         ++currentPos;
    148     return currentPos;
    149 }
    150 
    151 int CharBreakIterator::previous()
    152 {
    153     if (currentPos <= 0)
    154         return -1;
    155     if (currentPos > length)
    156         currentPos = length;
    157     --currentPos;
    158     while (currentPos > 0 && !isCharStop(string[currentPos]))
    159         --currentPos;
    160     return currentPos;
    161 }
    162 
    163 int LineBreakIterator::next()
    164 {
    165     if (currentPos == length) {
    166         currentPos = -1;
    167         return currentPos;
    168     }
    169     bool haveSpace = false;
    170     while (currentPos < length) {
    171         if (haveSpace && !isLineStop(string[currentPos]))
    172             break;
    173         if (isLineStop(string[currentPos]))
    174             haveSpace = true;
    175         ++currentPos;
    176     }
    177     return currentPos;
    178 }
    179 
    180 int LineBreakIterator::previous()
    181 {
    182     if (!currentPos) {
    183         currentPos = -1;
    184         return currentPos;
    185     }
    186     bool haveSpace = false;
    187     while (currentPos > 0) {
    188         if (haveSpace && !isLineStop(string[currentPos]))
    189             break;
    190         if (isLineStop(string[currentPos]))
    191             haveSpace = true;
    192         --currentPos;
    193     }
    194     return currentPos;
    195 }
    196 
    197 int SentenceBreakIterator::next()
    198 {
    199     if (currentPos == length) {
    200         currentPos = -1;
    201         return currentPos;
    202     }
    203     bool haveSpace = false;
    204     while (currentPos < length) {
    205         if (haveSpace && !isSentenceStop(string[currentPos]))
    206             break;
    207         if (isSentenceStop(string[currentPos]))
    208             haveSpace = true;
    209         ++currentPos;
    210     }
    211     return currentPos;
    212 }
    213 
    214 int SentenceBreakIterator::previous()
    215 {
    216     if (!currentPos) {
    217         currentPos = -1;
    218         return currentPos;
    219     }
    220     bool haveSpace = false;
    221     while (currentPos > 0) {
    222         if (haveSpace && !isSentenceStop(string[currentPos]))
    223             break;
    224         if (isSentenceStop(string[currentPos]))
    225             haveSpace = true;
    226         --currentPos;
    227     }
    228     return currentPos;
    229 }
    230 
    231 TextBreakIterator* wordBreakIterator(const UChar* string, int length)
    232 {
    233     DEFINE_STATIC_LOCAL(WordBreakIterator, iterator, ());
    234     iterator.reset(string, length);
    235     return &iterator;
    236 }
    237 
    238 TextBreakIterator* characterBreakIterator(const UChar* string, int length)
    239 {
    240     DEFINE_STATIC_LOCAL(CharBreakIterator, iterator, ());
    241     iterator.reset(string, length);
    242     return &iterator;
    243 }
    244 
    245 static TextBreakIterator* staticLineBreakIterator;
    246 
    247 TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
    248 {
    249     TextBreakIterator* lineBreakIterator = 0;
    250     if (staticLineBreakIterator) {
    251         staticLineBreakIterator->reset(string, length);
    252         swap(staticLineBreakIterator, lineBreakIterator);
    253     }
    254 
    255     if (!lineBreakIterator && string && length) {
    256         lineBreakIterator = new LineBreakIterator;
    257         lineBreakIterator->reset(string, length);
    258     }
    259 
    260     return lineBreakIterator;
    261 }
    262 
    263 void releaseLineBreakIterator(TextBreakIterator* iterator)
    264 {
    265     ASSERT(iterator);
    266 
    267     if (!staticLineBreakIterator)
    268         staticLineBreakIterator = iterator;
    269     else
    270         delete iterator;
    271 }
    272 
    273 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
    274 {
    275     DEFINE_STATIC_LOCAL(SentenceBreakIterator, iterator, ());
    276     iterator.reset(string, length);
    277     return &iterator;
    278 }
    279 
    280 int textBreakFirst(TextBreakIterator* breakIterator)
    281 {
    282     return breakIterator->first();
    283 }
    284 
    285 int textBreakLast(TextBreakIterator* breakIterator)
    286 {
    287     return breakIterator->last();
    288 }
    289 
    290 int textBreakNext(TextBreakIterator* breakIterator)
    291 {
    292     return breakIterator->next();
    293 }
    294 
    295 int textBreakPrevious(TextBreakIterator* breakIterator)
    296 {
    297     return breakIterator->previous();
    298 }
    299 
    300 int textBreakPreceding(TextBreakIterator* breakIterator, int position)
    301 {
    302     return breakIterator->preceding(position);
    303 }
    304 
    305 int textBreakFollowing(TextBreakIterator* breakIterator, int position)
    306 {
    307     return breakIterator->following(position);
    308 }
    309 
    310 int textBreakCurrent(TextBreakIterator* breakIterator)
    311 {
    312     return breakIterator->currentPos;
    313 }
    314 
    315 bool isTextBreak(TextBreakIterator*, int)
    316 {
    317     return true;
    318 }
    319 
    320 TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
    321 {
    322     return characterBreakIterator(string, length);
    323 }
    324 
    325 } // namespace WebCore
    326