• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

ktranslit.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries    Copyright (C) 2007 Chusslove Illich <caslav.ilic@gmx.net>
00002 
00003     This library is free software; you can redistribute it and/or
00004     modify it under the terms of the GNU Library General Public
00005     License as published by the Free Software Foundation; either
00006     version 2 of the License, or (at your option) any later version.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include <ktranslit_p.h>
00020 #include <kdebug.h>
00021 
00022 #include <config.h>
00023 
00024 #include <QHash>
00025 
00026 // -----------------------------------------------------------------------------
00027 // Base class.
00028 
00029 class KTranslitPrivate
00030 {
00031 };
00032 
00033 KTranslit::KTranslit ()
00034 : d(NULL)
00035 {
00036 }
00037 
00038 KTranslit::~KTranslit ()
00039 {
00040     delete d;
00041 }
00042 
00043 KTranslit *KTranslit::create (const QString &lang)
00044 {
00045     if (lang == QString::fromAscii("sr")) {
00046         return new KTranslitSerbian();
00047     }
00048     else {
00049         return NULL;
00050     }
00051 }
00052 
00053 QStringList KTranslit::fallbackList (const QString &lang)
00054 {
00055     QStringList fallbacks;
00056 
00057     if (   lang == QString::fromAscii("sr@latin")
00058         || lang == QString::fromAscii("sr@Latn")) {
00059         fallbacks += QString::fromAscii("sr");
00060     }
00061 
00062     return fallbacks;
00063 }
00064 
00065 void splitLangScript (const QString &lang, QString &ln, QString &scr)
00066 {
00067     ln = lang;
00068     scr.clear();
00069     int pos = lang.indexOf('@');
00070     if (pos >= 0) {
00071         ln = lang.left(pos);
00072         scr = lang.mid(pos + 1);
00073     }
00074 }
00075 
00076 QString KTranslit::higherPriorityScript (const QString &lang,
00077                                          const KLocale *locale)
00078 {
00079     if (locale == NULL) {
00080         return QString();
00081     }
00082 
00083     // Split into pure language and script part.
00084     QString ln, scr;
00085     splitLangScript(lang, ln, scr);
00086 
00087     // Search through higher priority languages.
00088     QString finalScrHi;
00089     if (lang != KLocale::defaultLanguage()) {
00090         foreach (const QString &langHi, locale->languageList()) {
00091             // Don't search lower priority languages.
00092             if (langHi == lang)
00093                 break;
00094 
00095             // Split current spec into pure language and script parts.
00096             QString lnHi, scrHi;
00097             splitLangScript(langHi, lnHi, scrHi);
00098 
00099             // Return current script if languages match.
00100             if (lnHi == ln) {
00101                 finalScrHi = scrHi;
00102                 break;
00103             }
00104         }
00105     }
00106     return finalScrHi;
00107 }
00108 
00109 QString KTranslit::transliterate (const QString &str,
00110                                   const QString &script) const
00111 {
00112     Q_UNUSED(script);
00113     return str;
00114 }
00115 
00116 // Head of alternative inserts directives.
00117 #define ALTINS_HEAD "~@"

