]> git.lyx.org Git - lyx.git/blob - src/frontends/controllers/ControlSpellchecker.C
fix triple-select.lyx crash
[lyx.git] / src / frontends / controllers / ControlSpellchecker.C
1 /**
2  * \file ControlSpellchecker.C
3  * Copyright 2001 the LyX Team
4  * Read the file COPYING
5  *
6  * \author Edwin Leuven <leuven@fee.uva.nl>
7  */
8
9 #include <config.h>
10
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15 #include "ControlSpellchecker.h"
16 #include "buffer.h"
17 #include "lyxrc.h"
18 #include "BufferView.h"
19 #include "lyxtext.h"
20 #include "gettext.h"
21 #include "language.h"
22
23 #include "ViewBase.h"
24 #include "Dialogs.h"
25 #include "Liason.h"
26
27 #include "frontends/LyXView.h"
28 #include "frontends/Alert.h"
29
30 #include "support/lstrings.h"
31
32 #include "ispell.h"
33 #ifdef USE_PSPELL
34 # include "pspell.h"
35 #endif
36
37 ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
38         : ControlDialogBD(lv, d),
39           rtl_(false), newval_(0.0), oldval_(0), newvalue_(0), count_(0),
40           stop_(false), speller_(0)
41 {}
42
43
44 void ControlSpellchecker::setParams()
45 {
46         if (!speller_) {
47                 // create spell object
48                 string tmp;
49 #ifdef USE_PSPELL
50                 if (lyxrc.use_pspell) {
51                         tmp = (lyxrc.isp_use_alt_lang) ?
52                                 lyxrc.isp_alt_lang : lv_.buffer()->params.language->code();
53
54                         speller_ = new PSpell(lv_.view()->buffer()->params, tmp);
55                 } else {
56 #endif
57                         tmp = (lyxrc.isp_use_alt_lang) ?
58                                 lyxrc.isp_alt_lang : lv_.buffer()->params.language->lang();
59
60                         speller_ = new ISpell(lv_.view()->buffer()->params, tmp);
61 #ifdef USE_PSPELL
62                 }
63 #endif
64
65                 if (lyxrc.isp_use_alt_lang) {
66                         Language const * lang = languages.getLanguage(tmp);
67                         if (lang)
68                                 rtl_ = lang->RightToLeft();
69                 } else {
70                         rtl_ = lv_.buffer()->params.language->RightToLeft();
71                 }
72
73                 if (!speller_->error().empty()) {
74                         emergency_exit_ = true;
75                         Alert::alert("The spellchecker has failed", speller_->error());
76                         clearParams();
77                         return;
78                 }
79         }
80 }
81
82
83 void ControlSpellchecker::check()
84 {
85         SpellBase::Result res = SpellBase::OK;
86         stop_ = false;
87
88         // clear any old selection
89         LyXText * text = lv_.view()->getLyXText();
90         lv_.view()->toggleSelection(true);
91         lv_.view()->update(text, BufferView::SELECT);
92
93         while ((res == SpellBase::OK || res == SpellBase::IGNORE) && !stop_) {
94                 word_ = lv_.view()->nextWord(newval_);
95
96                 if (word_.word().empty()) {
97                         clearParams();
98                         break;
99                 }
100
101                 ++count_;
102
103                 // Update slider if and only if value has changed
104                 newvalue_ = int(100.0 * newval_);
105                 if (newvalue_!= oldval_) {
106                         oldval_ = newvalue_;
107                         // set progress bar
108                         view().partialUpdate(0);
109                 }
110
111                 if (!speller_->alive()) {
112                         clearParams();
113                         stop();
114                         return;
115                 }
116
117                 res = speller_->check(word_);
118         }
119
120         if (!stop_ && !word_.word().empty())
121                 lv_.view()->selectLastWord();
122
123         // set suggestions
124         if (res != SpellBase::OK && res != SpellBase::IGNORE) {
125                 view().partialUpdate(1);
126         }
127 }
128
129
130 void ControlSpellchecker::replace(string const & replacement)
131 {
132         lv_.view()->replaceWord(replacement);
133         // fix up the count
134         --count_;
135         check();
136 }
137
138
139 void ControlSpellchecker::replaceAll(string const & replacement)
140 {
141         // TODO: add to list
142         replace(replacement);
143 }
144
145
146 void ControlSpellchecker::insert()
147 {
148         speller_->insert(word_);
149         check();
150 }
151
152
153 string ControlSpellchecker::getSuggestion()
154 {
155         string miss(speller_->nextMiss());
156
157         if (rtl_)
158                 std::reverse(miss.begin(), miss.end());
159
160         return miss;
161 }
162
163
164 string ControlSpellchecker::getWord()
165 {
166         string tmp = word_.word();
167         if (rtl_)
168                 std::reverse(tmp.begin(), tmp.end());
169         return tmp;
170 }
171
172
173 void ControlSpellchecker::ignoreAll()
174 {
175         speller_->accept(word_);
176         check();
177 }
178
179
180 void ControlSpellchecker::stop()
181 {
182         stop_ = true;
183         lv_.view()->endOfSpellCheck();
184 }
185
186
187 void ControlSpellchecker::clearParams()
188 {
189         if (!speller_)
190                 return;
191
192         if (speller_->alive()) {
193                 speller_->close();
194                 message_ = tostr(count_);
195                 if (count_ != 1) {
196                         message_ += _(" words checked.");
197
198                 } else {
199                         message_ += _(" word checked.");
200                 }
201                 message_ = "\n" + message_;
202                 message_ = _("Spellchecking completed! ") + message_;
203
204         } else {
205                 message_ = speller_->error();
206                 speller_->cleanUp();
207                 if (message_.empty())
208                     message_ = _("The spell checker has died for some reason.\n"
209                                  "Maybe it has been killed.");
210
211                 // make sure that the dialog is not launched
212                 emergency_exit_ = true;
213                 Alert::alert("The spellchecker has failed", message_);
214         }
215
216         delete speller_;
217
218         lv_.view()->endOfSpellCheck();
219
220         // show closing message if any words were checked.
221         if (count_ > 0)
222                 view().partialUpdate(2);
223
224         // reset values to initial
225         rtl_ = false;
226         newval_ = 0.0;
227         oldval_ = 0;
228         newvalue_ = 0;
229         count_ = 0;
230         message_.erase();
231         stop_ = false;
232         speller_ = 0;
233 }