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