]> git.lyx.org Git - lyx.git/blobdiff - src/AspellChecker.cpp
Routines for calculating numerical labels for BibTeX citations.
[lyx.git] / src / AspellChecker.cpp
index 6526b3b6815452fff5dcd7c18cc0914084010a9e..98506b88c453e60f216d0f19326e81d76b25ae5d 100644 (file)
 
 #include <config.h>
 
-#include "support/debug.h"
-
-#include <aspell.h>
-
 #include "AspellChecker.h"
 #include "LyXRC.h"
 #include "WordLangTuple.h"
 
 #include "support/lassert.h"
+#include "support/debug.h"
+#include "support/docstring_list.h"
+
+#include <aspell.h>
+
+#include <map>
+#include <string>
 
 using namespace std;
 
 namespace lyx {
 
-AspellChecker::AspellChecker(): els(0), spell_error_object(0)
+namespace {
+
+struct Speller {
+       AspellSpeller * speller;
+       AspellConfig * config;
+};
+
+typedef std::map<std::string, Speller> Spellers;
+
+} // anon namespace
+
+struct AspellChecker::Private
 {
-}
+       Private(): spell_error_object(0) {}
 
+       ~Private();
 
-AspellChecker::~AspellChecker()
+       /// add a speller of the given language
+       AspellSpeller * addSpeller(string const & lang);
+
+       ///
+       AspellSpeller * speller(string const & lang);
+
+       /// the spellers
+       Spellers spellers_;
+
+       /// FIXME
+       AspellCanHaveError * spell_error_object;
+};
+
+
+AspellChecker::Private::~Private()
 {
        if (spell_error_object) {
                delete_aspell_can_have_error(spell_error_object);
                spell_error_object = 0;
        }
 
-       if (els)
-               delete_aspell_string_enumeration(els);
-
        Spellers::iterator it = spellers_.begin();
        Spellers::iterator end = spellers_.end();
 
@@ -51,7 +77,7 @@ AspellChecker::~AspellChecker()
 }
 
 
-void AspellChecker::addSpeller(string const & lang)
+AspellSpeller * AspellChecker::Private::addSpeller(string const & lang)
 {
        AspellConfig * config = new_aspell_config();
        // FIXME The aspell documentation says to use "lang"
@@ -75,31 +101,46 @@ void AspellChecker::addSpeller(string const & lang)
                delete_aspell_can_have_error(spell_error_object);
        spell_error_object = 0;
 
-       if (aspell_error_number(err) == 0) {
-               Speller m;
-               m.speller = to_aspell_speller(err);
-               m.config = config;
-               spellers_[lang] = m;
-       } else {
+       if (aspell_error_number(err) != 0) {
+               // FIXME: We should we indicate somehow that this language is not
+               // supported.
                spell_error_object = err;
+               return 0;
        }
+       Speller m;
+       m.speller = to_aspell_speller(err);
+       m.config = config;
+       spellers_[lang] = m;
+       return m.speller;
 }
 
 
-AspellChecker::Result AspellChecker::check(WordLangTuple const & word)
+AspellSpeller * AspellChecker::Private::speller(string const & lang)
 {
-       Result res = UNKNOWN_WORD;
-
-       Spellers::iterator it = spellers_.find(word.lang_code());
-       if (it == spellers_.end()) {
-               addSpeller(word.lang_code());
-               it = spellers_.find(word.lang_code());
-               // FIXME
-               if (it == spellers_.end())
-                       return res;
-       }
+       Spellers::iterator it = spellers_.find(lang);
+       if (it != spellers_.end())
+               return it->second.speller;
+       
+       return addSpeller(lang);
+}
 
-       AspellSpeller * m = it->second.speller;
+
+AspellChecker::AspellChecker(): d(new Private)
+{
+}
+
+
+AspellChecker::~AspellChecker()
+{
+       delete d;
+}
+
+
+SpellChecker::Result AspellChecker::check(WordLangTuple const & word)
+{
+       AspellSpeller * m = d->speller(word.lang_code());
+       if (!m)
+               return OK;
 
        if (word.word().empty())
                // MSVC compiled Aspell doesn't like it.
@@ -108,46 +149,49 @@ AspellChecker::Result AspellChecker::check(WordLangTuple const & word)
        int const word_ok = aspell_speller_check(m, to_utf8(word.word()).c_str(), -1);
        LASSERT(word_ok != -1, /**/);
 
-       if (word_ok)
-               return OK;
-
-       AspellWordList const * sugs =
-               aspell_speller_suggest(m, to_utf8(word.word()).c_str(), -1);
-       LASSERT(sugs != 0, /**/);
-       els = aspell_word_list_elements(sugs);
-       if (aspell_word_list_empty(sugs))
-               res = UNKNOWN_WORD;
-       else
-               res = SUGGESTED_WORDS;
-
-       return res;
+       return (word_ok) ? OK : UNKNOWN_WORD;
 }
 
 
 void AspellChecker::insert(WordLangTuple const & word)
 {
-       Spellers::iterator it = spellers_.find(word.lang_code());
-       if (it != spellers_.end())
+       Spellers::iterator it = d->spellers_.find(word.lang_code());
+       if (it != d->spellers_.end())
                aspell_speller_add_to_personal(it->second.speller, to_utf8(word.word()).c_str(), -1);
 }
 
 
 void AspellChecker::accept(WordLangTuple const & word)
 {
-       Spellers::iterator it = spellers_.find(word.lang_code());
-       if (it != spellers_.end())
+       Spellers::iterator it = d->spellers_.find(word.lang_code());
+       if (it != d->spellers_.end())
                aspell_speller_add_to_session(it->second.speller, to_utf8(word.word()).c_str(), -1);
 }
 
 
-docstring const AspellChecker::nextMiss()
+void AspellChecker::suggest(WordLangTuple const & wl,
+       docstring_list & suggestions)
 {
-       char const * str = 0;
+       suggestions.clear();
+       AspellSpeller * m = d->speller(wl.lang_code());
+       if (!m)
+               return;
 
-       if (els)
-               str = aspell_string_enumeration_next(els);
+       AspellWordList const * sugs =
+               aspell_speller_suggest(m, to_utf8(wl.word()).c_str(), -1);
+       LASSERT(sugs != 0, /**/);
+       AspellStringEnumeration * els = aspell_word_list_elements(sugs);
+       if (!els || aspell_word_list_empty(sugs))
+               return;
+
+       for (;;) {
+               char const * str = aspell_string_enumeration_next(els);
+               if (!str)
+                       break;
+               suggestions.push_back(from_utf8(str));
+       }
 
-       return (str ? from_utf8(str) : docstring());
+       delete_aspell_string_enumeration(els);
 }
 
 
@@ -155,8 +199,8 @@ docstring const AspellChecker::error()
 {
        char const * err = 0;
 
-       if (spell_error_object && aspell_error_number(spell_error_object) != 0)
-               err = aspell_error_message(spell_error_object);
+       if (d->spell_error_object && aspell_error_number(d->spell_error_object) != 0)
+               err = aspell_error_message(d->spell_error_object);
 
        // FIXME UNICODE: err is not in UTF8, but probably the locale encoding
        return (err ? from_utf8(err) : docstring());