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