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

KDEUI

kcharselectdata.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002 
00003    Copyright (C) 2007 Daniel Laidig <d.laidig@gmx.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kcharselectdata_p.h"
00022 
00023 #include <QStringList>
00024 #include <QFile>
00025 #include <qendian.h>
00026 #include <QtConcurrentRun>
00027 
00028 #include <string.h>
00029 #include <klocalizedstring.h>
00030 #include <kstandarddirs.h>
00031 
00032 /* constants for hangul (de)composition, see UAX #15 */
00033 #define SBase 0xAC00
00034 #define LBase 0x1100
00035 #define VBase 0x1161
00036 #define TBase 0x11A7
00037 #define LCount 19
00038 #define VCount 21
00039 #define TCount 28
00040 #define NCount (VCount * TCount)
00041 #define SCount (LCount * NCount)
00042 
00043 static const char JAMO_L_TABLE[][4] =
00044     {
00045         "G", "GG", "N", "D", "DD", "R", "M", "B", "BB",
00046         "S", "SS", "", "J", "JJ", "C", "K", "T", "P", "H"
00047     };
00048 
00049 static const char JAMO_V_TABLE[][4] =
00050     {
00051         "A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O",
00052         "WA", "WAE", "OE", "YO", "U", "WEO", "WE", "WI",
00053         "YU", "EU", "YI", "I"
00054     };
00055 
00056 static const char JAMO_T_TABLE[][4] =
00057     {
00058         "", "G", "GG", "GS", "N", "NJ", "NH", "D", "L", "LG", "LM",
00059         "LB", "LS", "LT", "LP", "LH", "M", "B", "BS",
00060         "S", "SS", "NG", "J", "C", "K", "T", "P", "H"
00061     };
00062 
00063 bool KCharSelectData::openDataFile()
00064 {
00065     if(!dataFile.isEmpty()) {
00066         return true;
00067     } else {
00068         QFile file(KStandardDirs::locate("data", "kcharselect/kcharselect-data"));
00069         if (!file.open(QIODevice::ReadOnly)) {
00070             return false;
00071         }
00072         dataFile = file.readAll();
00073         file.close();
00074         futureIndex = QtConcurrent::run(this, &KCharSelectData::createIndex, dataFile);
00075         return true;
00076     }
00077 }
00078 
00079 quint32 KCharSelectData::getDetailIndex(const QChar& c) const
00080 {
00081     const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00082     // Convert from little-endian, so that this code works on PPC too.
00083     // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=482286
00084     const quint32 offsetBegin = qFromLittleEndian<quint32>(data+12);
00085     const quint32 offsetEnd = qFromLittleEndian<quint32>(data+16);
00086 
00087     int min = 0;
00088     int mid;
00089     int max = ((offsetEnd - offsetBegin) / 27) - 1;
00090 
00091     quint16 unicode = c.unicode();
00092 
00093     static quint16 most_recent_searched;
00094     static quint32 most_recent_result;
00095 
00096 
00097     if (unicode == most_recent_searched)
00098         return most_recent_result;
00099 
00100     most_recent_searched = unicode;
00101 
00102     while (max >= min) {
00103         mid = (min + max) / 2;
00104         const quint16 midUnicode = qFromLittleEndian<quint16>(data + offsetBegin + mid*27);
00105         if (unicode > midUnicode)
00106             min = mid + 1;
00107         else if (unicode < midUnicode)
00108             max = mid - 1;
00109         else {
00110             most_recent_result = offsetBegin + mid*27;
00111 
00112             return most_recent_result;
00113         }
00114     }
00115 
00116     most_recent_result = 0;
00117     return 0;
00118 }
00119 
00120 QString KCharSelectData::formatCode(ushort code, int length, const QString& prefix, int base)
00121 {
00122     QString s = QString::number(code, base).toUpper();
00123     while (s.size() < length)
00124         s.prepend('0');
00125     s.prepend(prefix);
00126     return s;
00127 }
00128 
00129 QList<QChar> KCharSelectData::blockContents(int block)
00130 {
00131     if(!openDataFile()) {
00132         return QList<QChar>();
00133     }
00134 
00135     const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00136     const quint32 offsetBegin = qFromLittleEndian<quint32>(data+20);
00137     const quint32 offsetEnd = qFromLittleEndian<quint32>(data+24);
00138 
00139     int max = ((offsetEnd - offsetBegin) / 4) - 1;
00140 
00141     QList<QChar> res;
00142 
00143     if(block > max)
00144         return res;
00145 
00146     quint16 unicodeBegin = qFromLittleEndian<quint16>(data + offsetBegin + block*4);
00147     quint16 unicodeEnd = qFromLittleEndian<quint16>(data + offsetBegin + block*4 + 2);
00148 
00149     while(unicodeBegin < unicodeEnd) {
00150         res.append(unicodeBegin);
00151         unicodeBegin++;
00152     }
00153     res.append(unicodeBegin); // Be carefull when unicodeEnd==0xffff
00154 
00155     return res;
00156 }
00157 
00158 QList<int> KCharSelectData::sectionContents(int section)
00159 {
00160     if(!openDataFile()) {
00161         return QList<int>();
00162     }
00163 
00164     const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00165     const quint32 offsetBegin = qFromLittleEndian<quint32>(data+28);
00166     const quint32 offsetEnd = qFromLittleEndian<quint32>(data+32);
00167 
00168     int max = ((offsetEnd - offsetBegin) / 4) - 1;
00169 
00170     QList<int> res;
00171 
00172     if(section > max)
00173         return res;
00174 
00175     for(int i = 0; i <= max; i++) {
00176         const quint16 currSection = qFromLittleEndian<quint16>(data + offsetBegin + i*4);
00177         if(currSection == section) {
00178             res.append( qFromLittleEndian<quint16>(data + offsetBegin + i*4 + 2) );
00179         }
00180     }
00181 
00182     return res;
00183 }
00184 
00185 QStringList KCharSelectData::sectionList()
00186 {
00187     if(!openDataFile()) {
00188         return QStringList();
00189     }
00190 
00191     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00192     const quint32 stringBegin = qFromLittleEndian<quint32>(udata+24);
00193     const quint32 stringEnd = qFromLittleEndian<quint32>(udata+28);
00194 
00195     const char* data = dataFile.constData();
00196     QStringList list;
00197     quint32 i = stringBegin;
00198     while(i < stringEnd) {
00199         list.append(i18nc("KCharSelect section name", data + i));
00200         i += strlen(data + i) + 1;
00201     }
00202 
00203     return list;
00204 }
00205 
00206 QString KCharSelectData::block(const QChar& c)
00207 {
00208     return blockName(blockIndex(c));
00209 }
00210 
00211 QString KCharSelectData::name(const QChar& c)
00212 {
00213     if(!openDataFile()) {
00214         return QString();
00215     }
00216 
00217     ushort unicode = c.unicode();
00218     if ((unicode >= 0x3400 && unicode <= 0x4DB5)
00219             || (unicode >= 0x4e00 && unicode <= 0x9fa5)) {
00220         // || (unicode >= 0x20000 && unicode <= 0x2A6D6) // useless, since limited to 16 bit
00221         return "CJK UNIFIED IDEOGRAPH-" + QString::number(unicode, 16);
00222     } else if (c >= 0xac00 && c <= 0xd7af) {
00223         /* compute hangul syllable name as per UAX #15 */
00224         int SIndex = c.unicode() - SBase;
00225         int LIndex, VIndex, TIndex;
00226 
00227         if (SIndex < 0 || SIndex >= SCount)
00228             return QString();
00229 
00230         LIndex = SIndex / NCount;
00231         VIndex = (SIndex % NCount) / TCount;
00232         TIndex = SIndex % TCount;
00233 
00234         return QString("HANGUL SYLLABLE ") + JAMO_L_TABLE[LIndex] + JAMO_V_TABLE[VIndex] + JAMO_T_TABLE[TIndex];
00235     } else if (unicode >= 0xD800 && unicode <= 0xDB7F)
00236         return i18n("<Non Private Use High Surrogate>");
00237     else if (unicode >= 0xDB80 && unicode <= 0xDBFF)
00238         return i18n("<Private Use High Surrogate>");
00239     else if (unicode >= 0xDC00 && unicode <= 0xDFFF)
00240         return i18n("<Low Surrogate>");
00241     else if (unicode >= 0xE000 && unicode <= 0xF8FF)
00242         return i18n("<Private Use>");
00243 //  else if (unicode >= 0xF0000 && unicode <= 0xFFFFD) // 16 bit!
00244 //   return i18n("<Plane 15 Private Use>");
00245 //  else if (unicode >= 0x100000 && unicode <= 0x10FFFD)
00246 //   return i18n("<Plane 16 Private Use>");
00247     else {
00248         const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00249         const quint32 offsetBegin = qFromLittleEndian<quint32>(data+4);
00250         const quint32 offsetEnd = qFromLittleEndian<quint32>(data+8);
00251 
00252         int min = 0;
00253         int mid;
00254         int max = ((offsetEnd - offsetBegin) / 6) - 1;
00255         QString s;
00256 
00257         while (max >= min) {
00258             mid = (min + max) / 2;
00259             const quint16 midUnicode = qFromLittleEndian<quint16>(data + offsetBegin + mid*6);
00260             if (unicode > midUnicode)
00261                 min = mid + 1;
00262             else if (unicode < midUnicode)
00263                 max = mid - 1;
00264             else {
00265                 quint32 offset = qFromLittleEndian<quint32>(data + offsetBegin + mid*6 + 2);
00266                 s = QString(dataFile.constData() + offset);
00267                 break;
00268             }
00269         }
00270 
00271         if (s.isNull()) {
00272             return i18n("<not assigned>");
00273         } else {
00274             return s;
00275         }
00276     }
00277 }
00278 
00279 int KCharSelectData::blockIndex(const QChar& c)
00280 {
00281     if(!openDataFile()) {
00282         return 0;
00283     }
00284 
00285     const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00286     const quint32 offsetBegin = qFromLittleEndian<quint32>(data+20);
00287     const quint32 offsetEnd = qFromLittleEndian<quint32>(data+24);
00288     const quint16 unicode = c.unicode();
00289 
00290     int max = ((offsetEnd - offsetBegin) / 4) - 1;
00291 
00292     int i = 0;
00293 
00294     while (unicode > qFromLittleEndian<quint16>(data + offsetBegin + i*4 + 2) && i < max) {
00295         i++;
00296     }
00297 
00298     return i;
00299 }
00300 
00301 int KCharSelectData::sectionIndex(int block)
00302 {
00303     if(!openDataFile()) {
00304         return 0;
00305     }
00306 
00307     const uchar* data = reinterpret_cast<const uchar*>(dataFile.constData());
00308     const quint32 offsetBegin = qFromLittleEndian<quint32>(data+28);
00309     const quint32 offsetEnd = qFromLittleEndian<quint32>(data+32);
00310 
00311     int max = ((offsetEnd - offsetBegin) / 4) - 1;
00312 
00313     for(int i = 0; i <= max; i++) {
00314         if( qFromLittleEndian<quint16>(data + offsetBegin + i*4 + 2) == block) {
00315             return qFromLittleEndian<quint16>(data + offsetBegin + i*4);
00316         }
00317     }
00318 
00319     return 0;
00320 }
00321 
00322 QString KCharSelectData::blockName(int index)
00323 {
00324     if(!openDataFile()) {
00325         return QString();
00326     }
00327 
00328     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00329     const quint32 stringBegin = qFromLittleEndian<quint32>(udata+16);
00330     const quint32 stringEnd = qFromLittleEndian<quint32>(udata+20);
00331 
00332     quint32 i = stringBegin;
00333     int currIndex = 0;
00334 
00335     const char* data = dataFile.constData();
00336     while(i < stringEnd && currIndex < index) {
00337         i += strlen(data + i) + 1;
00338         currIndex++;
00339     }
00340 
00341     return i18nc("KCharselect unicode block name", data + i);
00342 }
00343 
00344 QStringList KCharSelectData::aliases(const QChar& c)
00345 {
00346     if(!openDataFile()) {
00347         return QStringList();
00348     }
00349     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00350     const int detailIndex = getDetailIndex(c);
00351     if(detailIndex == 0) {
00352         return QStringList();
00353     }
00354 
00355     const quint8 count = * (quint8 *)(udata + detailIndex + 6);
00356     quint32 offset = qFromLittleEndian<quint32>(udata + detailIndex + 2);
00357 
00358     QStringList aliases;
00359 
00360     const char* data = dataFile.constData();
00361     for (int i = 0;  i < count;  i++) {
00362         aliases.append(QString::fromUtf8(data + offset));
00363         offset += strlen(data + offset) + 1;
00364     }
00365     return aliases;
00366 }
00367 
00368 QStringList KCharSelectData::notes(const QChar& c)
00369 {
00370     if(!openDataFile()) {
00371         return QStringList();
00372     }
00373     const int detailIndex = getDetailIndex(c);
00374     if(detailIndex == 0) {
00375         return QStringList();
00376     }
00377 
00378     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00379     const quint8 count = * (quint8 *)(udata + detailIndex + 11);
00380     quint32 offset = qFromLittleEndian<quint32>(udata + detailIndex + 7);
00381 
00382     QStringList notes;
00383 
00384     const char* data = dataFile.constData();
00385     for (int i = 0;  i < count;  i++) {
00386         notes.append(QString::fromLatin1(data + offset));
00387         offset += strlen(data + offset) + 1;
00388     }
00389 
00390     return notes;
00391 }
00392 
00393 QList<QChar> KCharSelectData::seeAlso(const QChar& c)
00394 {
00395     if(!openDataFile()) {
00396         return QList<QChar>();
00397     }
00398     const int detailIndex = getDetailIndex(c);
00399     if(detailIndex == 0) {
00400         return QList<QChar>();
00401     }
00402 
00403     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00404     const quint8 count = * (quint8 *)(udata + detailIndex + 26);
00405     quint32 offset = qFromLittleEndian<quint32>(udata + detailIndex + 22);
00406 
00407     QList<QChar> seeAlso;
00408 
00409     for (int i = 0;  i < count;  i++) {
00410         seeAlso.append(qFromLittleEndian<quint16> (udata + offset));
00411         offset += 2;
00412     }
00413 
00414     return seeAlso;
00415 }
00416 
00417 QStringList KCharSelectData::equivalents(const QChar& c)
00418 {
00419     if(!openDataFile()) {
00420         return QStringList();
00421     }
00422     const int detailIndex = getDetailIndex(c);
00423     if(detailIndex == 0) {
00424         return QStringList();
00425     }
00426 
00427     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00428     const quint8 count = * (quint8 *)(udata + detailIndex + 21);
00429     quint32 offset = qFromLittleEndian<quint32>(udata + detailIndex + 17);
00430 
00431     QStringList equivalents;
00432 
00433     const char* data = dataFile.constData();
00434     for (int i = 0;  i < count;  i++) {
00435         equivalents.append(QString::fromUtf8(data + offset));
00436         offset += strlen(data + offset) + 1;
00437     }
00438 
00439     return equivalents;
00440 }
00441 
00442 QStringList KCharSelectData::approximateEquivalents(const QChar& c)
00443 {
00444     if(!openDataFile()) {
00445         return QStringList();
00446     }
00447     const int detailIndex = getDetailIndex(c);
00448     if(detailIndex == 0) {
00449         return QStringList();
00450     }
00451 
00452     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00453     const quint8 count = * (quint8 *)(udata + detailIndex + 16);
00454     quint32 offset = qFromLittleEndian<quint32>(udata + detailIndex + 12);
00455 
00456     QStringList approxEquivalents;
00457 
00458     const char* data = dataFile.constData();
00459     for (int i = 0;  i < count;  i++) {
00460         approxEquivalents.append(QString::fromUtf8(data + offset));
00461         offset += strlen(data + offset) + 1;
00462     }
00463 
00464     return approxEquivalents;
00465 }
00466 
00467 QStringList KCharSelectData::unihanInfo(const QChar& c)
00468 {
00469     if(!openDataFile()) {
00470         return QStringList();
00471     }
00472 
00473     const char* data = dataFile.constData();
00474     const uchar* udata = reinterpret_cast<const uchar*>(data);
00475     const quint32 offsetBegin = qFromLittleEndian<quint32>(udata+36);
00476     const quint32 offsetEnd = dataFile.size();
00477 
00478     int min = 0;
00479     int mid;
00480     int max = ((offsetEnd - offsetBegin) / 30) - 1;
00481     quint16 unicode = c.unicode();
00482 
00483     while (max >= min) {
00484         mid = (min + max) / 2;
00485         const quint16 midUnicode = qFromLittleEndian<quint16>(udata + offsetBegin + mid*30);
00486         if (unicode > midUnicode)
00487             min = mid + 1;
00488         else if (unicode < midUnicode)
00489             max = mid - 1;
00490         else {
00491             QStringList res;
00492             for(int i = 0; i < 7; i++) {
00493                 quint32 offset = qFromLittleEndian<quint32>(udata + offsetBegin + mid*30 + 2 + i*4);
00494                 if(offset != 0) {
00495                     res.append(QString::fromUtf8(data + offset));
00496                 } else {
00497                     res.append(QString());
00498                 }
00499             }
00500             return res;
00501         }
00502     }
00503 
00504     return QStringList();
00505 }
00506 
00507 QString KCharSelectData::categoryText(QChar::Category category)
00508 {
00509     switch (category) {
00510     case QChar::Other_Control: return i18n("Other, Control");
00511     case QChar::Other_Format: return i18n("Other, Format");
00512     case QChar::Other_NotAssigned: return i18n("Other, Not Assigned");
00513     case QChar::Other_PrivateUse: return i18n("Other, Private Use");
00514     case QChar::Other_Surrogate: return i18n("Other, Surrogate");
00515     case QChar::Letter_Lowercase: return i18n("Letter, Lowercase");
00516     case QChar::Letter_Modifier: return i18n("Letter, Modifier");
00517     case QChar::Letter_Other: return i18n("Letter, Other");
00518     case QChar::Letter_Titlecase: return i18n("Letter, Titlecase");
00519     case QChar::Letter_Uppercase: return i18n("Letter, Uppercase");
00520     case QChar::Mark_SpacingCombining: return i18n("Mark, Spacing Combining");
00521     case QChar::Mark_Enclosing: return i18n("Mark, Enclosing");
00522     case QChar::Mark_NonSpacing: return i18n("Mark, Non-Spacing");
00523     case QChar::Number_DecimalDigit: return i18n("Number, Decimal Digit");
00524     case QChar::Number_Letter: return i18n("Number, Letter");
00525     case QChar::Number_Other: return i18n("Number, Other");
00526     case QChar::Punctuation_Connector: return i18n("Punctuation, Connector");
00527     case QChar::Punctuation_Dash: return i18n("Punctuation, Dash");
00528     case QChar::Punctuation_Close: return i18n("Punctuation, Close");
00529     case QChar::Punctuation_FinalQuote: return i18n("Punctuation, Final Quote");
00530     case QChar::Punctuation_InitialQuote: return i18n("Punctuation, Initial Quote");
00531     case QChar::Punctuation_Other: return i18n("Punctuation, Other");
00532     case QChar::Punctuation_Open: return i18n("Punctuation, Open");
00533     case QChar::Symbol_Currency: return i18n("Symbol, Currency");
00534     case QChar::Symbol_Modifier: return i18n("Symbol, Modifier");
00535     case QChar::Symbol_Math: return i18n("Symbol, Math");
00536     case QChar::Symbol_Other: return i18n("Symbol, Other");
00537     case QChar::Separator_Line: return i18n("Separator, Line");
00538     case QChar::Separator_Paragraph: return i18n("Separator, Paragraph");
00539     case QChar::Separator_Space: return i18n("Separator, Space");
00540     default: return i18n("Unknown");
00541     }
00542 }
00543 
00544 QList<QChar> KCharSelectData::find(const QString& needle)
00545 {
00546     QSet<quint16> result;
00547 
00548     QList<QChar> returnRes;
00549     QString simplified = needle.simplified();
00550     QStringList searchStrings = splitString(needle.simplified());
00551 
00552     if(simplified.length() == 1) {
00553         // search for hex representation of the character
00554         searchStrings = QStringList(formatCode(simplified.at(0).unicode()));
00555     }
00556 
00557     if (searchStrings.count() == 0) {
00558         return returnRes;
00559     }
00560 
00561     QRegExp regExp("^(|u\\+|U\\+|0x|0X)([A-Fa-f0-9]{4})$");
00562     foreach(const QString &s, searchStrings) {
00563         if(regExp.exactMatch(s)) {
00564             returnRes.append(regExp.cap(2).toInt(0, 16));
00565             // search for "1234" instead of "0x1234"
00566             if (s.length() == 6) {
00567                 searchStrings[searchStrings.indexOf(s)] = regExp.cap(2);
00568             }
00569         }
00570         // try to parse string as decimal number
00571         bool ok;
00572         int unicode = s.toInt(&ok);
00573         if (ok && unicode >= 0 && unicode <= 0xFFFF) {
00574             returnRes.append(unicode);
00575         }
00576     }
00577 
00578     bool firstSubString = true;
00579     foreach(const QString &s, searchStrings) {
00580         QSet<quint16> partResult = getMatchingChars(s.toLower());
00581         if (firstSubString) {
00582             result = partResult;
00583             firstSubString = false;
00584         } else {
00585             result = result.intersect(partResult);
00586         }
00587     }
00588 
00589     // remove results found by matching the code point to prevent duplicate results
00590     // while letting these characters stay at the beginning
00591     foreach(const QChar &c, returnRes) {
00592         result.remove(c.unicode());
00593     }
00594 
00595     QList<quint16> sortedResult = result.toList();
00596     qSort(sortedResult);
00597 
00598     foreach(const quint16 &c, sortedResult) {
00599         returnRes.append(c);
00600     }
00601 
00602     return returnRes;
00603 }
00604 
00605 QSet<quint16> KCharSelectData::getMatchingChars(const QString& s)
00606 {
00607     futureIndex.waitForFinished();
00608     const Index index = futureIndex;
00609     Index::const_iterator pos = index.lowerBound(s);
00610     QSet<quint16> result;
00611 
00612     while (pos != index.constEnd() && pos.key().startsWith(s)) {
00613         foreach (const quint16 &c, pos.value()) {
00614             result.insert(c);
00615         }
00616         ++pos;
00617     }
00618 
00619     return result;
00620 }
00621 
00622 QStringList KCharSelectData::splitString(const QString& s)
00623 {
00624     QStringList result;
00625     int start = 0;
00626     int end = 0;
00627     int length = s.length();
00628     while (end < length) {
00629         while (end < length && (s[end].isLetterOrNumber() || s[end] == '+')) {
00630             end++;
00631         }
00632         if (start != end) {
00633             result.append(s.mid(start, end - start));
00634         }
00635         start = end;
00636         while (end < length && !(s[end].isLetterOrNumber() || s[end] == '+')) {
00637             end++;
00638             start++;
00639         }
00640     }
00641     return result;
00642 }
00643 
00644 void KCharSelectData::appendToIndex(Index *index, quint16 unicode, const QString& s)
00645 {
00646     const QStringList strings = splitString(s);
00647     foreach(const QString &s, strings) {
00648         (*index)[s.toLower()].append(unicode);
00649     }
00650 }
00651 
00652 Index KCharSelectData::createIndex(const QByteArray& dataFile)
00653 {
00654     Index i;
00655 
00656     // character names
00657     const uchar* udata = reinterpret_cast<const uchar*>(dataFile.constData());
00658     const char* data = dataFile.constData();
00659     const quint32 nameOffsetBegin = qFromLittleEndian<quint32>(udata+4);
00660     const quint32 nameOffsetEnd = qFromLittleEndian<quint32>(udata+8);
00661 
00662     int max = ((nameOffsetEnd - nameOffsetBegin) / 6) - 1;
00663 
00664     for (int pos = 0; pos <= max; pos++) {
00665         const quint16 unicode = qFromLittleEndian<quint16>(udata + nameOffsetBegin + pos*6);
00666         quint32 offset = qFromLittleEndian<quint32>(udata + nameOffsetBegin + pos*6 + 2);
00667         appendToIndex(&i, unicode, QString(data + offset));
00668     }
00669 
00670     // details
00671     const quint32 detailsOffsetBegin = qFromLittleEndian<quint32>(udata+12);
00672     const quint32 detailsOffsetEnd = qFromLittleEndian<quint32>(udata+16);
00673 
00674     max = ((detailsOffsetEnd - detailsOffsetBegin) / 27) - 1;
00675 
00676     for (int pos = 0; pos <= max; pos++) {
00677         const quint16 unicode = qFromLittleEndian<quint16>(udata + detailsOffsetBegin + pos*27);
00678 
00679         // aliases
00680         const quint8 aliasCount = * (quint8 *)(udata + detailsOffsetBegin + pos*27 + 6);
00681         quint32 aliasOffset = qFromLittleEndian<quint32>(udata + detailsOffsetBegin + pos*27 + 2);
00682 
00683         for (int j = 0;  j < aliasCount;  j++) {
00684             appendToIndex(&i, unicode, QString::fromUtf8(data + aliasOffset));
00685             aliasOffset += strlen(data + aliasOffset) + 1;
00686         }
00687 
00688         // notes
00689         const quint8 notesCount = * (quint8 *)(udata + detailsOffsetBegin + pos*27 + 11);
00690         quint32 notesOffset = qFromLittleEndian<quint32>(udata + detailsOffsetBegin + pos*27 + 7);
00691 
00692         for (int j = 0;  j < notesCount;  j++) {
00693             appendToIndex(&i, unicode, QString::fromUtf8(data + notesOffset));
00694             notesOffset += strlen(data + notesOffset) + 1;
00695         }
00696 
00697         // approximate equivalents
00698         const quint8 apprCount = * (quint8 *)(udata + detailsOffsetBegin + pos*27 + 16);
00699         quint32 apprOffset = qFromLittleEndian<quint32>(udata + detailsOffsetBegin + pos*27 + 12);
00700 
00701         for (int j = 0;  j < apprCount;  j++) {
00702             appendToIndex(&i, unicode, QString::fromUtf8(data + apprOffset));
00703             apprOffset += strlen(data + apprOffset) + 1;
00704         }
00705 
00706         // equivalents
00707         const quint8 equivCount = * (quint8 *)(udata + detailsOffsetBegin + pos*27 + 21);
00708         quint32 equivOffset = qFromLittleEndian<quint32>(udata + detailsOffsetBegin + pos*27 + 17);
00709 
00710         for (int j = 0;  j < equivCount;  j++) {
00711             appendToIndex(&i, unicode, QString::fromUtf8(data + equivOffset));
00712             equivOffset += strlen(data + equivOffset) + 1;
00713         }
00714 
00715         // see also - convert to string (hex)
00716         const quint8 seeAlsoCount = * (quint8 *)(udata + detailsOffsetBegin + pos*27 + 26);
00717         quint32 seeAlsoOffset = qFromLittleEndian<quint32>(udata + detailsOffsetBegin + pos*27 + 22);
00718 
00719         for (int j = 0;  j < seeAlsoCount;  j++) {
00720             quint16 unicode = qFromLittleEndian<quint16> (udata + seeAlsoOffset);
00721             appendToIndex(&i, unicode, QString::number(unicode, 16));
00722             equivOffset += strlen(data + equivOffset) + 1;
00723         }
00724     }
00725 
00726     // unihan data
00727     // temporary disabled due to the huge amount of data
00728 //     const quint32 unihanOffsetBegin = qFromLittleEndian<quint32>(udata+36);
00729 //     const quint32 unihanOffsetEnd = dataFile.size();
00730 //     max = ((unihanOffsetEnd - unihanOffsetBegin) / 30) - 1;
00731 //
00732 //     for (int pos = 0; pos <= max; pos++) {
00733 //         const quint16 unicode = qFromLittleEndian<quint16>(udata + unihanOffsetBegin + pos*30);
00734 //         for(int j = 0; j < 7; j++) {
00735 //             quint32 offset = qFromLittleEndian<quint32>(udata + unihanOffsetBegin + pos*30 + 2 + j*4);
00736 //             if(offset != 0) {
00737 //                 appendToIndex(&i, unicode, QString::fromUtf8(data + offset));
00738 //             }
00739 //         }
00740 //     }
00741 
00742     return i;
00743 }

KDEUI

Skip menu "KDEUI"
  • 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
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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