]> git.lyx.org Git - lyx.git/blob - src/trans_mgr.C
Dispatch->dispatch, some trans work
[lyx.git] / src / trans_mgr.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation "trans_mgr.h"
5 #endif
6
7 #include "trans_mgr.h"
8 #include "trans.h"
9 #include "lyxtext.h"
10 #include "LString.h"
11 #include "debug.h"
12 #include "chset.h"
13 #include "insets/insetlatexaccent.h"
14 #include "BufferView.h"
15 #include "buffer.h"
16 #include "lyxrc.h"
17 #include "support/lstrings.h"
18 #include "language.h"
19
20 using std::endl;
21 using std::pair;
22
23 extern string const DoAccent(string const &, tex_accent);
24 extern string const DoAccent(char, tex_accent);
25 extern BufferView * current_view;
26
27
28 // TransFSMData
29 TransFSMData::TransFSMData()
30 {
31         deadkey_ = deadkey2_ = 0;
32         deadkey_info_.accent = deadkey2_info_.accent = TEX_NOACCENT;
33 #if 0
34         comb_info_ = 0;
35 #endif
36 }
37
38
39 // TransState
40 char const TransState::TOKEN_SEP = 4;
41
42
43 // TransInitState
44 TransInitState::TransInitState()
45 {
46         init_state_ = this;
47 }
48
49
50 #if 0
51 string const TransInitState::normalkey(char c, string const & t)
52 {
53         string res;
54         if (!t.empty()) res = t;
55         else res = c;
56         
57         return res;
58 }
59 #else
60 string const TransInitState::normalkey(char c)
61 {
62         string res;
63         res = c;
64         return res;
65 }
66 #endif
67
68
69 string const TransInitState::deadkey(char c, KmodInfo d)
70 {
71         deadkey_ = c;
72         deadkey_info_ = d;
73         currentState = deadkey_state_;
74         return string();
75 }
76
77
78 // TransDeadkeyState
79 TransDeadkeyState::TransDeadkeyState()
80 {
81         deadkey_state_ = this;
82 }
83
84
85 #if 0
86 string const TransDeadkeyState::normalkey(char c, string const & trans)
87 {
88         string res;
89         
90         // Check if it is an exception
91         KmodException l = deadkey_info_.exception_list;
92         while(l != 0) {
93                 if (l->c == c) {
94                         res = l->data;
95                         break;
96                 }
97                 l = l->next;
98         }
99         if (l == 0) {
100                 // Not an exception. Check if it allowed
101                 if (countChar(deadkey_info_.allowed, c) > 0) {
102                         res = DoAccent(c, deadkey_info_.accent);
103                 } else {
104                         // Not allowed
105                         if (deadkey_!= 0)
106                                 res = deadkey_;
107                         res+= TOKEN_SEP;
108                         res+= trans;
109                 }
110         }
111         currentState = init_state_;
112         return res;
113 }
114 #else
115 string const TransDeadkeyState::normalkey(char c)
116 {
117 #if 0
118         string res;
119         
120         // Check if it is an exception
121         KmodException l = deadkey_info_.exception_list;
122         while(l != 0) {
123                 if (l->c == c) {
124                         res = l->data;
125                         break;
126                 }
127                 l = l->next;
128         }
129         if (l == 0) {
130                         res = DoAccent(c, deadkey_info_.accent);
131         }
132         currentState = init_state_;
133         return res;
134 #else
135         string res;
136         
137         KmodException::iterator it = deadkey_info_.exception_list.begin();
138         KmodException::iterator end = deadkey_info_.exception_list.end();
139
140         for (; it != end; ++it) {
141                 if (it->c == c) {
142                         res = it->data;
143                         break;
144                 }
145         }
146         if (it == end) {
147                 res = DoAccent(c, deadkey_info_.accent);
148         }
149         currentState = init_state_;
150         return res;
151 #endif
152 }
153 #endif
154
155
156 string const TransDeadkeyState::deadkey(char c, KmodInfo d)
157 {
158         string res;
159         
160         // Check if the same deadkey was typed twice
161         if (deadkey_ == c) {
162                 res = deadkey_;
163                 deadkey_ = 0;
164                 deadkey_info_.accent = TEX_NOACCENT;
165                 currentState = init_state_;
166                 return res;
167         }
168         
169         // Check if it is a combination or an exception
170 #if 0
171         KmodException l;
172         l = deadkey_info_.exception_list;
173         
174         while (l) {
175                 if (l->combined == true && l->accent == d.accent) {
176                         deadkey2_ = c;
177                         deadkey2_info_ = d;
178                         comb_info_ = l;
179                         currentState = combined_state_;
180                         return string();
181                 }
182                 if (l->c == c) {
183                         res = l->data;
184                         deadkey_ = 0;
185                         deadkey_info_.accent = TEX_NOACCENT;
186                         currentState = init_state_;
187                         return res;
188                 }
189                 l = l->next;
190         }
191 #else
192         KmodException::const_iterator cit = deadkey_info_.exception_list.begin();
193         KmodException::const_iterator end = deadkey_info_.exception_list.end();
194         for (; cit != end; ++cit) {
195                 if (cit->combined == true && cit->accent == d.accent) {
196                         deadkey2_ = c;
197                         deadkey2_info_ = d;
198                         comb_info_ = (*cit);
199                         currentState = combined_state_;
200                         return string();
201                 }
202                 if (cit->c == c) {
203                         res = cit->data;
204                         deadkey_ = 0;
205                         deadkey_info_.accent = TEX_NOACCENT;
206                         currentState = init_state_;
207                         return res;
208                 }
209         }
210 #endif
211         // Not a combination or an exception. 
212         // Output deadkey1 and keep deadkey2
213         
214         if (deadkey_!= 0)
215                 res = deadkey_;
216         deadkey_ = c;
217         deadkey_info_ = d;
218         currentState = deadkey_state_;
219         return res;
220 }
221
222
223 TransCombinedState::TransCombinedState()
224 {
225         combined_state_ = this;
226 }
227
228
229 #if 0
230 string const TransCombinedState::normalkey(char c, string const & trans)
231 {
232         string res;
233
234         // Check if the key is allowed on the combination
235         if (countChar(comb_info_->data, c) > 0) {
236                 string const temp = DoAccent(c, deadkey2_info_.accent);
237                 res = DoAccent(temp, deadkey_info_.accent);
238                 currentState = init_state_;
239         } else {
240                 // Not allowed. Output deadkey1 and check deadkey2 + c
241                 if (deadkey_ != 0)
242                         res += deadkey_;
243                 res += TOKEN_SEP;
244                 deadkey_ = deadkey2_;
245                 deadkey_info_ = deadkey2_info_;
246                 // Call deadkey state and leave it to setup the FSM
247                 res += deadkey_state_->normalkey(c, trans);
248         }
249         return res;
250 }
251 #else
252 string const TransCombinedState::normalkey(char c)
253 {
254         string res;
255
256         string const temp = DoAccent(c, deadkey2_info_.accent);
257         res = DoAccent(temp, deadkey_info_.accent);
258         currentState = init_state_;
259         return res;
260 }
261 #endif
262
263
264 string const TransCombinedState::deadkey(char c, KmodInfo d)
265 {
266         // Third key in a row. Output the first one and
267         // reenter with shifted deadkeys
268         string res;
269         if (deadkey_ != 0)
270                 res = deadkey_;
271         res += TOKEN_SEP;
272         deadkey_ = deadkey2_;
273         deadkey_info_ = deadkey2_info_;
274         res += deadkey_state_->deadkey(c, d);
275         return res;
276 }
277
278
279 // TransFSM
280 TransFSM::TransFSM():
281         TransFSMData(),
282         TransInitState(),
283         TransDeadkeyState(),
284         TransCombinedState()
285 {
286         currentState = init_state_;
287 }
288
289
290 // TransManager
291
292 // Initialize static member.
293 Trans TransManager::default_;
294
295
296 TransManager::TransManager()
297         : active_(0), t1_(new Trans), t2_(new Trans)
298 {}
299
300
301 TransManager::~TransManager() 
302
303         delete t1_;
304         delete t2_;
305 }
306
307
308 int TransManager::SetPrimary(string const & language)
309 {
310         if (t1_->GetName() == language) 
311                 return 0;
312         
313         return t1_->Load(language);
314 }
315
316
317 int TransManager::SetSecondary(string const & language)
318 {
319         if (t2_->GetName() == language)
320                 return 0;
321         
322         return t2_->Load(language);
323 }
324
325
326 bool TransManager::setCharset(string const & str)
327 {
328         return chset_.loadFile(str);
329 }
330
331
332 void TransManager::EnablePrimary()
333 {
334         if (t1_->IsDefined())
335                 active_ = t1_;
336         
337         lyxerr[Debug::KBMAP] << "Enabling primary keymap" << endl;
338 }
339
340
341 void TransManager::EnableSecondary()
342 {
343         if (t2_->IsDefined())
344                 active_ = t2_;
345         lyxerr[Debug::KBMAP] << "Enabling secondary keymap" << endl;
346 }
347
348
349 void TransManager::DisableKeymap()
350 {
351         active_ = &default_;
352         lyxerr[Debug::KBMAP] << "Disabling keymap" << endl;
353 }
354
355
356 void  TransManager::TranslateAndInsert(char c, LyXText * text)
357 {
358         string res = active_->process(c, *this);
359         
360         // Process with tokens
361         string temp;
362         
363         while(res.length() > 0) {
364                 res = split(res, temp, TransState::TOKEN_SEP);
365                 insert(temp, text);
366         }
367 }
368
369
370 void TransManager::insertVerbatim(string const & str, LyXText * text)
371 {       
372         string::size_type const l = str.length();
373         
374         for (string::size_type i = 0; i < l; ++i) {
375                 if (str[i] == '\"'
376 #ifndef NO_LATEX
377                     && text->getFont(current_view->buffer(),text->cursor.par(),
378                                      text->cursor.pos()).latex() == LyXFont::OFF
379 #endif
380                     && text->getFont(current_view->buffer(),text->cursor.par(),
381                                      text->cursor.pos()).language()->lang() != "hebrew")
382                         current_view->insertCorrectQuote();
383                 else
384                         text->insertChar(current_view, str[i]);
385         }
386 }
387
388
389 void TransManager::insert(string const & str, LyXText * text)
390 {
391         // Go through the character encoding only if the current 
392         // encoding (chset_->name()) matches the current font_norm
393         // (lyrxc->font_norm
394         
395         // Is false to speak about "only if" the current encoding will
396         // almost always be equal to font_norm.
397         pair<bool, int> enc = chset_.encodeString(str);
398         if (chset_.getName() != lyxrc.font_norm || 
399             !enc.first) {
400                 // Could not find an encoding
401                 InsetLatexAccent ins(str);
402                 if (ins.canDisplay()) {
403                         text->insertInset(current_view,
404                                           new InsetLatexAccent(ins));
405                 } else {
406                         insertVerbatim(str, text);
407                 }
408                 return;
409         }
410         string tmp;
411         tmp += static_cast<char>(enc.second);
412         insertVerbatim(tmp, text);
413 }
414
415
416 void TransManager::deadkey(char c, tex_accent accent, LyXText * t)
417 {
418         if (c == 0 && active_ != &default_) {
419                 // A deadkey was pressed that cannot be printed
420                 // or a accent command was typed in the minibuffer
421                 KmodInfo i;
422                 if (active_->isAccentDefined(accent, i) == true) {
423                         string const res = trans_fsm_
424                                 .currentState->deadkey(c, i);
425                         insert(res, t);
426                         return;
427                 }
428         }
429         
430         if (active_ == &default_ || c == 0) {
431                 KmodInfo i;
432                 i.accent = accent;
433 #if 0
434                 i.allowed = lyx_accent_table[accent].native;
435 #endif
436                 i.data.erase();
437 #if 0
438                 i.exception_list = 0;
439 #endif  
440                 string res = trans_fsm_.currentState->deadkey(c, i);
441                 insert(res, t);
442         } else {
443                 // Go through the translation
444                 TranslateAndInsert(c, t);
445         }
446 }