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