From 48dcdb8e59d37497cca5515bc386ec6523a62ff2 Mon Sep 17 00:00:00 2001 From: Twan van Laarhoven Date: Tue, 12 May 2020 18:58:54 +0200 Subject: [PATCH] Don't throw an exception when failing to load spellchecker file, instead show warning and continue. Mitigates #25 somewhat --- src/gui/value/text.cpp | 4 ++-- src/script/functions/spelling.cpp | 7 +++--- src/util/spell_checker.cpp | 38 +++++++++++++++---------------- src/util/spell_checker.hpp | 16 +++++++------ 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 3ccd9779..510ac0f9 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -518,11 +518,11 @@ void spellcheck_language_at(const String& str, size_t error_pos, SpellChecker** size_t pos2 = min(tag.find_first_of(_(':'),pos+1), tag.size()); String language = tag.substr(pos+1,pos2-pos-1); if (language.empty()) return; - out[0] = &SpellChecker::get(language); + out[0] = SpellChecker::get(language); if (pos2 >= tag.size()) return; String extra = tag.substr(pos2+1); if (extra.empty()) return; - out[1] = &SpellChecker::get(extra,language); + out[1] = SpellChecker::get(extra,language); } void get_spelling_suggestions(const String& str, size_t error_pos, vector& suggestions_out) { diff --git a/src/script/functions/spelling.cpp b/src/script/functions/spelling.cpp index f59422bd..c4816a17 100644 --- a/src/script/functions/spelling.cpp +++ b/src/script/functions/spelling.cpp @@ -105,9 +105,9 @@ SCRIPT_FUNCTION(check_spelling) { SCRIPT_RETURN(input); } SpellChecker* checkers[3] = {nullptr}; - checkers[0] = &SpellChecker::get(language); + checkers[0] = SpellChecker::get(language); if (!extra_dictionary.empty()) { - checkers[1] = &SpellChecker::get(extra_dictionary,language); + checkers[1] = SpellChecker::get(extra_dictionary,language); } // what will the missspelling tag be? String tag = _("error-spelling:"); @@ -168,7 +168,8 @@ SCRIPT_FUNCTION(check_spelling_word) { // no language -> spelling checking SCRIPT_RETURN(true); } else { - bool correct = SpellChecker::get(language).spell(input); + auto checker = SpellChecker::get(language); + bool correct = !checker || checker->spell(input); SCRIPT_RETURN(correct); } } diff --git a/src/util/spell_checker.cpp b/src/util/spell_checker.cpp index 3890735d..921e20e9 100644 --- a/src/util/spell_checker.cpp +++ b/src/util/spell_checker.cpp @@ -15,7 +15,7 @@ map SpellChecker::spellers; -SpellChecker& SpellChecker::get(const String& language) { +SpellChecker* SpellChecker::get(const String& language) { SpellCheckerP& speller = spellers[language]; if (!speller) { String local_dir = package_manager.getDictionaryDir(true); @@ -23,19 +23,17 @@ SpellChecker& SpellChecker::get(const String& language) { String aff_path = language + _(".aff"); String dic_path = language + _(".dic"); if (wxFileExists(local_dir + aff_path) && wxFileExists(local_dir + dic_path)) { - speller = SpellCheckerP(new SpellChecker((local_dir + aff_path).mb_str(), - (local_dir + dic_path).mb_str())); + speller = make_intrusive((local_dir + aff_path).mb_str(), (local_dir + dic_path).mb_str()); } else if (wxFileExists(global_dir + aff_path) && wxFileExists(global_dir + dic_path)) { - speller = SpellCheckerP(new SpellChecker((global_dir + aff_path).mb_str(), - (global_dir + dic_path).mb_str())); + speller = make_intrusive((global_dir + aff_path).mb_str(), (global_dir + dic_path).mb_str()); } else { - throw Error(_("Dictionary not found for language: ") + language); + queue_message(MESSAGE_ERROR, _("Dictionary not found for language: ") + language); } } - return *speller; + return speller.get(); } -SpellChecker& SpellChecker::get(const String& filename, const String& language) { +SpellChecker* SpellChecker::get(const String& filename, const String& language) { SpellCheckerP& speller = spellers[filename + _(".") + language]; if (!speller) { Packaged* package = nullptr; @@ -44,20 +42,20 @@ SpellChecker& SpellChecker::get(const String& filename, const String& language) String global_dir = package_manager.getDictionaryDir(false); String aff_path = language + _(".aff"); String dic_path = language + _(".dic"); - if (wxFileExists(prefix + aff_path) && wxFileExists(prefix + dic_path)) { - speller = SpellCheckerP(new SpellChecker((prefix + aff_path).mb_str(), - (prefix + dic_path).mb_str())); - } else if (wxFileExists(local_dir + aff_path) && wxFileExists(prefix + dic_path)) { - speller = SpellCheckerP(new SpellChecker((local_dir + aff_path).mb_str(), - (prefix + dic_path).mb_str())); - } else if (wxFileExists(global_dir + aff_path) && wxFileExists(prefix + dic_path)) { - speller = SpellCheckerP(new SpellChecker((global_dir + aff_path).mb_str(), - (prefix + dic_path).mb_str())); - } else { - throw Error(_("Dictionary '") + filename + _("' not found for language: ") + language); + if (wxFileExists(prefix + dic_path)) { + if (wxFileExists(prefix + aff_path)) { + speller = make_intrusive((prefix + aff_path).mb_str(), (prefix + dic_path).mb_str()); + } else if (wxFileExists(local_dir + aff_path)) { + speller = make_intrusive((local_dir + aff_path).mb_str(), (prefix + dic_path).mb_str()); + } else if (wxFileExists(global_dir + aff_path)) { + speller = make_intrusive((global_dir + aff_path).mb_str(), (prefix + dic_path).mb_str()); + } + } + if (!speller) { + queue_message(MESSAGE_ERROR, _("Dictionary '") + filename + _("' not found for language: ") + language); } } - return *speller; + return speller.get(); } SpellChecker::SpellChecker(const char* aff_path, const char* dic_path) diff --git a/src/util/spell_checker.hpp b/src/util/spell_checker.hpp index a6ee6b24..8df5a55e 100644 --- a/src/util/spell_checker.hpp +++ b/src/util/spell_checker.hpp @@ -24,13 +24,16 @@ DECLARE_POINTER_TYPE(SpellChecker); /// A spelling checker for a particular language class SpellChecker : public Hunspell, public IntrusivePtrBase { - public: +public: + SpellChecker(const char* aff_path, const char* dic_path); /// Get a SpellChecker object for the given language. - /** Note: This is not threadsafe yet */ - static SpellChecker& get(const String& language); + /** Returns nullptr on error + * Note: This is not threadsafe yet */ + static SpellChecker* get(const String& language); /// Get a SpellChecker object for the given language and filename - /** Note: This is not threadsafe yet */ - static SpellChecker& get(const String& filename, const String& language); + /** Returns nullptr on error + * Note: This is not threadsafe yet */ + static SpellChecker* get(const String& filename, const String& language); /// Destroy all cached SpellChecker objects static void destroyAll(); @@ -42,12 +45,11 @@ class SpellChecker : public Hunspell, public IntrusivePtrBase { /// Give spelling suggestions void suggest(const String& word, vector& suggestions_out); - private: +private: /// Convert between String and dictionary encoding wxCSConv encoding; bool convert_encoding(const String& word, CharBuffer& out); - SpellChecker(const char* aff_path, const char* dic_path); static map spellers; //< Cached checkers for each language };