File indexing completed on 2024-05-12 15:49:37

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 #include <QTextCodec>
0017 
0018 using namespace Sonnet;
0019 
0020 HSpellDict::HSpellDict(const QString &lang)
0021     : SpellerPlugin(lang)
0022 {
0023     int int_error = hspell_init(&m_speller, HSPELL_OPT_DEFAULT);
0024     if (int_error == -1) {
0025         qCWarning(SONNET_LOG_HSPELL) << "HSpellDict::HSpellDict: Init failed";
0026         initialized = false;
0027     } else {
0028         /* hspell understands only iso8859-8-i */
0029         codec = QTextCodec::codecForName("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 = codec->fromUnicode(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     hspell_trycorrect(m_speller, codec->fromUnicode(word).constData(), &correctionList);
0093     for (suggestionCount = 0; suggestionCount < corlist_n(&correctionList); suggestionCount++) {
0094         suggestions.append(codec->toUnicode(corlist_str(&correctionList, suggestionCount)));
0095     }
0096     corlist_free(&correctionList);
0097     return suggestions;
0098 }
0099 
0100 bool HSpellDict::storeReplacement(const QString &bad, const QString &good)
0101 {
0102     m_replacements[bad] = good;
0103     storePersonalWords();
0104     return true;
0105 }
0106 
0107 bool HSpellDict::addToPersonal(const QString &word)
0108 {
0109     m_personalWords.insert(word);
0110     storePersonalWords();
0111     return true;
0112 }
0113 
0114 bool HSpellDict::addToSession(const QString &word)
0115 {
0116     m_sessionWords.insert(word);
0117     return true;
0118 }
0119 
0120 void HSpellDict::storePersonalWords()
0121 {
0122     QSettings settings(QStringLiteral("KDE"), QStringLiteral("SonnetHSpellPlugin"));
0123     const QStringList personalWordsList(m_personalWords.begin(), m_personalWords.end());
0124     settings.setValue(QStringLiteral("PersonalWords"), QVariant(personalWordsList));
0125     QVariantHash variantHash;
0126     for (const QString &key : m_replacements.keys()) {
0127         variantHash[key] = QVariant(m_replacements[key]);
0128     }
0129     settings.setValue(QStringLiteral("Replacements"), variantHash);
0130 }