]> git.lyx.org Git - lyx.git/blob - src/trans.C
merge from the string-switch branch and ready for a prelease.
[lyx.git] / src / trans.C
1 #include <config.h>
2
3 #include <cstdio>
4
5 #ifdef __GNUG__
6 #pragma implementation "trans.h"
7 #endif
8
9 #include "LyXView.h"
10 #include "trans.h"
11 #include "support/filetools.h"
12 #include "tex-strings.h"
13 #include "lyxlex.h"
14 #include "error.h"
15 #include "trans_mgr.h"
16
17
18 // KmodInfo
19 KmodInfo::KmodInfo()
20 {
21         exception_list=0;
22 }
23
24
25 KmodInfo::KmodInfo(const KmodInfo& o)
26 {
27         (*this)=o;
28 }
29
30
31 KmodInfo& KmodInfo::operator=(const KmodInfo& o)
32 {
33         if (this!=&o) {
34                 allowed=o.allowed;
35                 accent=o.accent;
36                 data=o.data;
37                 exception_list=o.exception_list;
38         }
39
40         return *this;
41 }
42
43     
44 // Default Trans
45 bool DefaultTrans::init_=false;
46
47
48 DefaultTrans::DefaultTrans()
49 {
50         if (init_==false) {
51                 // Do initialization
52                 init_=true;
53         }
54 }
55
56
57 string DefaultTrans::process(char c,TransManager& k)
58 {
59         char dummy[2]="?";
60         dummy[0]=c;
61     
62         return k.normalkey(c,dummy);
63 }
64
65
66 // Trans class
67
68 Trans::Trans()
69 {
70         int i;
71
72         for(i=0; i<256; i++)
73                 keymap_[i]=0;
74
75         for(i=0; i<TEX_MAX_ACCENT+1; i++)
76                 kmod_list_[i]=0;
77 }
78
79
80 Trans::~Trans()
81 {
82         FreeKeymap();
83 }
84
85
86 void Trans::InsertException(Trans::keyexc& exclist, char c,
87                             const string& data,bool flag,tex_accent accent)
88 {
89         keyexc p;
90
91         p = new Keyexc; 
92         p -> next = exclist;
93         p -> c = c;
94
95         p->data = data;
96         p->combined=flag;
97         p->accent=accent;
98
99         exclist = p;
100 }
101
102
103 void Trans::FreeException(Trans::keyexc& exclist)
104 {
105         Trans::keyexc p;
106
107         p = exclist;
108         while (p) {
109                 p = exclist->next;
110                 delete exclist;
111                 exclist = p;
112         }
113 }
114
115
116 void Trans::FreeKeymap()
117 {
118         int i;
119
120         for(i=0; i<256; i++)
121                 if (keymap_[i]) {
122                         delete keymap_[i];
123                         keymap_[i]=0;
124                 }
125         for(i=0; i<TEX_MAX_ACCENT+1; i++)
126                 if (kmod_list_[i]) {
127                         FreeException(kmod_list_[i]->exception_list);
128                         delete kmod_list_[i];
129                         kmod_list_[i]=0;
130                 }
131 }
132
133
134 bool Trans::IsDefined()
135 {
136         return !name_.empty();
137 }
138
139
140 const string& Trans::GetName()
141 {
142         return name_;
143 }
144
145
146 enum _kmaptags {
147         KCOMB=1,
148         KMOD,
149         KMAP,
150         KXMOD,
151         K_LAST
152 };
153
154
155 struct keyword_item kmapTags[K_LAST-1] = {
156         {"\\kcomb",KCOMB },
157         { "\\kmap", KMAP },
158         { "\\kmod", KMOD },
159         { "\\kxmod", KXMOD }
160 };
161
162
163 tex_accent getkeymod(const string&);
164
165
166 void Trans::AddDeadkey(tex_accent accent,const string& keys,
167                        const string& allowed)
168 {
169         if (kmod_list_[accent]) {
170                 FreeException(kmod_list_[accent]->exception_list);
171                 
172                 delete kmod_list_[accent];
173         }
174         
175         kmod_list_[accent] = new kmod_list_decl;
176         kmod_list_[accent]->data = keys;
177         kmod_list_[accent]->accent = accent;
178         if (allowed=="all") { 
179                 kmod_list_[accent]->allowed=lyx_accent_table[accent].native;
180         } else { 
181                 kmod_list_[accent]->allowed = allowed;
182         }
183         
184         for(string::size_type i = 0; i < keys.length(); ++i) {
185                 char * temp;
186                 temp = keymap_[(unsigned char)keys[i]] = new char[2];
187                 temp[0] = 0; temp[1] = accent;
188         }
189         kmod_list_[accent]->exception_list=0;
190 }
191
192
193 int Trans::Load(LyXLex &lex)
194 {
195         bool error = false;
196
197         while (lex.IsOK() && !error) {
198                 switch(lex.lex()) {
199                 case KMOD:
200                 {
201                         if (lyxerr.debugging(Error::KBMAP))
202                                 fprintf(stderr,"KMOD:   %s\n",lex.text());
203                         if (lex.next(true)) {
204                                 if (lyxerr.debugging(Error::KBMAP))
205                                         fprintf(stderr, "key     `%s'\n", lex.text());
206                         } else
207                                 return -1;
208                         
209                         string keys = lex.GetString();
210
211                         if (lex.next(true)) {
212                                 if ( lyxerr.debugging(Error::KBMAP))
213                                         fprintf(stderr, "accent     `%s'\n", lex.text());
214                         } else
215                                 return -1;
216
217                         tex_accent accent = getkeymod(lex.GetString());
218
219                         if (accent==TEX_NOACCENT)
220                                 return -1;
221
222                         if (lex.next(true)) {
223                                 if (lyxerr.debugging(Error::KBMAP))
224                                         fprintf(stderr,
225                                                 "allowed     `%s'\n",
226                                                 lex.text());
227                         } else
228                                 return -1;
229
230                         string allowed = lex.GetString();
231
232                         AddDeadkey(accent, keys, allowed);
233                         break;
234                 }       
235                 case KCOMB: {
236                         const char *str;
237
238                         lyxerr.debug("KCOMB:",Error::KBMAP);
239                         if (lex.next(true)) {
240                                 str=lex.text();
241                                 lyxerr.debug(str,Error::KBMAP);
242                         } else
243                                 return -1;
244                         
245                         tex_accent accent_1=getkeymod(str);
246                         if (accent_1==TEX_NOACCENT) return -1;
247
248                         if (lex.next(true)) {
249                                 str=lex.text();
250                                 lyxerr.debug(str,Error::KBMAP);
251                         } else
252                                 return -1;
253
254                         tex_accent accent_2=getkeymod(str);
255                         if (accent_2==TEX_NOACCENT) return -1;
256
257                         if (kmod_list_[accent_1]==0 || kmod_list_[accent_2]==0)
258                                 return -1;
259
260                         // Find what key accent_2 is on - should check about accent_1 also
261                         int key;
262
263                         for(key=0;key<256;key++) 
264                                 if (keymap_[key] && keymap_[key][0]==0 && keymap_[key][1]==accent_2)
265                                         break;
266                         
267                         string allowed;
268
269                         if (lex.next()) {
270                                 allowed=lex.GetString();
271                                 lyxerr.debug("allowed: "+allowed,Error::KBMAP);
272                         } else
273                                 return -1;
274
275                         InsertException(kmod_list_[accent_1]->exception_list,(char)key,allowed,true,accent_2);
276                 }
277                 break;
278                 case KMAP: {
279                         char key_from;
280                         char *string_to;
281
282                         if (lyxerr.debugging(Error::KBMAP))
283                                 fprintf(stderr, "KMAP: %s\n", lex.text());
284                         if (lex.next(true)) {
285                                 key_from=lex.text()[0];
286                                 if (lyxerr.debugging(Error::KBMAP))
287                                         fprintf(stderr, "     `%s'\n", lex.text());
288                         } else
289                                 return -1;
290
291                         if (lex.next(true)) {
292                                 char const *t = lex.text();
293                                 string_to = strcpy(new char[strlen(t)+1],t);
294                                 keymap_[(unsigned char)key_from]=string_to;
295                                 if (lyxerr.debugging(Error::KBMAP))
296                                         fprintf(stderr, "     `%s'\n", string_to);
297                         } else
298                                 return -1;
299
300                         break;
301                 }
302                 case KXMOD: {
303                         tex_accent accent;
304                         char key;
305                         const char *str;
306
307                         if (lyxerr.debugging(Error::KBMAP))
308                                 fprintf(stderr, "KXMOD: %s\n", lex.text());
309                         if (lex.next(true)) {
310                                 if (lyxerr.debugging(Error::KBMAP))
311                                         fprintf(stderr, "     `%s'\n", lex.text());
312                                 accent = getkeymod(lex.GetString());
313                         } else
314                                 return -1;
315
316                         if (lex.next(true)) {
317                                 if (lyxerr.debugging(Error::KBMAP))
318                                         fprintf(stderr, "      `%s'\n", lex.text());
319                                 key=lex.text()[0];
320                         } else
321                                 return -1;
322
323                         if (lex.next(true)) {
324                                 if (lyxerr.debugging(Error::KBMAP))
325                                         fprintf(stderr, "      `%s'\n", lex.text());
326                                 str=lex.text();
327                         } else
328                                 return -1;
329
330                         InsertException(kmod_list_[accent]->exception_list,key,str);
331                         break;
332                 }
333                 case LyXLex::LEX_FEOF:
334                         lyxerr.debug("End of parsing",Error::LEX_PARSER);
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)
347 {
348         if (kmod_list_[accent]!=0) {
349                 i=*kmod_list_[accent];
350                 return true;
351         }
352         return false;
353 }
354
355
356 string Trans::process(char c,TransManager& k)
357 {
358         char dummy[2]="?";
359         char *dt=dummy;
360         char *t=Match(c);
361         
362     
363         if ((t==0 && (*dt=c)) || (t[0]!=0 && (dt=t)) ){
364                 return k.normalkey(c,dt);
365         } else {
366                 return k.deadkey(c,*kmod_list_[(tex_accent)t[1]]);
367         }
368 }
369
370
371 int Trans::Load(string const &language)
372 {
373         string filename = LibFileSearch("kbd", language, "kmap");
374         if (filename.empty())
375                 return -1;
376
377         FreeKeymap();
378         LyXLex lex(kmapTags, K_LAST-1);
379         lex.setFile(filename);
380         
381         int res=Load(lex);
382
383         if (res==0) {
384                 name_=language;
385         } else
386                 name_.erase();
387
388         return res;
389 }
390
391
392 tex_accent getkeymod(string const &p)
393         /* return modifier - decoded from p and update p */
394 {
395         for (int i = 1; i <= TEX_MAX_ACCENT; i++) {
396                 if (lyxerr.debugging(Error::KBMAP))
397                         fprintf(stderr,
398                                 "p = %s, lyx_accent_table[%d].name = `%s'\n",
399                                 p.c_str(), i, lyx_accent_table[i].name);
400                 
401                 if ( lyx_accent_table[i].name && contains(p, lyx_accent_table[i].name)) {
402                         lyxerr.debug("Found it!",Error::KBMAP);
403                         return (tex_accent)i;
404                 }
405         }
406         return TEX_NOACCENT;
407 }