|
|
|
/******************************************************************************
|
|
|
|
* Copyright (C) 2002 by Alexander Dymo <cloudtemple@mskat.net> *
|
|
|
|
* Copyright (C) 2002-2003 by Lukas Tinkl <lukas@kde.org> *
|
|
|
|
* Copyright (C) 2003 David Faure <faure@kde.org> *
|
|
|
|
* *
|
|
|
|
* This program 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., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA. *
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kstaticdeleter.h>
|
|
|
|
|
|
|
|
#include "kohyphen.h"
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
|
|
|
|
//#define DEBUG_HYPHENATOR 1
|
|
|
|
|
|
|
|
KoHyphenator* KoHyphenator::s_self;
|
|
|
|
static KStaticDeleter<KoHyphenator> kohyphensd;
|
|
|
|
|
|
|
|
KoHyphenator* KoHyphenator::self()
|
|
|
|
{
|
|
|
|
if ( !s_self )
|
|
|
|
kohyphensd.setObject( s_self, new KoHyphenator );
|
|
|
|
return s_self;
|
|
|
|
}
|
|
|
|
|
|
|
|
KoHyphenator::KoHyphenator()
|
|
|
|
{
|
|
|
|
/* Reading config for dictionary encodings from file...*/
|
|
|
|
|
|
|
|
TQString path = kapp->dirs()->findResource("data", "koffice/hyphdicts/dicts.xml");
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << path << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQFile *f;
|
|
|
|
if (!path.isNull())
|
|
|
|
f = new TQFile(path);
|
|
|
|
else
|
|
|
|
throw KoHyphenatorException( "Could not create KoHyphenator instance." );
|
|
|
|
|
|
|
|
TQDomDocument config;
|
|
|
|
TQDomNodeList records;
|
|
|
|
config.setContent(f);
|
|
|
|
|
|
|
|
for (TQDomNode n = config.firstChild(); !n.isNull(); n = n.nextSibling())
|
|
|
|
if (n.nodeName() == "dicts")
|
|
|
|
{
|
|
|
|
records = n.childNodes();
|
|
|
|
for (uint i = 0; i < records.count(); i++)
|
|
|
|
{
|
|
|
|
TQDomNamedNodeMap attr = records.item(i).attributes();
|
|
|
|
if (attr.contains("lang") && attr.contains("encoding")) {
|
|
|
|
TQString lang = attr.namedItem("lang").nodeValue();
|
|
|
|
TQString encoding = attr.namedItem("encoding").nodeValue();
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "KoHyphenator: found lang=" << lang << " encoding=" << encoding << endl;
|
|
|
|
#endif
|
|
|
|
encodings.insert( lang,
|
|
|
|
EncodingStruct( encoding.latin1() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete f;
|
|
|
|
}
|
|
|
|
|
|
|
|
KoHyphenator::~KoHyphenator()
|
|
|
|
{
|
|
|
|
for (TQMap<TQString, HyphenDict*>::iterator it = dicts.begin(); it != dicts.end(); ++it)
|
|
|
|
{
|
|
|
|
if ((*it) != 0)
|
|
|
|
hnj_hyphen_free((*it));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *KoHyphenator::hyphens(const TQString& str, const TQString& lang) const
|
|
|
|
{
|
|
|
|
char *x = new char[str.length()+1];
|
|
|
|
try
|
|
|
|
{
|
|
|
|
TQTextCodec *codec = codecForLang(lang);
|
|
|
|
hnj_hyphen_hyphenate(dict(lang), (const char *)(codec->fromUnicode(str)), str.length(), x);
|
|
|
|
}
|
|
|
|
catch (KoHyphenatorException &e)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << e.message().latin1() << endl;
|
|
|
|
#endif
|
|
|
|
for (uint j = 0; j < str.length(); j++)
|
|
|
|
x[j] = '0';
|
|
|
|
x[str.length()] = '\0';
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KoHyphenator::hyphenate(const TQString& str, const TQString& lang) const
|
|
|
|
{
|
|
|
|
char* x = new char[str.length()+1];
|
|
|
|
TQString res = str;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
TQTextCodec *codec = codecForLang(lang);
|
|
|
|
hnj_hyphen_hyphenate(dict(lang), (const char *)(codec->fromUnicode(str)), str.length(), x);
|
|
|
|
}
|
|
|
|
catch (KoHyphenatorException &e)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << e.message() << endl;
|
|
|
|
#endif
|
|
|
|
delete[] x;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
int i = 0, j = 0;
|
|
|
|
int len = strlen(x);
|
|
|
|
for (; i < len; i++)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "loop: i=" << i << ", j=" << j << ", x=" << x << ", res=" << res << endl;
|
|
|
|
#endif
|
|
|
|
if ((x[i] % 2) != 0)
|
|
|
|
{
|
|
|
|
res.insert(j+1, TQChar(0xad));
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
delete[] x;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KoHyphenator::checkHyphenPos(const TQString& str, int pos, const TQString& lang) const
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "string: " << str << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
char *hyph = hyphens(str, lang);
|
|
|
|
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "result: " << hyph << endl;
|
|
|
|
kdDebug() << "checked position: " << pos << endl;
|
|
|
|
#endif
|
|
|
|
bool ret = ((hyph[pos] % 2) != 0);
|
|
|
|
delete[] hyph;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
HyphenDict *KoHyphenator::dict(const TQString &_lang) const
|
|
|
|
{
|
|
|
|
TQString lang( _lang );
|
|
|
|
//only load dictionary when encoding info is present
|
|
|
|
if (encodings.find(lang) == encodings.end())
|
|
|
|
{
|
|
|
|
int underscore = lang.find('_');
|
|
|
|
if ( underscore > -1 ) {
|
|
|
|
lang.truncate( underscore );
|
|
|
|
if (encodings.find(lang) == encodings.end())
|
|
|
|
throw KoHyphenatorException( TQString("No dictionary for %1").arg(lang) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw KoHyphenatorException( TQString("No dictionary for %1").arg(lang) );
|
|
|
|
}
|
|
|
|
if (dicts.find(lang) == dicts.end())
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "Searching dictionary for '" << lang << "' language..." << endl;
|
|
|
|
#endif
|
|
|
|
TQString path = kapp->dirs()->findResource("data", "koffice/hyphdicts/hyph_" + lang + ".dic");
|
|
|
|
if (!path.isNull())
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "Loading dictionary for '" << lang << "' language: path = " << path << endl;
|
|
|
|
#endif
|
|
|
|
const_cast<KoHyphenator*>(this)->dicts.insert( lang, hnj_hyphen_load(TQFile::encodeName(path)) );
|
|
|
|
if (dicts.find(lang) == dicts.end())
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_HYPHENATOR
|
|
|
|
kdDebug() << "No dictionary loaded" << endl;
|
|
|
|
#endif
|
|
|
|
throw(KoHyphenatorException( TQString("Could not load dictionary for the language: %1").arg(lang) ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw(KoHyphenatorException( TQString("Could not load dictionary for the language: %1").arg(lang) ));
|
|
|
|
}
|
|
|
|
return dicts[lang];
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTextCodec* KoHyphenator::codecForLang(const TQString& lang) const
|
|
|
|
{
|
|
|
|
EncodingMap::Iterator it = encodings.find(lang);
|
|
|
|
if (it == encodings.end())
|
|
|
|
{
|
|
|
|
int underscore = lang.find('_');
|
|
|
|
if ( underscore > -1 ) {
|
|
|
|
TQString _lang( lang );
|
|
|
|
_lang.truncate( underscore );
|
|
|
|
it = encodings.find(_lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (it != encodings.end())
|
|
|
|
{
|
|
|
|
if ( (*it).codec )
|
|
|
|
return (*it).codec;
|
|
|
|
(*it).codec = TQTextCodec::codecForName((*it).encoding);
|
|
|
|
return (*it).codec;
|
|
|
|
}
|
|
|
|
return TQTextCodec::codecForMib(106); // utf-8
|
|
|
|
}
|