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