Replace prefer_unicode with LKFLAG_PREFER_UNICODE
[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 const syms_entry
33 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 const struct cs {
57         const char *charset;
58         const sym *charnames;
59         const int start;
60 } charsets[] = {
61         { "",             NULL,                0 },
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 static unsigned int charsets_size = sizeof(charsets) / sizeof(charsets[0]);
83
84 /* Functions for both dumpkeys and loadkeys. */
85
86 void
87 lk_list_charsets(FILE *f) {
88         int lth,ct;
89         unsigned int i, j;
90         char *mm[] = { "iso-8859-", "koi8-" };
91
92         for (j=0; j<sizeof(mm)/sizeof(mm[0]); j++) {
93                 if(j)
94                         fprintf(f, ",");
95                 fprintf(f, "%s{", mm[j]);
96                 ct = 0;
97                 lth = strlen(mm[j]);
98                 for(i=1; i < charsets_size; i++) {
99                         if(!strncmp(charsets[i].charset, mm[j], lth)) {
100                                 if(ct++)
101                                         fprintf(f, ",");
102                                 fprintf(f, "%s", charsets[i].charset+lth);
103                         }
104                 }
105                 fprintf(f, "}");
106         }
107         for(i=1; i < charsets_size; i++) {
108                 for (j=0; j<sizeof(mm)/sizeof(mm[0]); j++) {
109                         lth = strlen(mm[j]);
110                         if(!strncmp(charsets[i].charset, mm[j], lth))
111                                 goto nxti;
112                 }
113                 fprintf(f, ",%s", charsets[i].charset);
114         nxti:;
115         }
116         fprintf(f, "\n");
117 }
118
119 const char *
120 lk_get_charset(struct keymap *kmap)
121 {
122         if (!kmap || !kmap->charset || kmap->charset >= charsets_size)
123                 return NULL;
124
125         return charsets[kmap->charset].charset;
126 }
127
128 int
129 lk_set_charset(struct keymap *kmap, const char *charset) {
130         unsigned int i;
131
132         for (i = 1; i < charsets_size; i++) {
133                 if (!strcasecmp(charsets[i].charset, charset)) {
134                         kmap->charset = i;
135                         return 0;
136                 }
137         }
138         return 1;
139 }
140
141 const char *
142 codetoksym(struct keymap *kmap, int code) {
143         unsigned int i;
144         int j;
145         sym *p;
146
147         if (code < 0)
148                 return NULL;
149
150         if (code < 0x1000) {    /* "traditional" keysym */
151                 if (code < 0x80)
152                         return iso646_syms[code];
153
154                 if (KTYP(code) == KT_META)
155                         return NULL;
156
157                 if (KTYP(code) == KT_LETTER)
158                         code = K(KT_LATIN, KVAL(code));
159
160                 if (KTYP(code) > KT_LATIN)
161                         return syms[KTYP(code)].table[KVAL(code)];
162
163                 i = kmap->charset;
164                 while (1) {
165                         p = (sym *) charsets[i].charnames;
166                         if (p) {
167                                 p += KVAL(code) - charsets[i].start;
168
169                                 if (p->name[0])
170                                         return p->name;
171                         }
172
173                         i++;
174
175                         if (i == charsets_size)
176                                 i = 0;
177                         if (i == kmap->charset)
178                                 break;
179                 }
180         }
181
182         else {                  /* Unicode keysym */
183                 code ^= 0xf000;
184
185                 if (code < 0x80)
186                         return iso646_syms[code];
187
188                 i = kmap->charset;
189                 while (1) {
190                         p = (sym *) charsets[i].charnames;
191                         if (p) {
192                                 for (j = charsets[i].start; j < 256; j++, p++) {
193                                         if (p->uni == code && p->name[0])
194                                                 return p->name;
195                                 }
196                         }
197
198                         i++;
199
200                         if (i == charsets_size)
201                                 i = 0;
202                         if (i == kmap->charset)
203                                 break;
204                 }
205
206         }
207
208         return NULL;
209 }
210
211 /* Functions for loadkeys. */
212
213 static int
214 kt_latin(struct keymap *kmap, const char *s, int direction) {
215         int i, max;
216
217         if (kmap->charset) {
218                 sym *p = (sym *) charsets[kmap->charset].charnames;
219
220                 for (i = charsets[kmap->charset].start; i < 256; i++, p++) {
221                         if(p->name[0] && !strcmp(s, p->name))
222                                 return K(KT_LATIN, i);
223                 }
224         }
225
226         max = (direction == TO_UNICODE ? 128 : syms[KT_LATIN].size);
227
228         for (i = 0; i < max; i++) {
229                 if (!strcmp(s, syms[KT_LATIN].table[i]))
230                         return K(KT_LATIN, i);
231         }
232
233         return -1;
234 }
235
236 int
237 ksymtocode(struct keymap *kmap, const char *s, int direction) {
238         unsigned int i;
239         int n, j;
240         int keycode;
241         sym *p;
242
243         if (direction == TO_AUTO)
244                 direction = (kmap->flags & LKFLAG_PREFER_UNICODE)
245                         ? TO_UNICODE : TO_8BIT;
246
247         if (!strncmp(s, "Meta_", 5)) {
248                 keycode = ksymtocode(kmap, s+5, TO_8BIT);
249                 if (KTYP(keycode) == KT_LATIN)
250                         return K(KT_META, KVAL(keycode));
251
252                 /* Avoid error messages for Meta_acute with UTF-8 */
253                 else if(direction == TO_UNICODE)
254                         return (0);
255
256                 /* fall through to error printf */
257         }
258
259         if ((n = kt_latin(kmap, s, direction)) >= 0) {
260                 return n;
261         }
262
263         for (i = 1; i < syms_size; i++) {
264                 for (j = 0; j < syms[i].size; j++) {
265                         if (!strcmp(s,syms[i].table[j]))
266                                 return K(i, j);
267                 }
268         }
269
270         for (i = 0; i < syn_size; i++)
271                 if (!strcmp(s, synonyms[i].synonym))
272                         return ksymtocode(kmap, synonyms[i].official_name, direction);
273
274         if (direction == TO_UNICODE) {
275                 i = kmap->charset;
276
277                 while (1) {
278                         p = (sym *) charsets[i].charnames;
279                         if (p) {
280                                 for (j = charsets[i].start; j < 256; j++, p++) {
281                                         if (!strcmp(s,p->name))
282                                                 return (p->uni ^ 0xf000);
283                                 }
284                         }
285
286                         i++;
287
288                         if (i == charsets_size)
289                                 i = 0;
290                         if (i == kmap->charset)
291                                 break;
292                 }
293         } else /* if (!chosen_charset[0]) */ {
294                 /* note: some keymaps use latin1 but with euro,
295                    so set_charset() would fail */
296                 /* note: some keymaps with charset line still use
297                    symbols from more than one character set,
298                    so we cannot have the  `if (!chosen_charset[0])'  here */
299
300                 for (i = 0; i < 256 - 160; i++)
301                         if (!strcmp(s, latin1_syms[i].name)) {
302                                 INFO(kmap, _("assuming iso-8859-1 %s"), s);
303                                 return K(KT_LATIN, 160 + i);
304                         }
305
306                 for (i = 0; i < 256 - 160; i++)
307                         if (!strcmp(s, iso_8859_15_syms[i].name)) {
308                                 INFO(kmap, _("assuming iso-8859-15 %s"), s);
309                                 return K(KT_LATIN, 160 + i);
310                         }
311
312                 for (i = 0; i < 256 - 160; i++)
313                         if (!strcmp(s, latin2_syms[i].name)) {
314                                 INFO(kmap, _("assuming iso-8859-2 %s"), s);
315                                 return K(KT_LATIN, 160 + i);
316                         }
317
318                 for (i = 0; i < 256 - 160; i++)
319                         if (!strcmp(s, latin3_syms[i].name)) {
320                                 INFO(kmap, _("assuming iso-8859-3 %s"), s);
321                                 return K(KT_LATIN, 160 + i);
322                         }
323
324                 for (i = 0; i < 256 - 160; i++)
325                         if (!strcmp(s, latin4_syms[i].name)) {
326                                 INFO(kmap, _("assuming iso-8859-4 %s"), s);
327                                 return K(KT_LATIN, 160 + i);
328                         }
329         }
330
331         ERR(kmap, _("unknown keysym '%s'\n"), s);
332
333         return CODE_FOR_UNKNOWN_KSYM;
334 }
335
336 int
337 convert_code(struct keymap *kmap, int code, int direction)
338 {
339         const char *ksym;
340         int unicode_forced = (direction == TO_UNICODE);
341         int input_is_unicode = (code >= 0x1000);
342         int result;
343
344         if (direction == TO_AUTO)
345                 direction = (kmap->flags & LKFLAG_PREFER_UNICODE)
346                     ? TO_UNICODE : TO_8BIT;
347
348         if (KTYP(code) == KT_META)
349                 return code;
350         else if (!input_is_unicode && code < 0x80)
351                 /* basic ASCII is fine in every situation */
352                 return code;
353         else if (input_is_unicode && (code ^ 0xf000) < 0x80)
354                 /* so is Unicode "Basic Latin" */
355                 return code ^ 0xf000;
356         else if ((input_is_unicode && direction == TO_UNICODE) ||
357                  (!input_is_unicode && direction == TO_8BIT))
358                 /* no conversion necessary */
359                 result = code;
360         else {
361                 /* depending on direction, this will give us either an 8-bit
362                  * K(KTYP, KVAL) or a Unicode keysym xor 0xf000 */
363                 ksym = codetoksym(kmap, code);
364                 if (ksym)
365                         result = ksymtocode(kmap, ksym, direction);
366                 else
367                         result = code;
368         }
369
370         /* if direction was TO_UNICODE from the beginning, we return the true
371          * Unicode value (without the 0xf000 mask) */
372         if (unicode_forced && result >= 0x1000)
373                 return result ^ 0xf000;
374         else
375                 return result;
376 }
377
378 int
379 add_capslock(struct keymap *kmap, int code)
380 {
381         if (KTYP(code) == KT_LATIN && (!(kmap->flags & LKFLAG_PREFER_UNICODE) || code < 0x80))
382                 return K(KT_LETTER, KVAL(code));
383         else if ((code ^ 0xf000) < 0x100)
384                 /* Unicode Latin-1 Supplement */
385                 /* a bit dirty to use KT_LETTER here, but it should work */
386                 return K(KT_LETTER, code ^ 0xf000);
387         else
388                 return convert_code(kmap, code, TO_AUTO);
389 }