]> git.lyx.org Git - lyx.git/blob - src/AppleSpellChecker.cpp
Merge branch 'master' of git.lyx.org:lyx
[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/debug.h"
17 #include "support/docstring_list.h"
18 #include "support/AppleSpeller.h"
19
20 using namespace std;
21 using namespace lyx::support;
22
23 namespace lyx {
24
25 struct AppleSpellChecker::Private
26 {
27         Private();
28
29         ~Private();
30
31         SpellChecker::Result toResult(SpellCheckResult status);
32         string toString(SpellCheckResult status);
33         int numDictionaries() const;
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()
58         : d(new Private)
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 NO_DICTIONARY;
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::numDictionaries() const
172 {
173         int result = 0;
174         map<string, string>::const_iterator it = d->languageMap.begin();
175         map<string, string>::const_iterator et = d->languageMap.end();
176
177         for (; it != et; ++it) {
178                 string const langmap = it->second;
179                 result += langmap.empty() ? 0 : 1;
180         }
181         return result;
182 }
183
184         
185 int AppleSpellChecker::numMisspelledWords() const
186 {
187         return AppleSpeller_numMisspelledWords(d->speller);
188 }
189
190
191 void AppleSpellChecker::misspelledWord(int index, int & start, int & length) const
192 {
193         AppleSpeller_misspelledWord(d->speller, index, &start, &length);
194 }
195
196
197 docstring const AppleSpellChecker::error()
198 {
199         return docstring();
200 }
201
202
203 } // namespace lyx