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