summaryrefslogtreecommitdiff
path: root/plugins/SpellChecker
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-11-26 16:55:51 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-11-26 16:55:51 +0300
commit15b337d3f4caa3fa71160dc93b7caf4f2c098b06 (patch)
tree140b1c2923ef84108c6e85fdc2403a21d47f106c /plugins/SpellChecker
parent70cd3610f4ec0131fe3c9308a483935e9f1c788c (diff)
fixes #4692 (SpellChecker to use the native Windows speller if present)
Diffstat (limited to 'plugins/SpellChecker')
-rw-r--r--plugins/SpellChecker/spellchecker.vcxproj1
-rw-r--r--plugins/SpellChecker/spellchecker.vcxproj.filters3
-rw-r--r--plugins/SpellChecker/src/dictionary.cpp45
-rw-r--r--plugins/SpellChecker/src/dictionary.h8
-rw-r--r--plugins/SpellChecker/src/hunspell.cpp29
-rw-r--r--plugins/SpellChecker/src/native.cpp145
-rw-r--r--plugins/SpellChecker/src/spellchecker.cpp1
-rw-r--r--plugins/SpellChecker/src/stdafx.h1
-rw-r--r--plugins/SpellChecker/src/version.h6
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>