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