QString KTranslit::resolveInserts (const QString &str_, int nins, int ind) const
{
    static QString head(ALTINS_HEAD);
    static int hlen = head.length();

    QString str = str_;
    QString rstr;
    while (1) {
        int p = str.indexOf(head);
        if (p < 0) {
            break;
        }

        // Append segment before optional insert to resulting text.
        rstr.append(str.left(p));

        // Must have at least 2 characters after the head.
        if (str.length() < p + hlen + 2) {
            kDebug(173) << QString("Malformed optional inserts list in {%1}, "
00118                                    "starting here: {%2}").arg(str_, str);
00119             return str_;
00120         }
00121 
00122         // Read the separating character and trim original string.
00123         QChar sep = str[p + hlen];
00124         str.remove(0, p + hlen + 1);
00125 
00126         // Parse requested number of inserts,
00127         // choose the one with matching index for resulting text.
00128         for (int i = 0; i < nins; ++i) {
00129             // Ending separator for this insert.
00130             int p = str.indexOf(sep);
00131 
00132             // Must have exactly the requested number of inserts.
00133             if (p < 0) {
00134                 kDebug(173) << QString("Not enough inserts listed in {%1}, "
00135                                        "starting here: {%2}").arg(str_, str);
00136                 return str_;
00137             }
00138 
00139             // If index is matching requested, append to resulting text.
00140             if (i == ind) {
00141                 rstr.append(str.left(p));
00142             }
00143 
00144             // Trim original string.
00145             str.remove(0, p + 1);
00146         }
00147     }
00148     // Append the final segment to resulting text.
00149     rstr.append(str);
00150 
00151     return rstr;
00152 }
00153 
00154 // If the insert is just starting at position i, return the position of the
00155 // first character after the insert (or string length if none).
00156 // If the insert is not starting, return i itself.
00157 static int skipInsert (const QString &str, int i, int ninserts)
00158 {
00159     static QString head(ALTINS_HEAD);
00160     static int hlen = head.length();
00161 
00162     if (str.mid(i, hlen) == head) {
00163         int slen = str.length();
00164         int ia = i + hlen;
00165         if (ia >= slen) return slen;
00166         QChar sep = str[ia];
00167         for (int k = 0; k < ninserts; ++k) {
00168             ia = str.indexOf(sep, ia + 1);
00169             if (ia < 0) return slen;
00170         }
00171         return ia + 1;
00172     }
00173     else {
00174         return i;
00175     }
00176 }
00177 
00178 // -----------------------------------------------------------------------------
00179 // Serbian.
00180 
00181 class KTranslitSerbianPrivate
00182 {
00183     public:
00184     QHash<QString, bool> latinNames;
00185     QHash<QChar, QString> dictC2L;
00186 };
00187 
00188 KTranslitSerbian::KTranslitSerbian ()
00189 : d(new KTranslitSerbianPrivate())
00190 {
00191     d->latinNames[QString::fromAscii("latin")] = true;
00192     d->latinNames[QString::fromAscii("Latn")] = true;
00193 
00194     #define SR_DICTC2L_ENTRY(a, b) do { \
00195         d->dictC2L[QString::fromUtf8(a)[0]] = QString::fromUtf8(b); \
00196     } while (0)
00197     SR_DICTC2L_ENTRY("а", "a");
00198     SR_DICTC2L_ENTRY("б", "b");
00199     SR_DICTC2L_ENTRY("в", "v");
00200     SR_DICTC2L_ENTRY("г", "g");
00201     SR_DICTC2L_ENTRY("д", "d");
00202     SR_DICTC2L_ENTRY("ђ", "đ");
00203     SR_DICTC2L_ENTRY("е", "e");
00204     SR_DICTC2L_ENTRY("ж", "ž");
00205     SR_DICTC2L_ENTRY("з", "z");
00206     SR_DICTC2L_ENTRY("и", "i");
00207     SR_DICTC2L_ENTRY("ј", "j");
00208     SR_DICTC2L_ENTRY("к", "k");
00209     SR_DICTC2L_ENTRY("л", "l");
00210     SR_DICTC2L_ENTRY("љ", "lj");
00211     SR_DICTC2L_ENTRY("м", "m");
00212     SR_DICTC2L_ENTRY("н", "n");
00213     SR_DICTC2L_ENTRY("њ", "nj");
00214     SR_DICTC2L_ENTRY("о", "o");
00215     SR_DICTC2L_ENTRY("п", "p");
00216     SR_DICTC2L_ENTRY("р", "r");
00217     SR_DICTC2L_ENTRY("с", "s");
00218     SR_DICTC2L_ENTRY("т", "t");
00219     SR_DICTC2L_ENTRY("ћ", "ć");
00220     SR_DICTC2L_ENTRY("у", "u");
00221     SR_DICTC2L_ENTRY("ф", "f");
00222     SR_DICTC2L_ENTRY("х", "h");
00223     SR_DICTC2L_ENTRY("ц", "c");
00224     SR_DICTC2L_ENTRY("ч", "č");
00225     SR_DICTC2L_ENTRY("џ", "dž");
00226     SR_DICTC2L_ENTRY("ш", "š");
00227     SR_DICTC2L_ENTRY("А", "A");
00228     SR_DICTC2L_ENTRY("Б", "B");
00229     SR_DICTC2L_ENTRY("В", "V");
00230     SR_DICTC2L_ENTRY("Г", "G");
00231     SR_DICTC2L_ENTRY("Д", "D");
00232     SR_DICTC2L_ENTRY("Ђ", "Đ");
00233     SR_DICTC2L_ENTRY("Е", "E");
00234     SR_DICTC2L_ENTRY("Ж", "Ž");
00235     SR_DICTC2L_ENTRY("З", "Z");
00236     SR_DICTC2L_ENTRY("И", "I");
00237     SR_DICTC2L_ENTRY("Ј", "J");
00238     SR_DICTC2L_ENTRY("К", "K");
00239     SR_DICTC2L_ENTRY("Л", "L");
00240     SR_DICTC2L_ENTRY("Љ", "Lj");
00241     SR_DICTC2L_ENTRY("М", "M");
00242     SR_DICTC2L_ENTRY("Н", "N");
00243     SR_DICTC2L_ENTRY("Њ", "Nj");
00244     SR_DICTC2L_ENTRY("О", "O");
00245     SR_DICTC2L_ENTRY("П", "P");
00246     SR_DICTC2L_ENTRY("Р", "R");
00247     SR_DICTC2L_ENTRY("С", "S");
00248     SR_DICTC2L_ENTRY("Т", "T");
00249     SR_DICTC2L_ENTRY("Ћ", "Ć");
00250     SR_DICTC2L_ENTRY("У", "U");
00251     SR_DICTC2L_ENTRY("Ф", "F");
00252     SR_DICTC2L_ENTRY("Х", "H");
00253     SR_DICTC2L_ENTRY("Ц", "C");
00254     SR_DICTC2L_ENTRY("Ч", "Č");
00255     SR_DICTC2L_ENTRY("Џ", "Dž");
00256     SR_DICTC2L_ENTRY("Ш", "Š");
00257 }
00258 
00259 KTranslitSerbian::~KTranslitSerbian ()
00260 {
00261     delete d;
00262 }
00263 
00264 QString KTranslitSerbian::transliterate (const QString &str,
00265                                          const QString &script) const
00266 {
00267     static QString insHead(ALTINS_HEAD);
00268 
00269     if (d->latinNames.contains(script)) {
00270         // NOTE: This loop has been somewhat optimized for speed.
00271         int slen = str.length();
00272         bool anyInserts = str.indexOf(insHead) >= 0;
00273         QString nstr;
00274         nstr.reserve(slen + 5);
00275         for (int i = 0; i < slen; ++i) {
00276             // Skip alternative inserts altogether, so that they can be used
00277             // as a mean to exclude from transliteration.
00278             if (anyInserts) {
00279                 int to = skipInsert(str, i, 2);
00280                 if (to > i) {
00281                     nstr.append(str.mid(i, to - i));
00282                     if (to >= slen) break;
00283                     i = to;
00284                 }
00285             }
00286             // Transliterate current character.
00287             QChar c = str[i];
00288             QString r = d->dictC2L[c];
00289             if (!r.isEmpty()) {
00290                 if (   r.length() > 1 && c.isUpper()
00291                     && (   (i + 1 < slen && str[i + 1].isUpper())
00292                         || (i > 0 && str[i - 1].isUpper()))) {
00293                     nstr.append(r.toUpper());
00294                 }
00295                 else {
00296                     nstr.append(r);
00297                 }
00298             }
00299             else {
00300                 nstr.append(c);
00301             }
00302         }
00303         nstr = resolveInserts(nstr, 2, 1);
00304         return nstr;
00305     }
00306     else {
00307         QString nstr = resolveInserts(str, 2, 0);
00308         return nstr;
00309     }
00310 }
00311 

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal