]> git.lyx.org Git - lyx.git/blob - src/trans.C
403ac0630ac5258bc9958402ce4028aacfa6bd59
[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 #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 void Trans::AddDeadkey(tex_accent accent, string const & keys,
143                        string const & allowed)
144 {
145         if (kmod_list_[accent]) {
146                 FreeException(kmod_list_[accent]->exception_list);
147                 
148                 delete kmod_list_[accent];
149         }
150         
151         kmod_list_[accent] = new kmod_list_decl;
152         kmod_list_[accent]->data = keys;
153         kmod_list_[accent]->accent = accent;
154 #if 0
155         if (allowed == "native") { 
156                 kmod_list_[accent]->allowed= lyx_accent_table[accent].native;
157         } else {
158 #endif
159                 kmod_list_[accent]->allowed = allowed;
160 #if 0
161         }
162 #endif
163         
164         for (string::size_type i = 0; i < keys.length(); ++i) {
165                 string & temp =
166                         keymap_[static_cast<unsigned char>(keys[i])];
167                 if (!temp.empty())
168                         temp.erase();
169
170                 // But the question remains: "Should we be allowed
171                 // to change bindings, without unbinding first?"
172                 // Lgb
173                 temp += char(0);
174                 temp += char(accent);
175         }
176         kmod_list_[accent]->exception_list = 0;
177 }
178
179
180 int Trans::Load(LyXLex & lex)
181 {
182         bool error = false;
183
184         while (lex.IsOK() && !error) {
185                 switch (lex.lex()) {
186                 case KMOD:
187                 {
188                         if (lyxerr.debugging(Debug::KBMAP))
189                                 lyxerr << "KMOD:\t" << lex.text() << endl;
190                         if (lex.next(true)) {
191                                 if (lyxerr.debugging(Debug::KBMAP))
192                                         lyxerr << "key\t`" << lex.text()
193                                                << "'" << endl;
194                         } else
195                                 return -1;
196                         
197                         string keys = lex.GetString();
198
199                         if (lex.next(true)) {
200                                 if (lyxerr.debugging(Debug::KBMAP))
201                                         lyxerr << "accent\t`" << lex.text()
202                                                << "'" << endl;
203                         } else
204                                 return -1;
205
206                         tex_accent accent = getkeymod(lex.GetString());
207
208                         if (accent == TEX_NOACCENT)
209                                 return -1;
210
211                         if (lex.next(true)) {
212                                 if (lyxerr.debugging(Debug::KBMAP))
213                                         lyxerr << "allowed\t`" << lex.text()
214                                                << "'" << endl;
215                         } else
216                                 return -1;
217
218                         string allowed = lex.GetString();
219
220                         AddDeadkey(accent, keys, allowed);
221                         break;
222                 }       
223                 case KCOMB: {
224                         string str;
225
226                         lyxerr[Debug::KBMAP] << "KCOMB:" << endl;
227                         if (lex.next(true)) {
228                                 str= lex.text();
229                                 lyxerr[Debug::KBMAP] << str << endl;
230                         } else
231                                 return -1;
232                         
233                         tex_accent accent_1 = getkeymod(str);
234                         if (accent_1 == TEX_NOACCENT) return -1;
235
236                         if (lex.next(true)) {
237                                 str = lex.text();
238                                 lyxerr[Debug::KBMAP] << str << endl;
239                         } else
240                                 return -1;
241
242                         tex_accent accent_2= getkeymod(str);
243                         if (accent_2 == TEX_NOACCENT) return -1;
244
245                         if (kmod_list_[accent_1] == 0
246                             || kmod_list_[accent_2] == 0)
247                                 return -1;
248
249                         // Find what key accent_2 is on - should
250                         // check about accent_1 also
251                         int key = 0;
252                         for (; key < 256; ++key) {
253                                 if (!keymap_[key].empty()
254                                     && keymap_[key][0] == 0
255                                     && keymap_[key][1] == accent_2)
256                                         break;
257                         }
258                         string allowed;
259
260                         if (lex.next()) {
261                                 allowed = lex.GetString();
262                                 lyxerr[Debug::KBMAP] << "allowed: "
263                                                      << allowed << endl;
264                         } else
265                                 return -1;
266
267                         InsertException(kmod_list_[accent_1]->exception_list,
268                                         static_cast<char>(key), allowed,
269                                         true, accent_2);
270                 }
271                 break;
272                 case KMAP: {
273                         unsigned char key_from;
274
275                         if (lyxerr.debugging(Debug::KBMAP))
276                                 lyxerr << "KMAP:\t" << lex.text() << endl;
277                         if (lex.next(true)) {
278                                 key_from = lex.text()[0];
279                                 if (lyxerr.debugging(Debug::KBMAP))
280                                         lyxerr << "\t`" << lex.text() << "'"
281                                                << endl;
282                         } else
283                                 return -1;
284
285                         if (lex.next(true)) {
286                                 string string_to = lex.text();
287                                 //char * string_to =
288                                 //      strcpy(new char[strlen(t)+1], t);
289                                 keymap_[key_from] = string_to;
290                                 if (lyxerr.debugging(Debug::KBMAP))
291                                         lyxerr << "\t`" << string_to << "'"
292                                                << endl;
293                         } else
294                                 return -1;
295
296                         break;
297                 }
298                 case KXMOD: {
299                         tex_accent accent;
300                         char key;
301                         string str;
302
303                         if (lyxerr.debugging(Debug::KBMAP))
304                                 lyxerr << "KXMOD:\t" << lex.text() << endl;
305                         if (lex.next(true)) {
306                                 if (lyxerr.debugging(Debug::KBMAP))
307                                         lyxerr << "\t`" << lex.text() << "'"
308                                                << endl;
309                                 accent = getkeymod(lex.GetString());
310                         } else
311                                 return -1;
312
313                         if (lex.next(true)) {
314                                 if (lyxerr.debugging(Debug::KBMAP))
315                                         lyxerr << "\t`" << lex.text() << "'"
316                                                << endl;
317                                 key = lex.text()[0];
318                         } else
319                                 return -1;
320
321                         if (lex.next(true)) {
322                                 if (lyxerr.debugging(Debug::KBMAP))
323                                         lyxerr << "\t`" << lex.text() << "'"
324                                                << endl;
325                                 str = lex.text();
326                         } else
327                                 return -1;
328
329                         InsertException(kmod_list_[accent]->exception_list,
330                                         key, str);
331                         break;
332                 }
333                 case LyXLex::LEX_FEOF:
334                         lyxerr[Debug::PARSER] << "End of parsing" << endl;
335                         break;
336                 default:
337                         lex.printError("ParseKeymapFile: "
338                                        "Unknown tag: `$$Token'");
339                         return -1;
340                 }
341         }
342         return 0;
343 }
344
345
346 bool Trans::isAccentDefined(tex_accent accent, KmodInfo & i) const
347 {
348         if (kmod_list_[accent] != 0) {
349                 i = *kmod_list_[accent];
350                 return true;
351         }
352         return false;
353 }
354
355
356 #if 0
357 string const Trans::process(char c, TransManager & k)
358 {
359         string dt("?");
360         string const t = Match(static_cast<unsigned char>(c));
361
362         if (t.empty() && c != 0) {
363                 dt[0] = c;
364                 return k.normalkey(c, dt);
365         } else if (!t.empty() && t[0] != char(0)) {
366                 dt = t;
367                 return k.normalkey(c, dt);
368         } else {
369                 return k.deadkey(c,
370                                  *kmod_list_[static_cast<tex_accent>(t[1])]);
371         }
372 }
373 #else
374 string const Trans::process(char c, TransManager & k)
375 {
376         string const t = Match(static_cast<unsigned char>(c));
377
378         if (t.empty() && c != 0) {
379                 return k.normalkey(c);
380         } else if (!t.empty() && t[0] != char(0)) {
381                 return k.normalkey(c);
382         } else {
383                 return k.deadkey(c,
384                                  *kmod_list_[static_cast<tex_accent>(t[1])]);
385         }
386 }
387 #endif
388
389
390 int Trans::Load(string const & language)
391 {
392         string const filename = LibFileSearch("kbd", language, "kmap");
393         if (filename.empty())
394                 return -1;
395
396         FreeKeymap();
397         LyXLex lex(kmapTags, K_LAST-1);
398         lex.setFile(filename);
399         
400         int const res = Load(lex);
401
402         if (res == 0) {
403                 name_ = language;
404         } else
405                 name_.erase();
406
407         return res;
408 }
409
410
411 tex_accent getkeymod(string const & p)
412         /* return modifier - decoded from p and update p */
413 {
414         for (int i = 1; i <= TEX_MAX_ACCENT; ++i) {
415                 if (lyxerr.debugging(Debug::KBMAP))
416                         lyxerr << "p = " << p
417                                << ", lyx_accent_table[" << i
418                                << "].name = `" << lyx_accent_table[i].name
419                                << "'" << endl;
420                 
421                 if (lyx_accent_table[i].name
422                      && contains(p, lyx_accent_table[i].name)) {
423                         lyxerr[Debug::KBMAP] << "Found it!" << endl;
424                         return static_cast<tex_accent>(i);
425                 }
426         }
427         return TEX_NOACCENT;
428 }