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