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