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