Split ksyms source
[platform/upstream/kbd.git] / src / libkeymap / ksyms.c
1 #include <linux/keyboard.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "ksyms.h"
6 #include "nls.h"
7
8 #include "keymap.h"
9
10 #include "syms.cp1250.h"
11 #include "syms.ethiopic.h"
12 #include "syms.iso8859_15.h"
13 #include "syms.iso8859_5.h"
14 #include "syms.iso8859_7.h"
15 #include "syms.iso8859_8.h"
16 #include "syms.iso8859_9.h"
17 #include "syms.koi8.h"
18 #include "syms.latin1.h"
19 #include "syms.latin2.h"
20 #include "syms.latin3.h"
21 #include "syms.latin4.h"
22 #include "syms.mazovia.h"
23 #include "syms.sami.h"
24 #include "syms.thai.h"
25
26 #include "syms.synonyms.h"
27
28 #include "syms.ktyp.h"
29
30 #define E(x) { x, sizeof(x) / sizeof(x[0]) }
31
32 syms_entry
33 const syms[] = {
34         E(iso646_syms),         /* KT_LATIN */
35         E(fn_syms),             /* KT_FN */
36         E(spec_syms),           /* KT_SPEC */
37         E(pad_syms),            /* KT_PAD */
38         E(dead_syms),           /* KT_DEAD */
39         E(cons_syms),           /* KT_CONS */
40         E(cur_syms),            /* KT_CUR */
41         E(shift_syms),          /* KT_SHIFT */
42         { 0, 0 },               /* KT_META */
43         E(ascii_syms),          /* KT_ASCII */
44         E(lock_syms),           /* KT_LOCK */
45         { 0, 0 },               /* KT_LETTER */
46         E(sticky_syms),         /* KT_SLOCK */
47         { 0, 0 },               /*  */
48         E(brl_syms)             /* KT_BRL */
49 };
50
51 #undef E
52
53 const unsigned int syms_size = sizeof(syms) / sizeof(syms_entry);
54 const unsigned int syn_size = sizeof(synonyms) / sizeof(synonyms[0]);
55
56 struct cs {
57     const char *charset;
58     sym *charnames;
59     int start;
60 } charsets[] = {
61     { "", NULL, 256 },
62     { "iso-8859-1",     latin1_syms, 160 },
63     { "iso-8859-2",     latin2_syms, 160 },
64     { "iso-8859-3",     latin3_syms, 160 },
65     { "iso-8859-4",     latin4_syms, 160 },
66     { "iso-8859-5",     iso_8859_5_syms, 160 },
67     { "iso-8859-7",     iso_8859_7_syms, 160 },
68     { "iso-8859-8",     iso_8859_8_syms, 160 },
69     { "iso-8859-9",     iso_8859_9_syms, 208 },
70     { "iso-8859-10",    latin6_syms, 160 },
71     { "iso-8859-15",    iso_8859_15_syms, 160 },
72     { "mazovia",        mazovia_syms, 128 },
73     { "cp-1250",        cp1250_syms, 128 },
74     { "koi8-r",         koi8_syms, 128 },
75     { "koi8-u",         koi8_syms, 128 },
76     { "tis-620",        tis_620_syms, 160 },            /* thai */
77     { "iso-10646-18",   iso_10646_18_syms, 159 },       /* ethiopic */
78     { "iso-ir-197",     iso_ir_197_syms, 160 },         /* sami */
79     { "iso-ir-209",     iso_ir_209_syms, 160 },         /* sami */
80 };
81
82 /* Functions for both dumpkeys and loadkeys. */
83
84 void
85 list_charsets(FILE *f) {
86         int lth,ct;
87         unsigned int i, j;
88         char *mm[] = { "iso-8859-", "koi8-" };
89
90         for (j=0; j<sizeof(mm)/sizeof(mm[0]); j++) {
91                 if(j)
92                         fprintf(f, ",");
93                 fprintf(f, "%s{", mm[j]);
94                 ct = 0;
95                 lth = strlen(mm[j]);
96                 for(i=1; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
97                         if(!strncmp(charsets[i].charset, mm[j], lth)) {
98                                 if(ct++)
99                                         fprintf(f, ",");
100                                 fprintf(f, "%s", charsets[i].charset+lth);
101                         }
102                 }
103                 fprintf(f, "}");
104         }
105         for(i=1; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
106                 for (j=0; j<sizeof(mm)/sizeof(mm[0]); j++) {
107                         lth = strlen(mm[j]);
108                         if(!strncmp(charsets[i].charset, mm[j], lth))
109                                 goto nxti;
110                 }
111                 fprintf(f, ",%s", charsets[i].charset);
112         nxti:;
113         }
114         fprintf(f, "\n");
115 }
116
117 int
118 set_charset(const char *charset) {
119         sym *p;
120         unsigned int i;
121
122         for (i = 1; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
123                 if (!strcasecmp(charsets[i].charset, charset)) {
124                         charsets[0].charset = charsets[i].charset;
125                         charsets[0].charnames = charsets[i].charnames;
126                         charsets[0].start = charsets[i].start;
127                         p = charsets[i].charnames;
128                         for (i = charsets[i].start; i < 256; i++,p++) {
129                                 if(p->name[0])
130                                         syms[0].table[i] = p->name;
131                         }
132                         return 0;
133                 }
134         }
135         return 1;
136 }
137
138 const char *
139 codetoksym(int code) {
140         unsigned int i;
141         int j;
142         sym *p;
143
144         if (code < 0)
145                 return NULL;
146
147         if (code < 0x1000) {    /* "traditional" keysym */
148                 if (code < 0x80)
149                         return iso646_syms[code];
150                 if (KTYP(code) == KT_META)
151                         return NULL;
152                 if (KTYP(code) == KT_LETTER)
153                         code = K(KT_LATIN, KVAL(code));
154                 if (KTYP(code) > KT_LATIN)
155                         return syms[KTYP(code)].table[KVAL(code)];
156
157                 for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
158                         p = charsets[i].charnames;
159                         if (!p)
160                                 continue;
161                         p += KVAL(code) - charsets[i].start;
162                         if (p->name[0])
163                                 return p->name;
164                 }
165         }
166
167         else {                  /* Unicode keysym */
168                 code ^= 0xf000;
169
170                 if (code < 0x80)
171                         return iso646_syms[code];
172
173                 for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
174                         p = charsets[i].charnames;
175                         if (!p)
176                                 continue;
177                         for (j = charsets[i].start; j < 256; j++, p++) {
178                                 if (p->uni == code && p->name[0])
179                                         return p->name;
180                         }
181                 }
182         }
183
184         return NULL;
185 }
186
187 /* Functions for loadkeys. */
188
189 int
190 ksymtocode(struct keymap *kmap, const char *s, int direction) {
191         unsigned int i;
192         int j, jmax;
193         int keycode;
194         sym *p;
195
196         if (direction == TO_AUTO)
197                 direction = kmap->prefer_unicode ? TO_UNICODE : TO_8BIT;
198
199         if (!strncmp(s, "Meta_", 5)) {
200                 keycode = ksymtocode(kmap, s+5, TO_8BIT);
201                 if (KTYP(keycode) == KT_LATIN)
202                         return K(KT_META, KVAL(keycode));
203
204                 /* Avoid error messages for Meta_acute with UTF-8 */
205                 else if(direction == TO_UNICODE)
206                         return (0);
207
208                 /* fall through to error printf */
209         }
210
211         for (i = 0; i < syms_size; i++) {
212                 jmax = ((i == 0 && direction == TO_UNICODE) ? 128 : syms[i].size);
213                 for (j = 0; j < jmax; j++)
214                         if (!strcmp(s,syms[i].table[j]))
215                                 return K(i, j);
216         }
217
218         for (i = 0; i < syn_size; i++)
219                 if (!strcmp(s, synonyms[i].synonym))
220                         return ksymtocode(kmap, synonyms[i].official_name, direction);
221
222         if (direction == TO_UNICODE) {
223                 for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
224                         p = charsets[i].charnames;
225                         for (j = charsets[i].start; j < 256; j++, p++)
226                                 if (!strcmp(s,p->name))
227                                         return (p->uni ^ 0xf000);
228                 }
229         } else /* if (!chosen_charset[0]) */ {
230                 /* note: some keymaps use latin1 but with euro,
231                    so set_charset() would fail */
232                 /* note: some keymaps with charset line still use
233                    symbols from more than one character set,
234                    so we cannot have the  `if (!chosen_charset[0])'  here */
235
236                 for (i = 0; i < 256 - 160; i++)
237                         if (!strcmp(s, latin1_syms[i].name)) {
238                                 log_verbose(kmap, LOG_VERBOSE1,
239                                         _("assuming iso-8859-1 %s\n"), s);
240                                 return K(KT_LATIN, 160 + i);
241                         }
242
243                 for (i = 0; i < 256 - 160; i++)
244                         if (!strcmp(s, iso_8859_15_syms[i].name)) {
245                                 log_verbose(kmap, LOG_VERBOSE1,
246                                         _("assuming iso-8859-15 %s\n"), s);
247                                 return K(KT_LATIN, 160 + i);
248                         }
249
250                 for (i = 0; i < 256 - 160; i++)
251                         if (!strcmp(s, latin2_syms[i].name)) {
252                                 log_verbose(kmap, LOG_VERBOSE1,
253                                         _("assuming iso-8859-2 %s\n"), s);
254                                 return K(KT_LATIN, 160 + i);
255                         }
256
257                 for (i = 0; i < 256 - 160; i++)
258                         if (!strcmp(s, latin3_syms[i].name)) {
259                                 log_verbose(kmap, LOG_VERBOSE1,
260                                         _("assuming iso-8859-3 %s\n"), s);
261                                 return K(KT_LATIN, 160 + i);
262                         }
263
264                 for (i = 0; i < 256 - 160; i++)
265                         if (!strcmp(s, latin4_syms[i].name)) {
266                                 log_verbose(kmap, LOG_VERBOSE1,
267                                         _("assuming iso-8859-4 %s\n"), s);
268                                 return K(KT_LATIN, 160 + i);
269                         }
270         }
271
272         log_error(kmap, _("unknown keysym '%s'\n"), s);
273
274         return CODE_FOR_UNKNOWN_KSYM;
275 }
276
277 int
278 convert_code(struct keymap *kmap, int code, int direction)
279 {
280         const char *ksym;
281         int unicode_forced = (direction == TO_UNICODE);
282         int input_is_unicode = (code >= 0x1000);
283         int result;
284
285         if (direction == TO_AUTO)
286                 direction = kmap->prefer_unicode ? TO_UNICODE : TO_8BIT;
287
288         if (KTYP(code) == KT_META)
289                 return code;
290         else if (!input_is_unicode && code < 0x80)
291                 /* basic ASCII is fine in every situation */
292                 return code;
293         else if (input_is_unicode && (code ^ 0xf000) < 0x80)
294                 /* so is Unicode "Basic Latin" */
295                 return code ^ 0xf000;
296         else if ((input_is_unicode && direction == TO_UNICODE) ||
297                  (!input_is_unicode && direction == TO_8BIT))
298                 /* no conversion necessary */
299                 result = code;
300         else {
301                 /* depending on direction, this will give us either an 8-bit
302                  * K(KTYP, KVAL) or a Unicode keysym xor 0xf000 */
303                 ksym = codetoksym(code);
304                 if (ksym)
305                         result = ksymtocode(kmap, ksym, direction);
306                 else
307                         result = code;
308         }
309
310         /* if direction was TO_UNICODE from the beginning, we return the true
311          * Unicode value (without the 0xf000 mask) */
312         if (unicode_forced && result >= 0x1000)
313                 return result ^ 0xf000;
314         else
315                 return result;
316 }
317
318 int
319 add_capslock(struct keymap *kmap, int code)
320 {
321         if (KTYP(code) == KT_LATIN && (!(kmap->prefer_unicode) || code < 0x80))
322                 return K(KT_LETTER, KVAL(code));
323         else if ((code ^ 0xf000) < 0x100)
324                 /* Unicode Latin-1 Supplement */
325                 /* a bit dirty to use KT_LETTER here, but it should work */
326                 return K(KT_LETTER, code ^ 0xf000);
327         else
328                 return convert_code(kmap, code, TO_AUTO);
329 }