]> git.lyx.org Git - lyx.git/blob - src/trans.C
52d7a26cd4c3ee456d7712eceae252f4238d6130
[lyx.git] / src / trans.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation "trans.h"
5 #endif
6
7 #include "LyXView.h"
8 #include "trans.h"
9 #include "support/filetools.h"
10 #include "tex-strings.h"
11 #include "lyxlex.h"
12 #include "debug.h"
13 #include "trans_mgr.h"
14
15 using std::endl;
16
17
18 // KmodInfo
19 KmodInfo::KmodInfo()
20 {
21         exception_list = 0;
22 }
23
24
25 // Default Trans
26 bool DefaultTrans::init_ = false;
27
28
29 DefaultTrans::DefaultTrans()
30 {
31         if (init_ == false) {
32                 // Do initialization
33                 init_ = true;
34         }
35 }
36
37
38 string const DefaultTrans::process(char c, TransManager & k)
39 {
40         char dummy[2] = "?";
41         dummy[0] = c;
42     
43         return k.normalkey(c, dummy);
44 }
45
46
47 // Trans class
48
49 Trans::Trans()
50 {
51         int i = 0;
52         for(i = 0; i < TEX_MAX_ACCENT + 1; ++i)
53                 kmod_list_[i] = 0;
54 }
55
56
57 Trans::~Trans()
58 {
59         FreeKeymap();
60 }
61
62
63 void Trans::InsertException(Trans::keyexc & exclist, char c,
64                             string const & data, bool flag, tex_accent accent)
65 {
66         keyexc p = new Keyexc; 
67         p->next = exclist;
68         p->c = c;
69
70         p->data = data;
71         p->combined = flag;
72         p->accent = accent;
73
74         exclist = p;
75 }
76
77
78 void Trans::FreeException(Trans::keyexc & exclist)
79 {
80         Trans::keyexc p = exclist;
81         while (p) {
82                 p = exclist->next;
83                 delete exclist;
84                 exclist = p;
85         }
86 }
87
88
89 void Trans::FreeKeymap()
90 {
91         for(int i = 0; i < 256; ++i)
92                 if (!keymap_[i].empty()) {
93                         //delete keymap_[i];
94                         keymap_[i].erase();
95                 }
96         for(int i = 0; i < TEX_MAX_ACCENT + 1; ++i)
97                 if (kmod_list_[i]) {
98                         FreeException(kmod_list_[i]->exception_list);
99                         delete kmod_list_[i];
100                         kmod_list_[i] = 0;
101                 }
102 }
103
104
105 bool Trans::IsDefined() const
106 {
107         return !name_.empty();
108 }
109
110
111 string const & Trans::GetName() const
112 {
113         return name_;
114 }
115
116
117 enum _kmaptags {
118         KCOMB = 1,
119         KMOD,
120         KMAP,
121         KXMOD,
122         K_LAST
123 };
124
125
126 struct keyword_item kmapTags[K_LAST - 1] = {
127         {"\\kcomb", KCOMB },
128         { "\\kmap", KMAP },
129         { "\\kmod", KMOD },
130         { "\\kxmod", KXMOD }
131 };
132
133
134 tex_accent getkeymod(string const &);
135
136
137 void Trans::AddDeadkey(tex_accent accent, string const & keys,
138                        string const & allowed)
139 {
140         if (kmod_list_[accent]) {
141                 FreeException(kmod_list_[accent]->exception_list);
142                 
143                 delete kmod_list_[accent];
144         }
145         
146         kmod_list_[accent] = new kmod_list_decl;
147         kmod_list_[accent]->data = keys;
148         kmod_list_[accent]->accent = accent;
149         if (allowed == "native") { 
150                 kmod_list_[accent]->allowed= lyx_accent_table[accent].native;
151         } else { 
152                 kmod_list_[accent]->allowed = allowed;
153         }
154         
155         for(string::size_type i = 0; i < keys.length(); ++i) {
156                 string * temp =
157                         &keymap_[static_cast<unsigned char>(keys[i])];
158                 (*temp)[0] = 0; (*temp)[1] = accent;
159         }
160         kmod_list_[accent]->exception_list = 0;
161 }
162
163
164 int Trans::Load(LyXLex & lex)
165 {
166         bool error = false;
167
168         while (lex.IsOK() && !error) {
169                 switch(lex.lex()) {
170                 case KMOD:
171                 {
172                         if (lyxerr.debugging(Debug::KBMAP))
173                                 lyxerr << "KMOD:\t" << lex.text() << endl;
174                         if (lex.next(true)) {
175                                 if (lyxerr.debugging(Debug::KBMAP))
176                                         lyxerr << "key\t`" << lex.text()
177                                                << "'" << endl;
178                         } else
179                                 return -1;
180                         
181                         string keys = lex.GetString();
182
183                         if (lex.next(true)) {
184                                 if ( lyxerr.debugging(Debug::KBMAP))
185                                         lyxerr << "accent\t`" << lex.text()
186                                                << "'" << endl;
187                         } else
188                                 return -1;
189
190                         tex_accent accent = getkeymod(lex.GetString());
191
192                         if (accent == TEX_NOACCENT)
193                                 return -1;
194
195                         if (lex.next(true)) {
196                                 if (lyxerr.debugging(Debug::KBMAP))
197                                         lyxerr << "allowed\t`" << lex.text()
198                                                << "'" << endl;
199                         } else
200                                 return -1;
201
202                         string allowed = lex.GetString();
203
204                         AddDeadkey(accent, keys, allowed);
205                         break;
206                 }       
207                 case KCOMB: {
208                         string str;
209
210                         lyxerr[Debug::KBMAP] << "KCOMB:" << endl;
211                         if (lex.next(true)) {
212                                 str= lex.text();
213                                 lyxerr[Debug::KBMAP] << str << endl;
214                         } else
215                                 return -1;
216                         
217                         tex_accent accent_1 = getkeymod(str);
218                         if (accent_1 == TEX_NOACCENT) return -1;
219
220                         if (lex.next(true)) {
221                                 str = lex.text();
222                                 lyxerr[Debug::KBMAP] << str << endl;
223                         } else
224                                 return -1;
225
226                         tex_accent accent_2= getkeymod(str);
227                         if (accent_2 == TEX_NOACCENT) return -1;
228
229                         if (kmod_list_[accent_1] == 0
230                             || kmod_list_[accent_2] == 0)
231                                 return -1;
232
233                         // Find what key accent_2 is on - should
234                         // check about accent_1 also
235                         int key = 0;
236                         for(; key < 256; ++key) {
237                                 if (!keymap_[key].empty()
238                                     && keymap_[key][0] == 0
239                                     && keymap_[key][1] == accent_2)
240                                         break;
241                         }
242                         string allowed;
243
244                         if (lex.next()) {
245                                 allowed = lex.GetString();
246                                 lyxerr[Debug::KBMAP] << "allowed: "
247                                                      << allowed << endl;
248                         } else
249                                 return -1;
250
251                         InsertException(kmod_list_[accent_1]->exception_list,
252                                         static_cast<char>(key), allowed,
253                                         true, accent_2);
254                 }
255                 break;
256                 case KMAP: {
257                         unsigned char key_from;
258
259                         if (lyxerr.debugging(Debug::KBMAP))
260                                 lyxerr << "KMAP:\t" << lex.text() << endl;
261                         if (lex.next(true)) {
262                                 key_from = lex.text()[0];
263                                 if (lyxerr.debugging(Debug::KBMAP))
264                                         lyxerr << "\t`" << lex.text() << "'"
265                                                << endl;
266                         } else
267                                 return -1;
268
269                         if (lex.next(true)) {
270                                 string string_to = lex.text();
271                                 //char * string_to =
272                                 //      strcpy(new char[strlen(t)+1], t);
273                                 keymap_[key_from] = string_to;
274                                 if (lyxerr.debugging(Debug::KBMAP))
275                                         lyxerr << "\t`" << string_to << "'"
276                                                << endl;
277                         } else
278                                 return -1;
279
280                         break;
281                 }
282                 case KXMOD: {
283                         tex_accent accent;
284                         char key;
285                         string str;
286
287                         if (lyxerr.debugging(Debug::KBMAP))
288                                 lyxerr << "KXMOD:\t" << lex.text() << endl;
289                         if (lex.next(true)) {
290                                 if (lyxerr.debugging(Debug::KBMAP))
291                                         lyxerr << "\t`" << lex.text() << "'"
292                                                << endl;
293                                 accent = getkeymod(lex.GetString());
294                         } else
295                                 return -1;
296
297                         if (lex.next(true)) {
298                                 if (lyxerr.debugging(Debug::KBMAP))
299                                         lyxerr << "\t`" << lex.text() << "'"
300                                                << endl;
301                                 key = lex.text()[0];
302                         } else
303                                 return -1;
304
305                         if (lex.next(true)) {
306                                 if (lyxerr.debugging(Debug::KBMAP))
307                                         lyxerr << "\t`" << lex.text() << "'"
308                                                << endl;
309                                 str = lex.text();
310                         } else
311                                 return -1;
312
313                         InsertException(kmod_list_[accent]->exception_list,
314                                         key, str);
315                         break;
316                 }
317                 case LyXLex::LEX_FEOF:
318                         lyxerr[Debug::PARSER] << "End of parsing" << endl;
319                         break;
320                 default:
321                         lex.printError("ParseKeymapFile: "
322                                        "Unknown tag: `$$Token'");
323                         return -1;
324                 }
325         }
326         return 0;
327 }
328
329
330 bool Trans::isAccentDefined(tex_accent accent, KmodInfo & i) const
331 {
332         if (kmod_list_[accent] != 0) {
333                 i = *kmod_list_[accent];
334                 return true;
335         }
336         return false;
337 }
338
339
340 string const Trans::process(char c, TransManager & k)
341 {
342         string dummy("?");
343         string dt = dummy;
344         string const t = Match(static_cast<unsigned char>(c));
345
346         if (t.empty() && c != 0) {
347                 dt[0] = c;
348                 return k.normalkey(c, dt);
349         } else if (!t.empty()) {
350                 dt = t;
351                 return k.normalkey(c, dt);
352         } else {
353                 return k.deadkey(c,
354                                  *kmod_list_[static_cast<tex_accent>(t[1])]);
355         }
356 }
357
358
359 int Trans::Load(string const & language)
360 {
361         string filename = LibFileSearch("kbd", language, "kmap");
362         if (filename.empty())
363                 return -1;
364
365         FreeKeymap();
366         LyXLex lex(kmapTags, K_LAST-1);
367         lex.setFile(filename);
368         
369         int res = Load(lex);
370
371         if (res == 0) {
372                 name_ = language;
373         } else
374                 name_.erase();
375
376         return res;
377 }
378
379
380 tex_accent getkeymod(string const & p)
381         /* return modifier - decoded from p and update p */
382 {
383         for (int i = 1; i <= TEX_MAX_ACCENT; ++i) {
384                 if (lyxerr.debugging(Debug::KBMAP))
385                         lyxerr << "p = " << p
386                                << ", lyx_accent_table[" << i
387                                << "].name = `" << lyx_accent_table[i].name
388                                << "'" << endl;
389                 
390                 if ( lyx_accent_table[i].name
391                      && contains(p, lyx_accent_table[i].name)) {
392                         lyxerr[Debug::KBMAP] << "Found it!" << endl;
393                         return static_cast<tex_accent>(i);
394                 }
395         }
396         return TEX_NOACCENT;
397 }