]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/ControlSpellchecker.C
The 'bformat' introduction
[lyx.git] / src / frontends / controllers / ControlSpellchecker.C
1 /**
2  * \file ControlSpellchecker.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include "ControlSpellchecker.h"
14 #include "ViewBase.h"
15 #include "buffer.h"
16 #include "BufferView.h"
17 #include "gettext.h"
18 #include "language.h"
19 #include "lyxrc.h"
20 #include "lyxtext.h"
21 #include "debug.h"
22
23 #include "ispell.h"
24 #ifdef USE_PSPELL
25 # include "pspell.h"
26 #else
27 #ifdef USE_ASPELL
28 # include "aspell_local.h"
29 #endif
30 #endif
31
32 #include "frontends/Alert.h"
33
34 using std::endl;
35
36
37 ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
38         : ControlDialogBD(lv, d),
39           newval_(0.0), oldval_(0), newvalue_(0), count_(0)
40 {}
41
42
43 ControlSpellchecker::~ControlSpellchecker()
44 {}
45
46
47 void ControlSpellchecker::setParams()
48 {
49         lyxerr[Debug::GUI] << "spell setParams" << endl;
50         startSession();
51 }
52
53
54 void ControlSpellchecker::clearParams()
55 {
56         lyxerr[Debug::GUI] << "spell clearParams" << endl;
57         endSession();
58 }
59
60 namespace {
61
62 SpellBase * getSpeller(BufferParams const & bp)
63 {
64         string lang = (lyxrc.isp_use_alt_lang)
65                       ? lyxrc.isp_alt_lang
66                       : bp.language->code();
67
68 #ifdef USE_ASPELL
69         if (lyxrc.use_spell_lib)
70                 return new ASpell(bp, lang);
71 #endif
72 #ifdef USE_PSPELL
73         if (lyxrc.use_spell_lib)
74                 return new PSpell(bp, lang);
75 #endif
76
77         lang = (lyxrc.isp_use_alt_lang) ?
78                 lyxrc.isp_alt_lang : bp.language->lang();
79
80         return new ISpell(bp, lang);
81 }
82
83 }
84
85 void ControlSpellchecker::startSession()
86 {
87         lyxerr[Debug::GUI] << "spell startSession" << endl;
88
89         if (speller_.get()) {
90                 lyxerr[Debug::GUI] << "startSession: speller exists" << endl;
91                 speller_.reset(0);
92                 return;
93         }
94
95         speller_.reset(getSpeller(buffer()->params));
96
97         // reset values to initial
98         newval_ = 0.0;
99         oldval_ = 0;
100         newvalue_ = 0;
101         count_ = 0;
102         emergency_exit_ = false;
103
104         // start off the check
105         if (speller_->error().empty()) {
106                 check();
107                 return;
108         }
109
110         emergency_exit_ = true;
111         string message = speller_->error();
112         if (message.empty())
113                 message = _("The spell-checker could not be started.\n"
114                          "Maybe it is mis-configured.");
115
116         Alert::error(_("The spell-checker has failed"), message);
117         speller_.reset(0);
118 }
119
120
121 void ControlSpellchecker::endSession()
122 {
123         lyxerr[Debug::GUI] << "spell endSession" << endl;
124
125         bufferview()->endOfSpellCheck();
126
127         emergency_exit_ = true;
128
129         if (!speller_.get()) {
130                 lyxerr[Debug::GUI] << "endSession with no speller" << endl;
131                 return;
132         }
133
134         speller_.reset(0);
135 }
136
137
138 void ControlSpellchecker::check()
139 {
140         lyxerr[Debug::GUI] << "spell check a word" << endl;
141
142         SpellBase::Result res = SpellBase::OK;
143
144         // clear any old selection
145         LyXText * text = bufferview()->getLyXText();
146         bufferview()->toggleSelection(true);
147         bufferview()->update(text, BufferView::SELECT);
148
149         while ((res == SpellBase::OK || res == SpellBase::IGNORE)) {
150                 word_ = bufferview()->nextWord(newval_);
151
152                 // end of document
153                 if (word_.word().empty())
154                         break;
155
156                 ++count_;
157
158                 // Update slider if and only if value has changed
159                 newvalue_ = int(100.0 * newval_);
160                 if (newvalue_!= oldval_) {
161                         lyxerr[Debug::GUI] << "Updating spell progress." << endl;
162                         oldval_ = newvalue_;
163                         // set progress bar
164                         view().partialUpdate(SPELL_PROGRESSED);
165                 }
166
167                 // speller might be dead ...
168                 if (!checkAlive())
169                         return;
170
171                 res = speller_->check(word_);
172
173                 // ... or it might just be reporting an error
174                 if (!checkAlive())
175                         return;
176         }
177
178         lyxerr[Debug::GUI] << "Found word \"" << word_.word() << "\"" << endl;
179
180         if (!word_.word().empty()) {
181                 bufferview()->selectLastWord();
182         } else {
183                 showSummary();
184                 endSession();
185                 return;
186         }
187
188         // set suggestions
189         if (res != SpellBase::OK && res != SpellBase::IGNORE) {
190                 lyxerr[Debug::GUI] << "Found a word needing checking." << endl;
191                 view().partialUpdate(SPELL_FOUND_WORD);
192         }
193 }
194
195
196 bool ControlSpellchecker::checkAlive()
197 {
198         if (speller_->alive() && speller_->error().empty())
199                 return true;
200
201         string message = speller_->error();
202         if (message.empty())
203                 message = _("The spell-checker has died for some reason.\n"
204                          "Maybe it has been killed.");
205
206         view().hide();
207         speller_.reset(0);
208
209         Alert::error(_("The spell-checker has failed"), message);
210         return false;
211 }
212
213
214 void ControlSpellchecker::showSummary()
215 {
216         if (!checkAlive() || count_ == 0) {
217                 view().hide();
218                 return;
219         }
220
221         string message;
222         if (count_ != 1)
223                 message = bformat(_("%1$s words checked."), tostr(count_));
224         else
225                 message = _("One word checked.");
226
227         view().hide();
228         Alert::information(_("Spell-checking is complete"), message);
229 }
230
231
232 void ControlSpellchecker::replace(string const & replacement)
233 {
234         bufferview()->replaceWord(replacement);
235         // fix up the count
236         --count_;
237         check();
238 }
239
240
241 void ControlSpellchecker::replaceAll(string const & replacement)
242 {
243         // TODO: add to list
244         replace(replacement);
245 }
246
247
248 void ControlSpellchecker::insert()
249 {
250         speller_->insert(word_);
251         check();
252 }
253
254
255 string const ControlSpellchecker::getSuggestion() const
256 {
257         return speller_->nextMiss();
258 }
259
260
261 string const ControlSpellchecker::getWord() const
262 {
263         return word_.word();
264 }
265
266
267 void ControlSpellchecker::ignoreAll()
268 {
269         speller_->accept(word_);
270         check();
271 }
272
273