]> git.lyx.org Git - lyx.git/blob - src/AppleSpellChecker.cpp
listerrors.lyx : Update a link.
[lyx.git] / src / AppleSpellChecker.cpp
1 /**
2  * \file AppleSpellChecker.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Stephan Witt
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "AppleSpellChecker.h"
14 #include "WordLangTuple.h"
15
16 #include "support/lassert.h"
17 #include "support/debug.h"
18 #include "support/docstring_list.h"
19 #include "support/AppleSpeller.h"
20
21 using namespace std;
22 using namespace lyx::support;
23
24 namespace lyx {
25
26 struct AppleSpellChecker::Private
27 {
28         Private();
29
30         ~Private();
31
32         SpellChecker::Result toResult(SpellCheckResult status);
33         string toString(SpellCheckResult status);
34
35         /// the speller
36         AppleSpeller speller;
37         
38         /// language map
39         map<string, string> languageMap;
40         
41 };
42
43
44 AppleSpellChecker::Private::Private()
45 {
46         speller = newAppleSpeller();
47 }
48
49
50 AppleSpellChecker::Private::~Private()
51 {
52         freeAppleSpeller(speller);
53         speller = 0;
54 }
55
56
57 AppleSpellChecker::AppleSpellChecker(): d(new Private)
58 {
59 }
60
61
62 AppleSpellChecker::~AppleSpellChecker()
63 {
64         delete d;
65 }
66
67
68 SpellChecker::Result AppleSpellChecker::Private::toResult(SpellCheckResult status)
69 {
70         return status == SPELL_CHECK_FAILED ? UNKNOWN_WORD :
71                 status == SPELL_CHECK_LEARNED ? LEARNED_WORD : WORD_OK ;
72 }
73
74
75 string AppleSpellChecker::Private::toString(SpellCheckResult status)
76 {
77         return status == SPELL_CHECK_FAILED ? "FAILED" :
78                  status == SPELL_CHECK_LEARNED ? "LEARNED" : "OK";
79 }
80
81
82 SpellChecker::Result AppleSpellChecker::check(WordLangTuple const & word)
83 {
84         if (!hasDictionary(word.lang()))
85                 return WORD_OK;
86
87         string const word_str = to_utf8(word.word());
88         string const lang = d->languageMap[word.lang()->lang()];
89         SpellCheckResult result =
90                 AppleSpeller_check(d->speller,
91                         word_str.c_str(), lang.c_str());
92         LYXERR(Debug::GUI, "spellCheck: \"" <<
93                    word.word() << "\" = " << d->toString(result) <<
94                    ", lang = " << lang) ;
95         return d->toResult(result);
96 }
97
98
99 void AppleSpellChecker::advanceChangeNumber()
100 {
101         nextChangeNumber();
102 }
103
104
105 // add to personal dictionary
106 void AppleSpellChecker::insert(WordLangTuple const & word)
107 {
108         string const word_str = to_utf8(word.word());
109         AppleSpeller_learn(d->speller, word_str.c_str());
110         LYXERR(Debug::GUI, "learn word: \"" << word.word() << "\"") ;
111         advanceChangeNumber();
112 }
113
114
115 // remove from personal dictionary
116 void AppleSpellChecker::remove(WordLangTuple const & word)
117 {
118         string const word_str = to_utf8(word.word());
119         AppleSpeller_unlearn(d->speller, word_str.c_str());
120         LYXERR(Debug::GUI, "unlearn word: \"" << word.word() << "\"") ;
121         advanceChangeNumber();
122 }
123
124
125 // ignore for session
126 void AppleSpellChecker::accept(WordLangTuple const & word)
127 {
128         string const word_str = to_utf8(word.word());
129         AppleSpeller_ignore(d->speller, word_str.c_str());
130         LYXERR(Debug::GUI, "ignore word: \"" << word.word() << "\"") ;
131         advanceChangeNumber();
132 }
133
134
135 void AppleSpellChecker::suggest(WordLangTuple const & wl,
136         docstring_list & suggestions)
137 {
138         suggestions.clear();
139         string const word_str = to_utf8(wl.word());
140         size_t num = AppleSpeller_makeSuggestion(d->speller, 
141                                         word_str.c_str(), wl.lang()->code().c_str());
142         for (size_t i = 0; i < num; i++) {
143                 char const * next = AppleSpeller_getSuggestion(d->speller, i);
144                 if (!next) break;
145                 suggestions.push_back(from_utf8(next));
146         }
147 }
148
149
150 bool AppleSpellChecker::hasDictionary(Language const * lang) const
151 {
152         string const langmap = d->languageMap[lang->lang()];
153         bool result = !langmap.empty();
154
155         if (result)
156                 return result;
157
158         result = AppleSpeller_hasLanguage(d->speller,lang->code().c_str());
159         if (result) {
160                 d->languageMap[lang->lang()] = lang->code();
161         } else {
162                 result = AppleSpeller_hasLanguage(d->speller,lang->lang().c_str());
163                 if (result)
164                         d->languageMap[lang->lang()] = lang->lang();
165         }
166         LYXERR(Debug::GUI, "has dictionary: " << lang->lang() << " = " << result) ;
167         return result;
168 }
169
170
171 int AppleSpellChecker::numMisspelledWords() const
172 {
173         return AppleSpeller_numMisspelledWords(d->speller);
174 }
175
176
177 void AppleSpellChecker::misspelledWord(int index, int & start, int & length) const
178 {
179         AppleSpeller_misspelledWord(d->speller, index, &start, &length);
180 }
181
182
183 docstring const AppleSpellChecker::error()
184 {
185         return docstring();
186 }
187
188
189 } // namespace lyx