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