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