blob: 7f46e4f4fe234eea887215b386869a5beec80e68 [file] [log] [blame]
/*
* Copyright (C) 2006 Lars Knoll <lars@trolltech.com>
* Copyright (C) 2007-2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include "TextBreakIterator.h"
#include "PlatformString.h"
#include <wtf/StdLibExtras.h>
#include <wtf/unicode/Unicode.h>
using namespace WTF::Unicode;
namespace WebCore {
// Hack, not entirely correct
static inline bool isCharStop(UChar c)
{
CharCategory charCategory = category(c);
return charCategory != Mark_NonSpacing && (charCategory != Other_Surrogate || (c < 0xd800 || c >= 0xdc00));
}
static inline bool isLineStop(UChar c)
{
return category(c) != Separator_Line;
}
static inline bool isSentenceStop(UChar c)
{
return isPunct(c);
}
class TextBreakIterator {
public:
void reset(const UChar* str, int len)
{
string = str;
length = len;
currentPos = 0;
}
virtual int first() = 0;
virtual int next() = 0;
virtual int previous() = 0;
int following(int position)
{
currentPos = position;
return next();
}
int preceding(int position)
{
currentPos = position;
return previous();
}
int currentPos;
const UChar* string;
int length;
};
struct WordBreakIterator: TextBreakIterator {
virtual int first();
virtual int next();
virtual int previous();
};
struct CharBreakIterator: TextBreakIterator {
virtual int first();
virtual int next();
virtual int previous();
};
struct LineBreakIterator: TextBreakIterator {
virtual int first();
virtual int next();
virtual int previous();
};
struct SentenceBreakIterator : TextBreakIterator {
virtual int first();
virtual int next();
virtual int previous();
};
int WordBreakIterator::first()
{
currentPos = 0;
return currentPos;
}
int WordBreakIterator::next()
{
if (currentPos == length) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos < length) {
if (haveSpace && !isSpace(string[currentPos]))
break;
if (isSpace(string[currentPos]))
haveSpace = true;
++currentPos;
}
return currentPos;
}
int WordBreakIterator::previous()
{
if (!currentPos) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos > 0) {
if (haveSpace && !isSpace(string[currentPos]))
break;
if (isSpace(string[currentPos]))
haveSpace = true;
--currentPos;
}
return currentPos;
}
int CharBreakIterator::first()
{
currentPos = 0;
return currentPos;
}
int CharBreakIterator::next()
{
if (currentPos >= length)
return -1;
++currentPos;
while (currentPos < length && !isCharStop(string[currentPos]))
++currentPos;
return currentPos;
}
int CharBreakIterator::previous()
{
if (currentPos <= 0)
return -1;
if (currentPos > length)
currentPos = length;
--currentPos;
while (currentPos > 0 && !isCharStop(string[currentPos]))
--currentPos;
return currentPos;
}
int LineBreakIterator::first()
{
currentPos = 0;
return currentPos;
}
int LineBreakIterator::next()
{
if (currentPos == length) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos < length) {
if (haveSpace && !isLineStop(string[currentPos]))
break;
if (isLineStop(string[currentPos]))
haveSpace = true;
++currentPos;
}
return currentPos;
}
int LineBreakIterator::previous()
{
if (!currentPos) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos > 0) {
if (haveSpace && !isLineStop(string[currentPos]))
break;
if (isLineStop(string[currentPos]))
haveSpace = true;
--currentPos;
}
return currentPos;
}
int SentenceBreakIterator::first()
{
currentPos = 0;
return currentPos;
}
int SentenceBreakIterator::next()
{
if (currentPos == length) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos < length) {
if (haveSpace && !isSentenceStop(string[currentPos]))
break;
if (isSentenceStop(string[currentPos]))
haveSpace = true;
++currentPos;
}
return currentPos;
}
int SentenceBreakIterator::previous()
{
if (!currentPos) {
currentPos = -1;
return currentPos;
}
bool haveSpace = false;
while (currentPos > 0) {
if (haveSpace && !isSentenceStop(string[currentPos]))
break;
if (isSentenceStop(string[currentPos]))
haveSpace = true;
--currentPos;
}
return currentPos;
}
TextBreakIterator* wordBreakIterator(const UChar* string, int length)
{
DEFINE_STATIC_LOCAL(WordBreakIterator, iterator, ());
iterator.reset(string, length);
return &iterator;
}
TextBreakIterator* characterBreakIterator(const UChar* string, int length)
{
DEFINE_STATIC_LOCAL(CharBreakIterator, iterator, ());
iterator.reset(string, length);
return &iterator;
}
TextBreakIterator* lineBreakIterator(const UChar* string, int length)
{
DEFINE_STATIC_LOCAL(LineBreakIterator , iterator, ());
iterator.reset(string, length);
return &iterator;
}
TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
{
DEFINE_STATIC_LOCAL(SentenceBreakIterator, iterator, ());
iterator.reset(string, length);
return &iterator;
}
int textBreakFirst(TextBreakIterator* breakIterator)
{
return breakIterator->first();
}
int textBreakNext(TextBreakIterator* breakIterator)
{
return breakIterator->next();
}
int textBreakPreceding(TextBreakIterator* breakIterator, int position)
{
return breakIterator->preceding(position);
}
int textBreakFollowing(TextBreakIterator* breakIterator, int position)
{
return breakIterator->following(position);
}
int textBreakCurrent(TextBreakIterator* breakIterator)
{
return breakIterator->currentPos;
}
bool isTextBreak(TextBreakIterator*, int)
{
return true;
}
TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
{
return characterBreakIterator(string, length);
}
} // namespace WebCore