src/hbcore/inputfw/hbinputextrauserdictionary.cpp
branchGCC_SURGE
changeset 15 f378acbc9cfb
parent 6 c3690ec91ef8
child 28 b7da29130b0e
child 34 ed14f46c0e55
equal deleted inserted replaced
9:730c025d4b77 15:f378acbc9cfb
    20 **
    20 **
    21 ** If you have questions regarding the use of this file, please contact
    21 ** If you have questions regarding the use of this file, please contact
    22 ** Nokia at developer.feedback@nokia.com.
    22 ** Nokia at developer.feedback@nokia.com.
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
       
    25 #include "hbinputextrauserdictionary.h"
       
    26 #include "hbinputextrauserdictionary_p.h"
       
    27 
    25 #include <qbytearray.h> // For memmove()
    28 #include <qbytearray.h> // For memmove()
    26 
    29 
    27 #include <QFile>
    30 #include <QFile>
    28 #include <QDir>
    31 #include <QDir>
    29 #include <QSharedMemory>
    32 #include <QSharedMemory>
    30 #include <QVector>
    33 #include <QVector>
    31 
    34 
    32 #include "hbinputextrauserdictionary.h"
       
    33 #include "hbinputextrauserdictionary_p.h"
       
    34 #include "hbinputsettingproxy.h"
    35 #include "hbinputsettingproxy.h"
    35 
    36 
    36 const int HbExtraDictMaxFrequency = 255;
    37 const int HbExtraDictMaxFrequency = 255;
    37 
    38 
    38 /*!
    39 /*!
    63 
    64 
    64 /// @cond
    65 /// @cond
    65 
    66 
    66 bool HbExtraUserDictionaryPrivate::createSharedBlock(int aSize)
    67 bool HbExtraUserDictionaryPrivate::createSharedBlock(int aSize)
    67 {
    68 {
    68    if (sharedMemory.isAttached()) {
    69     if (sharedMemory.isAttached()) {
    69        return true;
    70         return true;
    70    }
    71     }
    71 
    72 
    72    if (id == 0) {
    73     if (id == 0) {
    73        return false;
    74         return false;
    74    }
    75     }
    75 
    76 
    76    sharedMemory.setKey(name());
    77     sharedMemory.setKey(name());
    77 
    78 
    78    if (!sharedMemory.attach()) {
    79     if (!sharedMemory.attach()) {
    79         if (sharedMemory.error() != QSharedMemory::NotFound) {
    80         if (sharedMemory.error() != QSharedMemory::NotFound) {
    80             qDebug("HbExtraUserDictionaryPrivate: QSharedMemory::attached returned error %d", sharedMemory.error());
    81             qDebug("HbExtraUserDictionaryPrivate: QSharedMemory::attached returned error %d", sharedMemory.error());
    81             return false;
    82             return false;
    82         }
    83         }
    83 
    84 
    88 
    89 
    89         dataHeader()->numWords = 0;
    90         dataHeader()->numWords = 0;
    90         dataHeader()->numUsers = 0;
    91         dataHeader()->numUsers = 0;
    91         dataHeader()->modified = false;
    92         dataHeader()->modified = false;
    92         dataHeader()->dataSize = 0;
    93         dataHeader()->dataSize = 0;
    93    }
    94     }
    94 
    95 
    95    dataHeader()->numUsers++;
    96     dataHeader()->numUsers++;
    96    return true;
    97     return true;
    97 }
    98 }
    98 
    99 
    99 QString HbExtraUserDictionaryPrivate::name() const
   100 QString HbExtraUserDictionaryPrivate::name() const
   100 {
   101 {
   101     QString num;
   102     QString num;
   109     return HbInputSettingProxy::extraDictionaryPath() + QDir::separator() + name() + QString(KExtraFileExt);
   110     return HbInputSettingProxy::extraDictionaryPath() + QDir::separator() + name() + QString(KExtraFileExt);
   110 }
   111 }
   111 
   112 
   112 bool HbExtraUserDictionaryPrivate::save(QString fileName)
   113 bool HbExtraUserDictionaryPrivate::save(QString fileName)
   113 {
   114 {
   114    QFile file(fileName);
   115     QFile file(fileName);
   115    if (file.open( QIODevice::WriteOnly )) {
   116     if (file.open(QIODevice::WriteOnly)) {
   116        file.write((char*)&id, sizeof(int));
   117         file.write((char *)&id, sizeof(int));
   117        if (sharedMemory.isAttached()) {
   118         if (sharedMemory.isAttached()) {
   118            file.write((char*)sharedMemory.data(), KExtraUDBlockSize);
   119             file.write((char *)sharedMemory.data(), KExtraUDBlockSize);
   119            }
   120         }
   120        file.close();
   121         file.close();
   121        dataHeader()->modified = false;
   122         dataHeader()->modified = false;
   122        return true;
   123         return true;
   123        }
   124     }
   124 
   125 
   125    return false;
   126     return false;
   126 }
   127 }
   127 
   128 
   128 int HbExtraUserDictionaryPrivate::findFirstMatch(int start, int end, const QString& searchString, int knownMatch, Qt::CaseSensitivity caseSensitivity) const
   129 int HbExtraUserDictionaryPrivate::findFirstMatch(int start, int end, const QString &searchString, int knownMatch, Qt::CaseSensitivity caseSensitivity) const
   129 {
   130 {
   130     HbExtraUDDirectoryEntry *dir = directory();
   131     HbExtraUDDirectoryEntry *dir = directory();
   131     QChar *data = dataArea();
   132     QChar *data = dataArea();
   132 
   133 
   133     if (start >= end) {
   134     if (start >= end) {
   139 
   140 
   140     int half = (start + end) / 2;
   141     int half = (start + end) / 2;
   141     if (QString(&data[dir[half].start], dir[half].length).startsWith(searchString, Qt::CaseInsensitive)) {
   142     if (QString(&data[dir[half].start], dir[half].length).startsWith(searchString, Qt::CaseInsensitive)) {
   142         knownMatch = half;
   143         knownMatch = half;
   143         return findFirstMatch(start, half, searchString, knownMatch, caseSensitivity);
   144         return findFirstMatch(start, half, searchString, knownMatch, caseSensitivity);
   144       }
   145     }
   145 
   146 
   146     if (compareWords(half, searchString, caseSensitivity) > 0) {
   147     if (compareWords(half, searchString, caseSensitivity) > 0) {
   147         return findFirstMatch(half + 1, end, searchString, knownMatch, caseSensitivity);
   148         return findFirstMatch(half + 1, end, searchString, knownMatch, caseSensitivity);
   148     }
   149     }
   149 
   150 
   161     // First move trailing directory entries and the beginning of the data area
   162     // First move trailing directory entries and the beginning of the data area
   162     // by size of one dictionary entry item.
   163     // by size of one dictionary entry item.
   163     memmove((char *)&dir[index], (char *)&dir[index + 1], (dataHeader()->numWords - index) * sizeof(HbExtraUDDirectoryEntry) + start * sizeof(QChar));
   164     memmove((char *)&dir[index], (char *)&dir[index + 1], (dataHeader()->numWords - index) * sizeof(HbExtraUDDirectoryEntry) + start * sizeof(QChar));
   164 
   165 
   165     // Then move trailing part of the data area.
   166     // Then move trailing part of the data area.
   166     memmove(((char*)&data[start]) - sizeof(HbExtraUDDirectoryEntry), (char*)&data[start + length], (dataHeader()->dataSize - (start + length)) * 2);
   167     memmove(((char *)&data[start]) - sizeof(HbExtraUDDirectoryEntry), (char *)&data[start + length], (dataHeader()->dataSize - (start + length)) * 2);
   167 
   168 
   168     // Update word count.
   169     // Update word count.
   169     dataHeader()->numWords--;
   170     dataHeader()->numWords--;
   170     dataHeader()->dataSize -= length;
   171     dataHeader()->dataSize -= length;
   171     dataHeader()->modified = true;
   172     dataHeader()->modified = true;
   172 
   173 
   173     // Then update remaining dictionary entries.
   174     // Then update remaining dictionary entries.
   174     const int rounds = dataHeader()->numWords;
   175     const int rounds = dataHeader()->numWords;
   175     for (int i = index; i < rounds; i++) {
   176     for (int i = index; i < rounds; i++) {
   176        dir[i].start -= length;
   177         dir[i].start -= length;
   177     }
   178     }
   178 }
   179 }
   179 
   180 
   180 void HbExtraUserDictionaryPrivate::addEntry(int index, const QString& newWord)
   181 void HbExtraUserDictionaryPrivate::addEntry(int index, const QString &newWord)
   181 {
   182 {
   182     HbExtraUDDirectoryEntry *dir = directory();
   183     HbExtraUDDirectoryEntry *dir = directory();
   183     QChar *data = dataArea();
   184     QChar *data = dataArea();
   184 
   185 
   185     const int origNumWords = dataHeader()->numWords;
   186     const int origNumWords = dataHeader()->numWords;
   186     if (origNumWords > 0) {
   187     if (origNumWords > 0) {
   187         if (index < origNumWords) {
   188         if (index < origNumWords) {
   188             // First move the trailing part of the data area to make space for the new word.
   189             // First move the trailing part of the data area to make space for the new word.
   189             memmove((char*)&data[dir[index].start + newWord.size()] + sizeof(HbExtraUDDirectoryEntry),
   190             memmove((char *)&data[dir[index].start + newWord.size()] + sizeof(HbExtraUDDirectoryEntry),
   190                     (char*)(&data[dir[index].start]),
   191                     (char *)(&data[dir[index].start]),
   191                     (dataHeader()->dataSize - dir[index].start) * 2);
   192                     (dataHeader()->dataSize - dir[index].start) * 2);
   192 
   193 
   193             // Then move the trailing part of the dictionary and the leading part of the data area.
   194             // Then move the trailing part of the dictionary and the leading part of the data area.
   194             memmove((char*)(&dir[index + 1]),
   195             memmove((char *)(&dir[index + 1]),
   195                     (char*)(&dir[index]),
   196                     (char *)(&dir[index]),
   196                     ((dataHeader()->numWords - index) * sizeof(HbExtraUDDirectoryEntry)) + (dir[index].start * 2));
   197                     ((dataHeader()->numWords - index) * sizeof(HbExtraUDDirectoryEntry)) + (dir[index].start * 2));
   197         } else {
   198         } else {
   198             // This will be the last one. Just make room for new directory entry.
   199             // This will be the last one. Just make room for new directory entry.
   199             memmove((char*)data + sizeof(HbExtraUDDirectoryEntry),
   200             memmove((char *)data + sizeof(HbExtraUDDirectoryEntry),
   200                     (char*)data,
   201                     (char *)data,
   201                     dataHeader()->dataSize * 2);
   202                     dataHeader()->dataSize * 2);
   202        }
   203         }
   203     }
   204     }
   204 
   205 
   205     // Update word count.
   206     // Update word count.
   206     dataHeader()->numWords++;
   207     dataHeader()->numWords++;
   207     dataHeader()->dataSize += newWord.size();
   208     dataHeader()->dataSize += newWord.size();
   223     }
   224     }
   224 
   225 
   225     // Then update remaining dictionary entries.
   226     // Then update remaining dictionary entries.
   226     const int rounds = dataHeader()->numWords;
   227     const int rounds = dataHeader()->numWords;
   227     for (int i = index + 1; i < rounds; i++) {
   228     for (int i = index + 1; i < rounds; i++) {
   228        dir[i].start += newWord.size();
   229         dir[i].start += newWord.size();
   229     }
   230     }
   230 }
   231 }
   231 
   232 
   232 int HbExtraUserDictionaryPrivate::findWord(int startIndex, int endIndex, const QString& newWord, Qt::CaseSensitivity caseSensitivity) const
   233 int HbExtraUserDictionaryPrivate::findWord(int startIndex, int endIndex, const QString &newWord, Qt::CaseSensitivity caseSensitivity) const
   233 {
   234 {
   234     if (startIndex >= endIndex) {
   235     if (startIndex >= endIndex) {
   235         if (startIndex < dataHeader()->numWords && compareWords(startIndex, newWord, caseSensitivity) == 0) {
   236         if (startIndex < dataHeader()->numWords && compareWords(startIndex, newWord, caseSensitivity) == 0) {
   236             return startIndex;
   237             return startIndex;
   237         }
   238         }
   248     } else {
   249     } else {
   249         return findWord(startIndex, half, newWord, caseSensitivity);
   250         return findWord(startIndex, half, newWord, caseSensitivity);
   250     }
   251     }
   251 }
   252 }
   252 
   253 
   253 int HbExtraUserDictionaryPrivate::findIndexForNewWord(int start, int end, const QString& newWord) const
   254 int HbExtraUserDictionaryPrivate::findIndexForNewWord(int start, int end, const QString &newWord) const
   254 {
   255 {
   255     if (start >= end) {
   256     if (start >= end) {
   256         if (dataHeader()->numWords == 0) {
   257         if (dataHeader()->numWords == 0) {
   257             return 0;
   258             return 0;
   258         }
   259         }
   273     } else {
   274     } else {
   274         return findIndexForNewWord(start, half, newWord);
   275         return findIndexForNewWord(start, half, newWord);
   275     }
   276     }
   276 }
   277 }
   277 
   278 
   278 int HbExtraUserDictionaryPrivate::compareWords(int index, const QString& otherWord, Qt::CaseSensitivity caseSensitivity) const
   279 int HbExtraUserDictionaryPrivate::compareWords(int index, const QString &otherWord, Qt::CaseSensitivity caseSensitivity) const
   279 {
   280 {
   280     HbExtraUDDirectoryEntry *dir = directory();
   281     HbExtraUDDirectoryEntry *dir = directory();
   281     QChar *data = dataArea();
   282     QChar *data = dataArea();
   282 
   283 
   283     const int start = dir[index].start;
   284     const int start = dir[index].start;
   284     const int rounds = (dir[index].length > otherWord.size() ? otherWord.size() : dir[index].length);
   285     const int rounds = (dir[index].length > otherWord.size() ? otherWord.size() : dir[index].length);
   285         if (caseSensitivity == Qt::CaseSensitive) {
   286     if (caseSensitivity == Qt::CaseSensitive) {
   286                 for (int i = 0; i < rounds; i++) {
   287         for (int i = 0; i < rounds; i++) {
   287                         if (data[start + i] == otherWord[i]) {
   288             if (data[start + i] == otherWord[i]) {
   288                                 continue;
   289                 continue;
   289                         }
   290             }
   290 
   291 
   291                         if (otherWord[i] > data[start + i]) {
   292             if (otherWord[i] > data[start + i]) {
   292                                 return 1;
   293                 return 1;
   293                         }
   294             }
   294 
   295 
   295                         return -1;
   296             return -1;
   296                 }
   297         }
   297         } else {
   298     } else {
   298                 for (int i = 0; i < rounds; i++) {
   299         for (int i = 0; i < rounds; i++) {
   299                         if (data[start + i].toCaseFolded() == otherWord[i].toCaseFolded()) {
   300             if (data[start + i].toCaseFolded() == otherWord[i].toCaseFolded()) {
   300                                 continue;
   301                 continue;
   301                         }
   302             }
   302 
   303 
   303                         if (otherWord[i].toCaseFolded() > data[start + i].toCaseFolded()) {
   304             if (otherWord[i].toCaseFolded() > data[start + i].toCaseFolded()) {
   304                                 return 1;
   305                 return 1;
   305                         }
   306             }
   306 
   307 
   307                         return -1;
   308             return -1;
   308                 }
   309         }
   309         }
   310     }
   310 
   311 
   311     if (dir[index].length == otherWord.size()) {
   312     if (dir[index].length == otherWord.size()) {
   312         return 0;  // Match!
   313         return 0;  // Match!
   313     }
   314     }
   314 
   315 
   317     }
   318     }
   318 
   319 
   319     return -1;
   320     return -1;
   320 }
   321 }
   321 
   322 
   322 bool HbExtraUserDictionaryPrivate::hasEnoughSpaceForNewWord(const QString& newWord) const
   323 bool HbExtraUserDictionaryPrivate::hasEnoughSpaceForNewWord(const QString &newWord) const
   323 {
   324 {
   324     if ((unsigned int)dataAreaSize() - (dataHeader()->dataSize * 2) >= (newWord.size() * 2) + sizeof(HbExtraUDDirectoryEntry)) {
   325     if ((unsigned int)dataAreaSize() - (dataHeader()->dataSize * 2) >= (newWord.size() * 2) + sizeof(HbExtraUDDirectoryEntry)) {
   325         return true;
   326         return true;
   326     }
   327     }
   327 
   328 
   375     return d->id;
   376     return d->id;
   376 }
   377 }
   377 
   378 
   378 /*!
   379 /*!
   379 Adds single word to the database. Returns true if there was enough space for new
   380 Adds single word to the database. Returns true if there was enough space for new
   380 word and the word was succesfully added. Returns false if word already
   381 word and the word was successfully added. Returns false if word already
   381 exists.
   382 exists.
   382 
   383 
   383 \sa addWords
   384 \sa addWords
   384 \sa removeWord
   385 \sa removeWord
   385 */
   386 */
   386 bool HbExtraUserDictionary::addWord(const QString& newWord, HbPredictionCallback* callback)
   387 bool HbExtraUserDictionary::addWord(const QString &newWord, HbPredictionCallback *callback)
   387 {
   388 {
   388     Q_UNUSED(callback);
   389     Q_UNUSED(callback);
   389     Q_D(HbExtraUserDictionary);
   390     Q_D(HbExtraUserDictionary);
   390 
   391 
   391     d->lock();
   392     d->lock();
   397     }
   398     }
   398 
   399 
   399     if (newWord.size() < KExtraUserDictionaryMaxWordLength &&
   400     if (newWord.size() < KExtraUserDictionaryMaxWordLength &&
   400         d->hasEnoughSpaceForNewWord(newWord) &&
   401         d->hasEnoughSpaceForNewWord(newWord) &&
   401         d->dataHeader()->numWords < KExtraUserDictionaryMaxWords) {
   402         d->dataHeader()->numWords < KExtraUserDictionaryMaxWords) {
   402        int newIndex = d->findIndexForNewWord(0, d->dataHeader()->numWords - 1, newWord);
   403         int newIndex = d->findIndexForNewWord(0, d->dataHeader()->numWords - 1, newWord);
   403        d->addEntry(newIndex, newWord);
   404         d->addEntry(newIndex, newWord);
   404 
   405 
   405        d->unlock();
   406         d->unlock();
   406        return true;
   407         return true;
   407        }
   408     }
   408 
   409 
   409     d->unlock();
   410     d->unlock();
   410     return false;
   411     return false;
   411 }
   412 }
   412 
   413 
   415 successfully added to the database.
   416 successfully added to the database.
   416 
   417 
   417 \sa addWord
   418 \sa addWord
   418 \sa removeWord
   419 \sa removeWord
   419 */
   420 */
   420 bool HbExtraUserDictionary::addWords(const QStringList& wordList)
   421 bool HbExtraUserDictionary::addWords(const QStringList &wordList)
   421 {
   422 {
   422     bool ret = true;
   423     bool ret = true;
   423 
   424 
   424     for (int i = 0; i < wordList.count(); i++) {
   425     for (int i = 0; i < wordList.count(); i++) {
   425         ret &= addWord(wordList[i]);
   426         ret &= addWord(wordList[i]);
   432 Removes a word from the database. Returns true if the word was found and removed.
   433 Removes a word from the database. Returns true if the word was found and removed.
   433 
   434 
   434 \sa addWord
   435 \sa addWord
   435 \sa addWords
   436 \sa addWords
   436 */
   437 */
   437 bool HbExtraUserDictionary::removeWord(const QString& toBeRemoved)
   438 bool HbExtraUserDictionary::removeWord(const QString &toBeRemoved)
   438 {
   439 {
   439     Q_D(HbExtraUserDictionary);
   440     Q_D(HbExtraUserDictionary);
   440 
   441 
   441     d->lock();
   442     d->lock();
   442 
   443 
   443     int index = d->findWord(0, d->dataHeader()->numWords - 1, toBeRemoved, Qt::CaseInsensitive);
   444     int index = d->findWord(0, d->dataHeader()->numWords - 1, toBeRemoved, Qt::CaseInsensitive);
   444     if (index >= 0) {
   445     if (index >= 0) {
   445        d->removeEntry(index);
   446         d->removeEntry(index);
   446        d->unlock();
   447         d->unlock();
   447        return true;
   448         return true;
   448     }
   449     }
   449 
   450 
   450     d->unlock();
   451     d->unlock();
   451     return false;
   452     return false;
   452 }
   453 }
   515 
   516 
   516 /*!
   517 /*!
   517 Returns all the dictionary words that begin with contents of searchString.
   518 Returns all the dictionary words that begin with contents of searchString.
   518 Search is case insensitive. Empty string will match to all words.
   519 Search is case insensitive. Empty string will match to all words.
   519 */
   520 */
   520 QStringList HbExtraUserDictionary::findMatches(const QString& searchString, bool sortByFrequency, Qt::CaseSensitivity caseSensitivity)
   521 QStringList HbExtraUserDictionary::findMatches(const QString &searchString, bool sortByFrequency, Qt::CaseSensitivity caseSensitivity)
   521 {
   522 {
   522     Q_UNUSED(caseSensitivity);  // Will be taken into use...
   523     Q_UNUSED(caseSensitivity);  // Will be taken into use...
   523     Q_D(HbExtraUserDictionary);
   524     Q_D(HbExtraUserDictionary);
   524 
   525 
   525     QVector<unsigned char> frequencies;
   526     QVector<unsigned char> frequencies;
   570 }
   571 }
   571 
   572 
   572 /*!
   573 /*!
   573 Returns pointer to host prediction engine.
   574 Returns pointer to host prediction engine.
   574 */
   575 */
   575 HbPredictionBase* HbExtraUserDictionary::hostEngine() const
   576 HbPredictionBase *HbExtraUserDictionary::hostEngine() const
   576 {
   577 {
   577     Q_D(const HbExtraUserDictionary);
   578     Q_D(const HbExtraUserDictionary);
   578     return d->hostEngine;
   579     return d->hostEngine;
   579 }
   580 }
   580 
   581 
   581 /*!
   582 /*!
   582 Sets host prediction engine.
   583 Sets host prediction engine.
   583 */
   584 */
   584 void HbExtraUserDictionary::setHostEngine(HbPredictionBase* host)
   585 void HbExtraUserDictionary::setHostEngine(HbPredictionBase *host)
   585 {
   586 {
   586     Q_D(HbExtraUserDictionary);
   587     Q_D(HbExtraUserDictionary);
   587     d->hostEngine = host;
   588     d->hostEngine = host;
   588 }
   589 }
   589 
   590 
   590 /*!
   591 /*!
   591 Loads dictionary from disk.
   592 Loads dictionary from disk.
   592 */
   593 */
   593 bool HbExtraUserDictionary::load(const QString& nameOfTheFile)
   594 bool HbExtraUserDictionary::load(const QString &nameOfTheFile)
   594 {
   595 {
   595    Q_D(HbExtraUserDictionary);
   596     Q_D(HbExtraUserDictionary);
   596 
   597 
   597    QString realFileName = nameOfTheFile;
   598     QString realFileName = nameOfTheFile;
   598    if (realFileName.size() == 0) {
   599     if (realFileName.size() == 0) {
   599        realFileName = fileName();
   600         realFileName = fileName();
   600    }
   601     }
   601 
   602 
   602    if (attach()) {
   603     if (attach()) {
   603        d->lock();
   604         d->lock();
   604        QFile file(realFileName);
   605         QFile file(realFileName);
   605        if (file.open( QIODevice::ReadOnly )) {
   606         if (file.open(QIODevice::ReadOnly)) {
   606            int numUsers = d->dataHeader()->numUsers;
   607             int numUsers = d->dataHeader()->numUsers;
   607            file.read((char*)&d->id, sizeof(int));
   608             file.read((char *)&d->id, sizeof(int));
   608            file.read((char*)d->sharedMemory.data(), KExtraUDBlockSize);
   609             file.read((char *)d->sharedMemory.data(), KExtraUDBlockSize);
   609            file.close();
   610             file.close();
   610            d->dataHeader()->numUsers = numUsers;
   611             d->dataHeader()->numUsers = numUsers;
   611            d->unlock();
   612             d->unlock();
   612            return true;
   613             return true;
   613        }
   614         }
   614        d->unlock();
   615         d->unlock();
   615    }
   616     }
   616 
   617 
   617    return false;
   618     return false;
   618 }
   619 }
   619 
   620 
   620 /*!
   621 /*!
   621 Saves dictionary to disk. If no file name is give, fileName() will
   622 Saves dictionary to disk. If no file name is give, fileName() will
   622 be used.
   623 be used.
   623 
   624 
   624 \sa fileName
   625 \sa fileName
   625 */
   626 */
   626 bool HbExtraUserDictionary::save(const QString& nameOfTheFile)
   627 bool HbExtraUserDictionary::save(const QString &nameOfTheFile)
   627 {
   628 {
   628    Q_D(HbExtraUserDictionary);
   629     Q_D(HbExtraUserDictionary);
   629 
   630 
   630    QString realFileName = nameOfTheFile;
   631     QString realFileName = nameOfTheFile;
   631    if (realFileName.size() == 0) {
   632     if (realFileName.size() == 0) {
   632        realFileName = fileName();
   633         realFileName = fileName();
   633    }
   634     }
   634 
   635 
   635    bool ret = false;
   636     bool ret = false;
   636    d->lock();
   637     d->lock();
   637    ret = d->save(realFileName);
   638     ret = d->save(realFileName);
   638    d->unlock();
   639     d->unlock();
   639 
   640 
   640    return ret;
   641     return ret;
   641 }
   642 }
   642 
   643 
   643 /*!
   644 /*!
   644 Sets dictionary id.
   645 Sets dictionary id.
   645 */
   646 */
   705 This method is provided for sake of efficiency for those who need direct access and know what they are doing.
   706 This method is provided for sake of efficiency for those who need direct access and know what they are doing.
   706 
   707 
   707 \sa rawDataAreaSize
   708 \sa rawDataAreaSize
   708 \sa directory
   709 \sa directory
   709 */
   710 */
   710 QChar* HbExtraUserDictionary::rawDataArea() const
   711 QChar *HbExtraUserDictionary::rawDataArea() const
   711 {
   712 {
   712     Q_D(const HbExtraUserDictionary);
   713     Q_D(const HbExtraUserDictionary);
   713     return d->dataArea();
   714     return d->dataArea();
   714 }
   715 }
   715 
   716 
   758 }
   759 }
   759 
   760 
   760 /*!
   761 /*!
   761 Increases word frequency counter for given word if it is in the dictionary.
   762 Increases word frequency counter for given word if it is in the dictionary.
   762 */
   763 */
   763 void HbExtraUserDictionary::incrementUseCount(const QString& word)
   764 void HbExtraUserDictionary::incrementUseCount(const QString &word)
   764 {
   765 {
   765     Q_D(const HbExtraUserDictionary);
   766     Q_D(const HbExtraUserDictionary);
   766 
   767 
   767     if (d->dataHeader()->numWords) {
   768     if (d->dataHeader()->numWords) {
   768         HbExtraUDDirectoryEntry *dir = d->directory();
   769         HbExtraUDDirectoryEntry *dir = d->directory();
   769 
   770 
   770         int first = d->findFirstMatch(0, d->dataHeader()->numWords - 1, word);
   771         int first = d->findFirstMatch(0, d->dataHeader()->numWords - 1, word);
   771         if (first >= 0 && dir[first].frequency < HbExtraDictMaxFrequency) {
   772         if (first >= 0 && dir[first].frequency < HbExtraDictMaxFrequency) {
   772             dir[first].frequency++;
   773             dir[first].frequency++;
   773             d->dataHeader()->modified = true;
   774             d->dataHeader()->modified = true;
   774             }
   775         }
   775         }
   776     }
   776 }
   777 }
   777 
   778 
   778 /*!
   779 /*!
   779 Returns true if given word exits in the dictionary.
   780 Returns true if given word exits in the dictionary.
   780 */
   781 */
   781 bool HbExtraUserDictionary::hasWord(const QString& word, Qt::CaseSensitivity caseSensitivity) const
   782 bool HbExtraUserDictionary::hasWord(const QString &word, Qt::CaseSensitivity caseSensitivity) const
   782 {
   783 {
   783     Q_D(const HbExtraUserDictionary);
   784     Q_D(const HbExtraUserDictionary);
   784 
   785 
   785     if (d->dataHeader()->numWords) {
   786     if (d->dataHeader()->numWords) {
   786         QChar *data = d->dataArea();
   787         QChar *data = d->dataArea();
   787         HbExtraUDDirectoryEntry *dir = d->directory();
   788         HbExtraUDDirectoryEntry *dir = d->directory();
   788             int first = d->findFirstMatch(0, d->dataHeader()->numWords - 1, word,-1, caseSensitivity);
   789         int first = d->findFirstMatch(0, d->dataHeader()->numWords - 1, word, -1, caseSensitivity);
   789             if (first >= 0) {
   790         if (first >= 0) {
   790                 if (caseSensitivity == Qt::CaseSensitive) {
   791             if (caseSensitivity == Qt::CaseSensitive) {
   791                     if (QString(&data[dir[first].start], dir[first].length) == word) {
   792                 if (QString(&data[dir[first].start], dir[first].length) == word) {
   792                         return true;
   793                     return true;
       
   794                 }
       
   795 
       
   796                 const int rounds = d->dataHeader()->numWords;
       
   797                 for (int i = first + 1; i <= rounds; i++) {
       
   798                     QString candidate(&data[dir[i].start], dir[i].length);
       
   799                     if (candidate.startsWith(word, Qt::CaseInsensitive)) {
       
   800                         if (candidate == word) {
       
   801                             return true;
       
   802                         }
       
   803                     } else {
       
   804                         break;
   793                     }
   805                     }
   794 
   806                 }
   795                     const int rounds = d->dataHeader()->numWords;
       
   796                     for (int i = first + 1; i <= rounds; i++) {
       
   797                          QString candidate(&data[dir[i].start], dir[i].length);
       
   798                          if (candidate.startsWith(word, Qt::CaseInsensitive)) {
       
   799                              if (candidate == word) {
       
   800                                  return true;
       
   801                              }
       
   802                          } else {
       
   803                              break;
       
   804                          }
       
   805                     }
       
   806             } else {
   807             } else {
   807                 if (QString(&data[dir[first].start], dir[first].length).toCaseFolded() == word.toCaseFolded()) {
   808                 if (QString(&data[dir[first].start], dir[first].length).toCaseFolded() == word.toCaseFolded()) {
   808                     return true;
   809                     return true;
   809                 }
   810                 }
   810                 const int rounds = d->dataHeader()->numWords;
   811                 const int rounds = d->dataHeader()->numWords;
   816                         }
   817                         }
   817                     } else {
   818                     } else {
   818                         break;
   819                         break;
   819                     }
   820                     }
   820                 }
   821                 }
   821            }
   822             }
   822         }
   823         }
   823     }
   824     }
   824 
   825 
   825     return false;
   826     return false;
   826 }
   827 }