File indexing completed on 2024-04-28 04:00:53

0001 /*
0002  * kspell_hspelldict.cpp
0003  *
0004  * SPDX-FileCopyrightText: 2003 Zack Rusin <zack@kde.org>
0005  * SPDX-FileCopyrightText: 2005 Mashrab Kuvatov <kmashrab@uni-bremen.de>
0006  * SPDX-FileCopyrightText: 2013 Martin Sandsmark <martin.sandsmark@kde.org>
0007  *
0008  * SPDX-License-Identifier: LGPL-2.1-or-later
0009  */
0010 
0011 #include "hspelldict.h"
0012 
0013 #include "hspell_debug.h"
0014 
0015 #include <QSettings>
0016 
0017 using namespace Sonnet;
0018 
0019 HSpellDict::HSpellDict(const QString &lang)
0020     : SpellerPlugin(lang)
0021 {
0022     int int_error = hspell_init(&m_speller, HSPELL_OPT_DEFAULT);
0023     if (int_error == -1) {
0024         qCWarning(SONNET_LOG_HSPELL) << "HSpellDict::HSpellDict: Init failed";
0025         initialized = false;
0026     } else {
0027         /* hspell understands only iso8859-8-i */
0028         m_decoder = QStringDecoder("iso8859-8-i");
0029         m_encoder = QStringEncoder("iso8859-8-i");
0030         initialized = true;
0031     }
0032 
0033     QSettings settings(QStringLiteral("KDE"), QStringLiteral("SonnetHSpellPlugin"));
0034     const QStringList personalWordsList = settings.value(QStringLiteral("PersonalWords"), QStringList()).toStringList();
0035     m_personalWords = QSet<QString>(personalWordsList.begin(), personalWordsList.end());
0036     QVariantHash replacementMap = settings.value(QStringLiteral("Replacements"), QVariant()).toHash();
0037     for (const QString &key : replacementMap.keys()) {
0038         m_replacements[key] = replacementMap[key].toString();
0039     }
0040 }
0041 
0042 HSpellDict::~HSpellDict()
0043 {
0044     /* It exists in =< hspell-0.8 */
0045     if (initialized) {
0046         hspell_uninit(m_speller);
0047     }
0048 }
0049 
0050 bool HSpellDict::isCorrect(const QString &word) const
0051 {
0052     if (m_sessionWords.contains(word)) {
0053         return true;
0054     }
0055 
0056     if (m_personalWords.contains(word)) {
0057         return true;
0058     }
0059 
0060     if (!initialized) {
0061         // Not much we can do, so just return true (less annoying for the user)
0062         return true;
0063     }
0064 
0065     int preflen;
0066     QByteArray wordISO = m_encoder.encode(word);
0067 
0068     // returns 1 if the word is correct, 0 otherwise
0069     int correct = hspell_check_word(m_speller, wordISO.constData(),
0070                                     &preflen); // this argument might be removed, it isn't useful
0071 
0072     // gimatria is a representation of numbers with hebrew letters, we accept these
0073     if (correct != 1) {
0074         if (hspell_is_canonic_gimatria(wordISO.constData()) != 0) {
0075             correct = 1;
0076         }
0077     }
0078     return correct == 1;
0079 }
0080 
0081 QStringList HSpellDict::suggest(const QString &word) const
0082 {
0083     QStringList suggestions;
0084 
0085     if (m_replacements.contains(word)) {
0086         suggestions.append(m_replacements[word]);
0087     }
0088 
0089     struct corlist correctionList;
0090     int suggestionCount;
0091     corlist_init(&correctionList);
0092     const QByteArray encodedWord = m_encoder.encode(word);
0093     hspell_trycorrect(m_speller, encodedWord.constData(), &correctionList);
0094     for (suggestionCount = 0; suggestionCount < corlist_n(&correctionList); suggestionCount++) {
0095         suggestions.append(m_decoder.decode(corlist_str(&correctionList, suggestionCount)));
0096     }
0097     corlist_free(&correctionList);
0098     return suggestions;
0099 }
0100 
0101 bool HSpellDict::storeReplacement(const QString &bad, const QString &good)
0102 {
0103     m_replacements[bad] = good;
0104     storePersonalWords();
0105     return true;
0106 }
0107 
0108 bool HSpellDict::addToPersonal(const QString &word)
0109 {
0110     m_personalWords.insert(word);
0111     storePersonalWords();
0112     return true;
0113 }
0114 
0115 bool HSpellDict::addToSession(const QString &word)
0116 {
0117     m_sessionWords.insert(word);
0118     return true;
0119 }
0120 
0121 void HSpellDict::storePersonalWords()
0122 {
0123     QSettings settings(QStringLiteral("KDE"), QStringLiteral("SonnetHSpellPlugin"));
0124     const QStringList personalWordsList(m_personalWords.begin(), m_personalWords.end());
0125     settings.setValue(QStringLiteral("PersonalWords"), QVariant(personalWordsList));
0126     QVariantHash variantHash;
0127     for (const QString &key : m_replacements.keys()) {
0128         variantHash[key] = QVariant(m_replacements[key]);
0129     }
0130     settings.setValue(QStringLiteral("Replacements"), variantHash);
0131 }