00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00083
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);
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
00221 return "CJK UNIFIED IDEOGRAPH-" + QString::number(unicode, 16);
00222 } else if (c >= 0xac00 && c <= 0xd7af) {
00223
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
00244
00245
00246
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
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
00566 if (s.length() == 6) {
00567 searchStrings[searchStrings.indexOf(s)] = regExp.cap(2);
00568 }
00569 }
00570
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
00590
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
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
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
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
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
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
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
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
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 return i;
00743 }