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