diff options
author | George Hazan <george.hazan@gmail.com> | 2024-11-26 16:55:51 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-11-26 16:55:51 +0300 |
commit | 15b337d3f4caa3fa71160dc93b7caf4f2c098b06 (patch) | |
tree | 140b1c2923ef84108c6e85fdc2403a21d47f106c /plugins/SpellChecker | |
parent | 70cd3610f4ec0131fe3c9308a483935e9f1c788c (diff) |
fixes #4692 (SpellChecker to use the native Windows speller if present)
Diffstat (limited to 'plugins/SpellChecker')
-rw-r--r-- | plugins/SpellChecker/spellchecker.vcxproj | 1 | ||||
-rw-r--r-- | plugins/SpellChecker/spellchecker.vcxproj.filters | 3 | ||||
-rw-r--r-- | plugins/SpellChecker/src/dictionary.cpp | 45 | ||||
-rw-r--r-- | plugins/SpellChecker/src/dictionary.h | 8 | ||||
-rw-r--r-- | plugins/SpellChecker/src/hunspell.cpp | 29 | ||||
-rw-r--r-- | plugins/SpellChecker/src/native.cpp | 145 | ||||
-rw-r--r-- | plugins/SpellChecker/src/spellchecker.cpp | 1 | ||||
-rw-r--r-- | plugins/SpellChecker/src/stdafx.h | 1 | ||||
-rw-r--r-- | plugins/SpellChecker/src/version.h | 6 |
9 files changed, 178 insertions, 61 deletions
diff --git a/plugins/SpellChecker/spellchecker.vcxproj b/plugins/SpellChecker/spellchecker.vcxproj index 570332771c..ebafe54ef1 100644 --- a/plugins/SpellChecker/spellchecker.vcxproj +++ b/plugins/SpellChecker/spellchecker.vcxproj @@ -33,6 +33,7 @@ <ClCompile Include="src\autoreplace.cpp" />
<ClCompile Include="src\dictionary.cpp" />
<ClCompile Include="src\hunspell.cpp" />
+ <ClCompile Include="src\native.cpp" />
<ClCompile Include="src\options.cpp" />
<ClCompile Include="src\RichEdit.cpp" />
<ClCompile Include="src\spellchecker.cpp" />
diff --git a/plugins/SpellChecker/spellchecker.vcxproj.filters b/plugins/SpellChecker/spellchecker.vcxproj.filters index d53fe3bae2..6140ec504f 100644 --- a/plugins/SpellChecker/spellchecker.vcxproj.filters +++ b/plugins/SpellChecker/spellchecker.vcxproj.filters @@ -32,6 +32,9 @@ <ClCompile Include="src\hunspell.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\native.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\ardialog.h">
diff --git a/plugins/SpellChecker/src/dictionary.cpp b/plugins/SpellChecker/src/dictionary.cpp index 83bbefd5ce..de8464eb98 100644 --- a/plugins/SpellChecker/src/dictionary.cpp +++ b/plugins/SpellChecker/src/dictionary.cpp @@ -57,7 +57,7 @@ static aditionalLanguages[] = { ///////////////////////////////////////////////////////////////////////////////////////// // To get the names of the languages -void Dictionary::GetInfo() +bool Dictionary::GetInfo() { for (auto &it : g_plugin.locales) { if (mir_wstrcmpi(language, it.first.c_str()) == 0) { @@ -82,35 +82,34 @@ void Dictionary::GetInfo() mir_wstrncpy(localized_name, TranslateW(localName), _countof(localized_name)); } - if (localized_name[0] != 0) - mir_snwprintf(full_name, L"%s [%s]", localized_name, language); - - break; + mir_snwprintf(full_name, L"%s [%s]", localized_name, language); + return true; } } - if (full_name[0] == '\0') { - DBVARIANT dbv; + DBVARIANT dbv; - char lang[128]; - WideCharToMultiByte(CP_ACP, 0, language, -1, lang, sizeof(lang), nullptr, nullptr); - if (!g_plugin.getWString(lang, &dbv)) { - mir_wstrncpy(localized_name, dbv.pwszVal, _countof(localized_name)); - db_free(&dbv); - } + char lang[128]; + WideCharToMultiByte(CP_ACP, 0, language, -1, lang, sizeof(lang), nullptr, nullptr); + if (!g_plugin.getWString(lang, &dbv)) { + mir_wstrncpy(localized_name, dbv.pwszVal, _countof(localized_name)); + db_free(&dbv); + } - if (localized_name[0] == '\0') { - for (auto &it : aditionalLanguages) { - if (!mir_wstrcmp(it.language, language)) { - mir_wstrncpy(localized_name, TranslateW(it.localized_name), _countof(localized_name)); - break; - } + if (localized_name[0] == '\0') { + for (auto &it : aditionalLanguages) { + if (!mir_wstrcmp(it.language, language)) { + mir_wstrncpy(localized_name, TranslateW(it.localized_name), _countof(localized_name)); + break; } } + } - if (localized_name[0] != '\0') - mir_snwprintf(full_name, L"%s [%s]", localized_name, language); - else - mir_wstrncpy(full_name, language, _countof(full_name)); + if (localized_name[0] != '\0') { + mir_snwprintf(full_name, L"%s [%s]", localized_name, language); + return true; } + + mir_wstrncpy(full_name, language, _countof(full_name)); + return false; } diff --git a/plugins/SpellChecker/src/dictionary.h b/plugins/SpellChecker/src/dictionary.h index 8ba9ee2acf..daad917ddc 100644 --- a/plugins/SpellChecker/src/dictionary.h +++ b/plugins/SpellChecker/src/dictionary.h @@ -38,7 +38,7 @@ struct Dictionary Dictionary(const wchar_t *aLanguage, const wchar_t *aSource);
virtual ~Dictionary();
- void GetInfo();
+ bool GetInfo();
// Return TRUE if the word is correct
virtual BOOL spell(const wchar_t *word) = 0;
@@ -46,9 +46,6 @@ struct Dictionary // Return a list of suggestions to a word
virtual Suggestions suggest(const wchar_t *word) = 0;
- // Return a list of auto suggestions to a word
- virtual Suggestions autoSuggest(const wchar_t *word) = 0;
-
// Return a auto suggestions to a word
// You have to free the item
virtual wchar_t* autoSuggestOne(const wchar_t *word) = 0;
@@ -71,5 +68,6 @@ struct Dictionary // Return a list of avaible languages
void GetAvaibleDictionaries(OBJLIST<Dictionary> &dicts, wchar_t *path, wchar_t *user_path);
-
+void GetNativeDictionaries(OBJLIST<Dictionary> &dicts);
+
#endif // __DICTIONARY_H__
diff --git a/plugins/SpellChecker/src/hunspell.cpp b/plugins/SpellChecker/src/hunspell.cpp index ebf76d5c88..d5e953dc32 100644 --- a/plugins/SpellChecker/src/hunspell.cpp +++ b/plugins/SpellChecker/src/hunspell.cpp @@ -590,35 +590,6 @@ public: } // Return a list of auto suggestions to a word - virtual Suggestions autoSuggest(const wchar_t * word) - { - Suggestions ret; - - load(); - if (loaded != LANGUAGE_LOADED) - return ret; - - char hunspell_word[1024]; - toHunspell(hunspell_word, word, _countof(hunspell_word)); - - char **words; - int count = hunspell->suggest(&words, hunspell_word); - if (count <= 0) - return ret; - - // Oki, lets make our array - for (int i = 0; i < count; i++) { - auto *p = fromHunspell(words[i]); - ret.push_back(p); - free(p); - free(words[i]); - } - free(words); - - return ret; - } - - // Return a list of auto suggestions to a word // You have to free the list AND each item virtual wchar_t * autoSuggestOne(const wchar_t * word) { diff --git a/plugins/SpellChecker/src/native.cpp b/plugins/SpellChecker/src/native.cpp new file mode 100644 index 0000000000..b80ab78ea5 --- /dev/null +++ b/plugins/SpellChecker/src/native.cpp @@ -0,0 +1,145 @@ +/* +Copyright (C) 2006-2010 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +struct NativeDictionary : public Dictionary +{ + CComPtr<ISpellChecker> m_speller; + + NativeDictionary(const wchar_t *wszLanguage) : + Dictionary(wszLanguage, 0) + { + if (auto *p = wcschr(language, '-')) + *p = '_'; + + g_plugin.m_spellFactory->CreateSpellChecker(wszLanguage, &m_speller); + + if (!GetInfo()) + if (auto *p = wcschr(full_name, '_')) + *p = '-'; + } + + virtual ~NativeDictionary() + { + } + + // Return TRUE if the word is correct + virtual BOOL spell(const wchar_t *word) + { + CComPtr<IEnumSpellingError> error; + if (FAILED(m_speller->Check(word, &error))) + return FALSE; + + CComPtr<ISpellingError> err; + if (FAILED(error->Next(&err))) + return FALSE; + + return err == nullptr; + } + + // Return a list of suggestions to a word + virtual Suggestions suggest(const wchar_t *word) + { + Suggestions ret; + + CComPtr<IEnumString> suggestions; + if (SUCCEEDED(m_speller->Suggest(word, &suggestions))) { + wchar_t *ws; + ULONG fetched; + while (true) { + suggestions->Next(1, &ws, &fetched); + if (fetched == 0) + break; + ret.push_back(ws); + } + } + return ret; + } + + // Return a list of auto suggestions to a word + // You have to free the list AND each item + virtual wchar_t* autoSuggestOne(const wchar_t * word) + { + CComPtr<IEnumString> suggestions; + if (SUCCEEDED(m_speller->Suggest(word, &suggestions))) { + wchar_t *ws; + ULONG fetched; + suggestions->Next(1, &ws, &fetched); + if (fetched) { + wchar_t *p = (wchar_t *)malloc(sizeof(wchar_t) * (mir_wstrlen(ws) + 1)); + mir_wstrcpy(p, ws); + return p; + } + } + return nullptr; + } + + // Return TRUE if the char is a word char + virtual BOOL isWordChar(wchar_t c) + { + if (c == 0) + return FALSE; + + return iswalpha(c); + } + + // Assert that all needed data is loaded + virtual void load() + { + } + + virtual BOOL isLoaded() + { + return TRUE; + } + + // Add a word to the user custom dict + virtual void addWord(const wchar_t *word) + { + m_speller->Add(word); + } + + // Add a word to the list of ignored words + virtual void ignoreWord(const wchar_t * word) + { + m_speller->Ignore(word); + } +}; + +// Return a list of avaible languages +void GetNativeDictionaries(OBJLIST<Dictionary> &dicts) +{ + CComPtr<IEnumString> ptr; + g_plugin.m_spellFactory->get_SupportedLanguages(&ptr); + + ULONG fetched; + wchar_t *ws; + while (true) { + ptr->Next(1, &ws, &fetched); + if (fetched == 0) + break; + + auto *pNew = new NativeDictionary(ws); + if (!mir_wstrcmpi(ws, pNew->full_name)) + delete pNew; + else + dicts.insert(pNew); + } +} diff --git a/plugins/SpellChecker/src/spellchecker.cpp b/plugins/SpellChecker/src/spellchecker.cpp index 16213bc425..deeadb0bcf 100644 --- a/plugins/SpellChecker/src/spellchecker.cpp +++ b/plugins/SpellChecker/src/spellchecker.cpp @@ -104,6 +104,7 @@ static int ModulesLoaded(WPARAM, LPARAM) } else flagsDllFolder = Utils_ReplaceVarsW(FLAGS_DLL_FOLDER); + GetNativeDictionaries(languages); GetAvaibleDictionaries(languages, dictionariesFolder, customDictionariesFolder); LoadOptions(); diff --git a/plugins/SpellChecker/src/stdafx.h b/plugins/SpellChecker/src/stdafx.h index 57eeba34e8..a7ff2b119e 100644 --- a/plugins/SpellChecker/src/stdafx.h +++ b/plugins/SpellChecker/src/stdafx.h @@ -83,7 +83,6 @@ struct CMPlugin : public PLUGIN<CMPlugin> std::map<std::wstring, int> locales;
- CComPtr<ISpellChecker> m_speller;
CComPtr<ISpellCheckerFactory> m_spellFactory;
int Load() override;
diff --git a/plugins/SpellChecker/src/version.h b/plugins/SpellChecker/src/version.h index dcc16f666f..78946dccd1 100644 --- a/plugins/SpellChecker/src/version.h +++ b/plugins/SpellChecker/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 -#define __MINOR_VERSION 2 -#define __RELEASE_NUM 6 -#define __BUILD_NUM 6 +#define __MINOR_VERSION 3 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 0 #include <stdver.h> |