]> git.lyx.org Git - features.git/blob - src/frontends/controllers/ControlSpellchecker.C
Switch from SigC signals to boost::signals
[features.git] / src / frontends / controllers / ControlSpellchecker.C
1 /* This file is part of
2  * ======================================================
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 2001 The LyX Team.
7  *
8  * ======================================================
9  *
10  * \file ControlSpellchecker.C
11  * \author Edwin Leuven <leuven@fee.uva.nl>
12  */
13
14 #include <config.h>
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif
19
20 #include "ControlSpellchecker.h"
21 #include "buffer.h"
22 #include "lyxrc.h"
23 #include "BufferView.h"
24 #include "lyxtext.h"
25 #include "gettext.h"
26 #include "language.h"
27
28 #include "ViewBase.h"
29 #include "ButtonControllerBase.h"
30 #include "Dialogs.h"
31 #include "Liason.h"
32
33 #include "frontends/LyXView.h"
34
35 #include "support/lstrings.h"
36
37 # include "sp_ispell.h"
38 #ifdef USE_PSPELL
39 # include "sp_pspell.h"
40 #endif
41
42 #include "debug.h"
43
44 #include <boost/bind.hpp>
45
46 #include <sys/types.h> // needed by <sys/select.h> at least on freebsd
47
48 #ifdef HAVE_SYS_SELECT_H
49 # ifdef HAVE_STRINGS_H
50    // <strings.h> is needed at least on AIX because FD_ZERO uses bzero().
51    // BUT we cannot include both string.h and strings.h on Irix 6.5 :(
52 #  ifdef _AIX
53 #   include <strings.h>
54 #  endif
55 # endif
56 #include <sys/select.h>
57 #endif
58
59 ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
60         : ControlDialogBD(lv, d),
61           rtl_(false), newval_(0.0), oldval_(0), newvalue_(0), count_(0),
62           stop_(false), result_(SpellBase::ISP_OK), speller_(0)
63 {
64         d_.showSpellchecker = boost::bind(&ControlSpellchecker::show, this);
65 }
66
67
68 void ControlSpellchecker::setParams()
69 {
70         if (!speller_) {
71                 // create spell object
72                 string tmp;
73 #ifdef USE_PSPELL
74                 if (lyxrc.use_pspell) {
75                         tmp = (lyxrc.isp_use_alt_lang) ?
76                                 lyxrc.isp_alt_lang : lv_.buffer()->params.language->code();
77
78                         speller_ = new PSpell(lv_.view()->buffer()->params, tmp);
79                 } else {
80 #endif
81                         tmp = (lyxrc.isp_use_alt_lang) ?
82                                 lyxrc.isp_alt_lang : lv_.buffer()->params.language->lang();
83
84                         speller_ = new ISpell(lv_.view()->buffer()->params, tmp);
85 #ifdef USE_PSPELL
86                 }
87 #endif
88
89                 if (lyxrc.isp_use_alt_lang) {
90                         Language const * lang = languages.getLanguage(tmp);
91                         if (lang)
92                                 rtl_ = lang->RightToLeft();
93                 } else {
94                         rtl_ = lv_.buffer()->params.language->RightToLeft();
95                 }
96
97                 if (speller_->error() != 0) {
98 #if 0
99                         message_ = speller_->error();
100                         // show error message
101                         view().partialUpdate(2);
102 #endif
103                         clearParams();
104                         return;
105                 }
106         }
107 }
108
109
110 void ControlSpellchecker::check()
111 {
112         result_ = SpellBase::ISP_OK;
113         stop_ = false;
114
115         // clear any old selection
116         LyXText * text = lv_.view()->getLyXText();
117         lv_.view()->toggleSelection(true);
118         lv_.view()->update(text, BufferView::SELECT);
119
120         while ((result_==SpellBase::ISP_OK || result_==SpellBase::ISP_IGNORE) &&
121                !stop_) {
122                 word_ = lv_.view()->nextWord(newval_);
123
124                 if (word_.empty()) {
125                         clearParams();
126                         break;
127                 }
128
129                 ++count_;
130
131                 // Update slider if and only if value has changed
132                 newvalue_ = int(100.0*newval_);
133                 if (newvalue_!= oldval_) {
134                         oldval_ = newvalue_;
135                         // set progress bar
136                         view().partialUpdate(0);
137                 }
138
139                 if (!speller_->alive()) clearParams();
140
141                 result_ = speller_->check(word_);
142         }
143
144         if (!stop_ && !word_.empty())
145                 lv_.view()->selectLastWord();
146
147         // set suggestions
148         if (result_!=SpellBase::ISP_OK && result_!=SpellBase::ISP_IGNORE) {
149                 view().partialUpdate(1);
150         }
151 }
152
153
154 void ControlSpellchecker::replace(string const & replacement)
155 {
156         lv_.view()->replaceWord(replacement);
157         check();
158 }
159
160
161 void ControlSpellchecker::replaceAll(string const & replacement)
162 {
163         // TODO: add to list
164         replace(replacement);
165 }
166
167
168 void ControlSpellchecker::insert()
169 {
170         speller_->insert(word_);
171         check();
172 }
173
174
175 string ControlSpellchecker::getSuggestion()
176 {
177         // this is needed because string tmp = nextmiss()
178         // segfaults when nextMiss is 0
179         string tmp;
180         char const * w = speller_->nextMiss();
181
182         if (w!=0) {
183                 tmp = w;
184                 if (rtl_) std::reverse(tmp.begin(), tmp.end());
185         }
186
187         return tmp;
188 }
189
190
191 string ControlSpellchecker::getWord()
192 {
193         string tmp = word_;
194         if (rtl_) std::reverse(tmp.begin(), tmp.end());
195         return tmp;
196 }
197
198
199 void ControlSpellchecker::ignoreAll()
200 {
201         speller_->accept(word_);
202         check();
203 }
204
205
206 void ControlSpellchecker::stop()
207 {
208         stop_ = true;
209         lv_.view()->endOfSpellCheck();
210 }
211
212
213 void ControlSpellchecker::clearParams()
214 {
215         if (!speller_) return;
216
217         if (speller_->alive()) {
218                 speller_->close();
219                 message_ = tostr(count_);
220                 if (count_ != 1) {
221                         message_ += _(" words checked.");
222
223                 } else {
224                         message_ += _(" word checked.");
225                 }
226                 message_ = "\n" + message_;
227                 message_ = _("Spellchecking completed! ") + message_;
228
229         } else {
230                 message_ = speller_->error();
231                 speller_->cleanUp();
232                 if (message_.empty())
233                     message_ = _("The spell checker has died for some reason.\n"
234                                  "Maybe it has been killed.");
235
236                 // make sure that the dialog is not launched
237                 emergency_exit_ = true;
238         }
239
240         delete speller_;
241
242         lv_.view()->endOfSpellCheck();
243
244         // show closing message if any words were checked.
245         if (count_ > 0)
246                 view().partialUpdate(2);
247
248         // reset values to initial
249         rtl_ = false;
250         word_.erase();
251         newval_ = 0.0;
252         oldval_ = 0;
253         newvalue_ = 0;
254         count_ = 0;
255         message_.erase();
256         stop_ = false;
257         result_ = SpellBase::ISP_OK;
258         speller_ = 0;
259 }
260
261
262 void ControlSpellchecker::options()
263 {
264         lv_.getDialogs()->showSpellcheckerPreferences();
265 }