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