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