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