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