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