diff --git a/src/AppleSpellChecker.h b/src/AppleSpellChecker.h index e41ff3729d..64e5f2b26b 100644 --- a/src/AppleSpellChecker.h +++ b/src/AppleSpellChecker.h @@ -26,6 +26,7 @@ public: //@{ enum Result check(WordLangTuple const &); void suggest(WordLangTuple const &, docstring_list &); + void stem(WordLangTuple const &, docstring_list &) {}; void insert(WordLangTuple const &); void remove(WordLangTuple const &); void accept(WordLangTuple const &); diff --git a/src/AspellChecker.h b/src/AspellChecker.h index c2208498ec..bce5402b12 100644 --- a/src/AspellChecker.h +++ b/src/AspellChecker.h @@ -27,6 +27,7 @@ public: //@{ enum Result check(WordLangTuple const &); void suggest(WordLangTuple const &, docstring_list &); + void stem(WordLangTuple const &, docstring_list &) {}; void insert(WordLangTuple const &); void remove(WordLangTuple const &); void accept(WordLangTuple const &); diff --git a/src/EnchantChecker.h b/src/EnchantChecker.h index fc1b70b13a..d92774972d 100644 --- a/src/EnchantChecker.h +++ b/src/EnchantChecker.h @@ -33,6 +33,7 @@ public: ///@{ enum Result check(WordLangTuple const &); void suggest(WordLangTuple const &, docstring_list &); + void stem(WordLangTuple const &, docstring_list &) {}; void insert(WordLangTuple const &); void remove(WordLangTuple const &); void accept(WordLangTuple const &); diff --git a/src/HunspellChecker.cpp b/src/HunspellChecker.cpp index d044889107..a2d2c95e05 100644 --- a/src/HunspellChecker.cpp +++ b/src/HunspellChecker.cpp @@ -413,6 +413,25 @@ void HunspellChecker::suggest(WordLangTuple const & wl, } +void HunspellChecker::stem(WordLangTuple const & wl, + docstring_list & suggestions) +{ + suggestions.clear(); + Hunspell * h = d->speller(wl.lang()); + if (!h) + return; + string const encoding = h->get_dic_encoding(); + string const word_to_check = to_iconv_encoding(wl.word(), encoding); + char ** suggestion_list; + int const suggestion_number = h->stem(&suggestion_list, word_to_check.c_str()); + if (suggestion_number <= 0) + return; + for (int i = 0; i != suggestion_number; ++i) + suggestions.push_back(from_iconv_encoding(suggestion_list[i], encoding)); + h->free_list(&suggestion_list, suggestion_number); +} + + bool HunspellChecker::hasDictionary(Language const * lang) const { if (!lang) diff --git a/src/HunspellChecker.h b/src/HunspellChecker.h index ca28d01d64..686f014384 100644 --- a/src/HunspellChecker.h +++ b/src/HunspellChecker.h @@ -27,6 +27,7 @@ public: ///@{ enum Result check(WordLangTuple const &); void suggest(WordLangTuple const &, docstring_list &); + void stem(WordLangTuple const &, docstring_list &); void insert(WordLangTuple const &); void remove(WordLangTuple const &); void accept(WordLangTuple const &); diff --git a/src/SpellChecker.h b/src/SpellChecker.h index f87ef122b9..425925ce37 100644 --- a/src/SpellChecker.h +++ b/src/SpellChecker.h @@ -62,6 +62,9 @@ public: /// Gives suggestions. virtual void suggest(WordLangTuple const &, docstring_list & suggestions) = 0; + /// Lemmatizing: return stem of word (used by Thesaurus). + virtual void stem(WordLangTuple const &, docstring_list & suggestions) = 0; + /// insert the given word into the personal dictionary virtual void insert(WordLangTuple const &) = 0; diff --git a/src/Thesaurus.cpp b/src/Thesaurus.cpp index fcec80bef5..f8e8448979 100644 --- a/src/Thesaurus.cpp +++ b/src/Thesaurus.cpp @@ -15,9 +15,13 @@ #include "LyXRC.h" +#include "SpellChecker.h" +#include "WordLangTuple.h" + #include "support/FileNameList.h" #include "support/Package.h" #include "support/debug.h" +#include "support/docstring_list.h" #include "support/filetools.h" #include "support/gettext.h" #include "support/lstrings.h" @@ -195,17 +199,20 @@ bool Thesaurus::thesaurusInstalled(docstring const & lang) const } -Thesaurus::Meanings Thesaurus::lookup(docstring const & t, docstring const & lang) +Thesaurus::Meanings Thesaurus::lookup(WordLangTuple const & wl) { Meanings meanings; MyThes * mythes = 0; - if (!d->addThesaurus(lang)) + docstring const lang_code = from_ascii(wl.lang()->code()); + docstring const t = wl.word(); + + if (!d->addThesaurus(lang_code)) return meanings; for (Thesauri::const_iterator it = d->thes_.begin(); it != d->thes_.end(); ++it) { - if (it->first == lang) { + if (it->first == lang_code) { mythes = it->second; break; } @@ -220,8 +227,22 @@ Thesaurus::Meanings Thesaurus::lookup(docstring const & t, docstring const & lan string const text = to_iconv_encoding(support::lowercase(t), encoding); int len = strlen(text.c_str()); int count = mythes->Lookup(text.c_str(), len, &pmean); - if (!count) - return meanings; + if (!count) { + SpellChecker * speller = theSpellChecker(); + if (!speller) + return meanings; + docstring_list suggestions; + speller->stem(wl, suggestions); + for (size_t i = 0; i != suggestions.size(); ++i) { + string const wordform = to_iconv_encoding(support::lowercase(suggestions[i]), encoding); + len = strlen(wordform.c_str()); + count = mythes->Lookup(wordform.c_str(), len, &pmean); + if (count) + break; + } + if (!count) + return meanings; + } // don't change value of pmean or count // they are needed for the CleanUpAfterLookup routine diff --git a/src/Thesaurus.h b/src/Thesaurus.h index 9c0bdc61de..a479fda962 100644 --- a/src/Thesaurus.h +++ b/src/Thesaurus.h @@ -14,6 +14,7 @@ #define THESAURUS_H #include "support/docstring.h" +#include "WordLangTuple.h" #include #include @@ -38,7 +39,7 @@ public: /** * look up some text in the thesaurus */ - Meanings lookup(docstring const & text, docstring const & lang); + Meanings lookup(WordLangTuple const & wl); /** check if a thesaurus for a given language \p lang is available * (installed and loaded) */ diff --git a/src/frontends/qt4/GuiThesaurus.cpp b/src/frontends/qt4/GuiThesaurus.cpp index 86ed9598ab..cf6f3821cf 100644 --- a/src/frontends/qt4/GuiThesaurus.cpp +++ b/src/frontends/qt4/GuiThesaurus.cpp @@ -22,6 +22,7 @@ #include "FuncRequest.h" #include "Language.h" #include "lyxfind.h" +#include "WordLangTuple.h" #include "support/debug.h" #include "support/gettext.h" @@ -173,11 +174,11 @@ void GuiThesaurus::updateLists() QString const lang = languageCO->itemData( languageCO->currentIndex()).toString(); - docstring const lang_code = - from_ascii(lyx::languages.getLanguage(fromqstr(lang))->code()); + Language * language = const_cast(lyx::languages.getLanguage(fromqstr(lang))); + docstring const lang_code = from_ascii(language->code()); Thesaurus::Meanings meanings = - getMeanings(qstring_to_ucs4(entryCO->currentText()), lang_code); + getMeanings(WordLangTuple(qstring_to_ucs4(entryCO->currentText()), language)); for (Thesaurus::Meanings::const_iterator cit = meanings.begin(); cit != meanings.end(); ++cit) { @@ -271,11 +272,10 @@ void GuiThesaurus::replace(docstring const & newstr) } -Thesaurus::Meanings const & GuiThesaurus::getMeanings(docstring const & str, - docstring const & lang) +Thesaurus::Meanings const & GuiThesaurus::getMeanings(WordLangTuple const & wl) { - if (str != laststr_) - meanings_ = thesaurus.lookup(str, lang); + if (wl.word() != laststr_) + meanings_ = thesaurus.lookup(wl); return meanings_; } diff --git a/src/frontends/qt4/GuiThesaurus.h b/src/frontends/qt4/GuiThesaurus.h index 17f9ebf179..3cc45f0993 100644 --- a/src/frontends/qt4/GuiThesaurus.h +++ b/src/frontends/qt4/GuiThesaurus.h @@ -16,6 +16,8 @@ #include "Thesaurus.h" #include "ui_ThesaurusUi.h" +#include "WordLangTuple.h" + class QTreeWidgetItem; namespace lyx { @@ -56,8 +58,7 @@ private: void replace(docstring const & newstr); /// get meanings - Thesaurus::Meanings const & getMeanings(docstring const & str, - docstring const & lang); + Thesaurus::Meanings const & getMeanings(WordLangTuple const & wl); private: /// last string looked up