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