]> git.lyx.org Git - lyx.git/blob - src/AppleSpellChecker.cpp
start the timer in the correct thread
[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()->code()];
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, word_str.c_str(), wl.lang()->code().c_str());
141         for (size_t i = 0; i < num; i++) {
142                 char const * next = AppleSpeller_getSuggestion(d->speller, i);
143                 if (!next) break;
144                 suggestions.push_back(from_utf8(next));
145         }
146 }
147
148
149 bool AppleSpellChecker::hasDictionary(Language const * lang) const
150 {
151         string const langmap = d->languageMap[lang->code()];
152         bool result = !langmap.empty();
153
154         if (result)
155                 return result;
156
157         result = AppleSpeller_hasLanguage(d->speller,lang->code().c_str());
158         if (result) {
159                 d->languageMap[lang->code()] = lang->code();
160         } else {
161                 result = AppleSpeller_hasLanguage(d->speller,lang->lang().c_str());
162                 if (result)
163                         d->languageMap[lang->code()] = lang->lang();
164         }
165         return result;
166 }
167
168
169 int AppleSpellChecker::numMisspelledWords() const
170 {
171         return AppleSpeller_numMisspelledWords(d->speller);
172 }
173
174
175 void AppleSpellChecker::misspelledWord(int index, int & start, int & length) const
176 {
177         AppleSpeller_misspelledWord(d->speller, index, &start, &length);
178 }
179
180
181 docstring const AppleSpellChecker::error()
182 {
183         return docstring();
184 }
185
186
187 } // namespace lyx