/****************************************************************************** * 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 }