3 * This file is part of kbd project.
4 * Copyright (C) 1993 Risto Kankkunen.
5 * Copyright (C) 1993 Eugene G. Crosser.
6 * Copyright (C) 1994-2007 Andries E. Brouwer.
7 * Copyright (C) 2007-2013 Alexey Gladkov <gladkov.alexey@gmail.com>
9 * This file is covered by the GNU General Public License,
10 * which should be included with kbd as the file COPYING.
18 #include "modifiers.h"
23 #define U(x) ((x) ^ 0xf000)
26 outchar(FILE *fd, unsigned char c, int comma)
29 fprintf(fd, (c == '\'' || c == '\\') ? "\\%c"
32 fprintf(fd, comma ? "', " : "'");
35 // FIXME: Merge outchar ?
37 dumpchar(FILE *fd, unsigned char c, int comma)
40 fprintf(fd, (c == '\'' || c == '\\') ? "\\%c"
41 : (isgraph(c) || c == ' ' || c >= 0200) ? "%c"
43 fprintf(fd, comma ? "', " : "'");
47 lk_dump_bkeymap(struct keymap *kmap)
52 char flag, magic[] = "bkeymap";
55 if (lk_add_constants(kmap) < 0)
58 if (write(1, magic, 7) == -1)
60 for (i = 0; i < MAX_NR_KEYMAPS; i++) {
61 flag = kmap->key_map[i] ? 1 : 0;
62 if (write(1, &flag, 1) == -1)
65 for (i = 0; i < MAX_NR_KEYMAPS; i++) {
66 if (kmap->key_map[i]) {
67 for (j = 0; j < NR_KEYS / 2; j++) {
68 v = lk_get_key(kmap, i, j);
69 if (write(1, &v, 2) == -1)
76 fail: ERR(kmap, _("Error writing map to file"));
81 mk_mapname(char modifier)
83 static char *mods[8] = {
84 "shift", "altgr", "ctrl", "alt", "shl", "shr", "ctl", "ctr"
92 for (i = 0; i < 8; i++)
93 if (modifier & (1 << i)) {
102 lk_dump_ctable(struct keymap *kmap, FILE *fd)
105 unsigned int i, imax;
108 unsigned int maxfunc;
109 unsigned int keymap_count = 0;
110 unsigned int func_table_offs[MAX_NR_FUNC];
111 unsigned int func_buf_offset = 0;
113 if (lk_add_constants(kmap) < 0)
117 /* not to be translated... */
118 "/* Do not edit this file! It was automatically generated by */\n");
119 fprintf(fd, "/* loadkeys --mktable defkeymap.map > defkeymap.c */\n\n");
120 fprintf(fd, "#include <linux/types.h>\n");
121 fprintf(fd, "#include <linux/keyboard.h>\n");
122 fprintf(fd, "#include <linux/kd.h>\n\n");
124 for (i = 0; i < MAX_NR_KEYMAPS; i++)
125 if (kmap->key_map[i]) {
128 fprintf(fd, "static ");
129 fprintf(fd, "u_short %s_map[NR_KEYS] = {", mk_mapname(i));
130 for (j = 0; j < NR_KEYS; j++) {
133 fprintf(fd, "\t0x%04x,", U(lk_get_key(kmap, i, j)));
135 fprintf(fd, "\n};\n\n");
138 for (imax = MAX_NR_KEYMAPS - 1; imax > 0; imax--)
139 if (kmap->key_map[imax])
141 fprintf(fd, "ushort *key_maps[MAX_NR_KEYMAPS] = {");
142 for (i = 0; i <= imax; i++) {
143 fprintf(fd, (i % 4) ? " " : "\n\t");
144 if (kmap->key_map[i])
145 fprintf(fd, "%s_map,", mk_mapname(i));
149 if (imax < MAX_NR_KEYMAPS - 1)
151 fprintf(fd, "\n};\n\nunsigned int keymap_count = %d;\n\n", keymap_count);
153 /* uglified just for xgettext - it complains about nonterminated strings */
156 " * Philosophy: most people do not define more strings, but they who do\n"
157 " * often want quite a lot of string space. So, we statically allocate\n"
158 " * the default and allocate dynamically in chunks of 512 bytes.\n"
160 for (maxfunc = MAX_NR_FUNC; maxfunc; maxfunc--)
161 if (kmap->func_table[maxfunc - 1])
164 fprintf(fd, "char func_buf[] = {\n");
165 for (i = 0; i < maxfunc; i++) {
166 ptr = kmap->func_table[i];
168 func_table_offs[i] = func_buf_offset;
171 outchar(fd, *ptr, 1);
172 fprintf(fd, "0, \n");
173 func_buf_offset += (ptr - kmap->func_table[i] + 1);
177 fprintf(fd, "\t0\n");
178 fprintf(fd, "};\n\n");
181 "char *funcbufptr = func_buf;\n"
182 "int funcbufsize = sizeof(func_buf);\n"
183 "int funcbufleft = 0; /* space left */\n" "\n");
185 fprintf(fd, "char *func_table[MAX_NR_FUNC] = {\n");
186 for (i = 0; i < maxfunc; i++) {
187 if (kmap->func_table[i])
188 fprintf(fd, "\tfunc_buf + %u,\n", func_table_offs[i]);
190 fprintf(fd, "\t0,\n");
192 if (maxfunc < MAX_NR_FUNC)
193 fprintf(fd, "\t0,\n");
197 if (kmap->prefer_unicode) {
198 fprintf(fd, "\nstruct kbdiacruc accent_table[MAX_DIACR] = {\n");
199 for (i = 0; i < kmap->accent_table_size; i++) {
201 outchar(fd, kmap->accent_table[i].diacr, 1);
202 outchar(fd, kmap->accent_table[i].base, 1);
203 fprintf(fd, "0x%04x},", kmap->accent_table[i].result);
209 fprintf(fd, "};\n\n");
213 fprintf(fd, "\nstruct kbdiacr accent_table[MAX_DIACR] = {\n");
214 for (i = 0; i < kmap->accent_table_size; i++) {
216 outchar(fd, kmap->accent_table[i].diacr, 1);
217 outchar(fd, kmap->accent_table[i].base, 1);
218 outchar(fd, kmap->accent_table[i].result, 0);
225 fprintf(fd, "};\n\n");
227 fprintf(fd, "unsigned int accent_table_size = %d;\n", kmap->accent_table_size);
231 /* void dump_funcs(void) */
233 lk_dump_funcs(struct keymap *kmap, FILE *fd)
237 unsigned int maxfunc;
239 for (maxfunc = MAX_NR_FUNC; maxfunc; maxfunc--) {
240 if (kmap->func_table[maxfunc - 1])
244 for (i = 0; i < maxfunc; i++) {
245 ptr = kmap->func_table[i];
249 fprintf(fd, "string %s = \"", syms[KT_FN].table[i]);
251 for (; *ptr; ptr++) {
252 if (*ptr == '"' || *ptr == '\\') {
255 } else if (isgraph(*ptr) || *ptr == ' ') {
258 fprintf(fd, "\\%03o", *ptr);
266 /* void dump_diacs(void) */
268 lk_dump_diacs(struct keymap *kmap, FILE *fd)
272 if (kmap->prefer_unicode) {
273 for (i = 0; i < kmap->accent_table_size; i++) {
274 fprintf(fd, "compose ");
275 dumpchar(fd, kmap->accent_table[i].diacr & 0xff, 0);
277 dumpchar(fd, kmap->accent_table[i].base & 0xff, 0);
278 fprintf(fd, " to U+%04x\n", kmap->accent_table[i].result);
283 for (i = 0; i < kmap->accent_table_size; i++) {
284 fprintf(fd, "compose ");
285 dumpchar(fd, kmap->accent_table[i].diacr, 0);
287 dumpchar(fd, kmap->accent_table[i].base, 0);
289 dumpchar(fd, kmap->accent_table[i].result, 0);
296 lk_dump_keymaps(struct keymap *kmap, FILE *fd)
301 fprintf(fd, "keymaps");
302 for (i = 0; i < kmap->max_keymap; i++) {
305 m0 = m = kmap->defining[i];
306 while (i+1 < kmap->max_keymap && kmap->defining[i+1] == m+1)
311 ? fprintf(fd, "%c%d" , c, m0-1)
312 : fprintf(fd, "%c%d-%d", c, m0-1, m-1);
318 print_mod(FILE *fd, int x)
321 modifier_t *mod = (modifier_t *) modifiers;
323 if (x & (1 << mod->bit))
324 fprintf(fd, "%s\t", mod->name);
328 fprintf(fd, "plain\t");
333 print_keysym(struct keymap *kmap, FILE *fd, int code, char numeric)
343 if (t >= syms_size) {
344 if (!numeric && (p = codetoksym(kmap, code)) != NULL)
345 fprintf(fd, "%-16s", p);
347 fprintf(fd, "U+%04x ", code ^ 0xf000);
351 if (t == KT_LETTER) {
356 if (!numeric && t < syms_size && v < syms[t].size &&
357 (p = syms[t].table[v])[0])
358 fprintf(fd, "%-*s", 16 - plus, p);
359 else if (!numeric && t == KT_META && v < 128 && v < syms[0].size &&
360 (p = syms[0].table[v])[0])
361 fprintf(fd, "Meta_%-11s", p);
363 fprintf(fd, "0x%04x %s", code, plus ? "" : " ");
367 print_bind(struct keymap *kmap, FILE *fd, int bufj, int i, int j, char numeric)
372 fprintf(fd, "keycode %3d =", i);
373 print_keysym(kmap, fd, bufj, numeric);
378 lk_dump_keys(struct keymap *kmap, FILE *fd, char table_shape, char numeric)
381 int buf[MAX_NR_KEYMAPS];
382 int isletter, islatin, isasexpected;
386 int zapped[MAX_NR_KEYMAPS];
387 int keymapnr = kmap->max_keymap;
392 if (table_shape == FULL_TABLE || table_shape == SEPARATE_LINES)
395 /* first pass: determine whether to set alt_is_meta */
396 for (j = 0; j < MAX_NR_KEYMAPS; j++) {
397 int ja = (j | M_ALT);
399 if (!(j != ja && kmap->defining[j] && kmap->defining[ja]))
402 for (i = 1; i < NR_KEYS; i++) {
403 int buf0, buf1, type;
405 buf0 = lk_get_key(kmap, j, i);
412 if ((type == KT_LATIN || type == KT_LETTER) && KVAL(buf0) < 128) {
413 buf1 = (kmap->defining[ja])
414 ? lk_get_key(kmap, ja, i)
417 if (buf1 != K(KT_META, KVAL(buf0)))
418 goto not_alt_is_meta;
423 fprintf(fd, "alt_is_meta\n");
428 for (i = 1; i < NR_KEYS; i++) {
431 for (j = 0; j < keymapnr; j++) {
432 buf[j] = (kmap->defining[j])
433 ? lk_get_key(kmap, kmap->defining[j]-1, i)
436 if (buf[j] != K_HOLE)
440 if (all_holes && table_shape != FULL_TABLE)
443 if (table_shape == FULL_TABLE) {
444 fprintf(fd, "keycode %3d =", i);
446 for (j = 0; j < keymapnr; j++)
447 print_keysym(kmap, fd, buf[j], numeric);
453 if (table_shape == SEPARATE_LINES) {
454 for (j = 0; j < keymapnr; j++) {
455 //if (buf[j] != K_HOLE)
456 print_bind(kmap, fd, buf[j], i, kmap->defining[j]-1, numeric);
467 islatin = (typ == KT_LATIN || typ == KT_LETTER);
468 isletter = (islatin &&
469 ((val >= 'A' && val <= 'Z') ||
470 (val >= 'a' && val <= 'z')));
475 defs[0] = K(KT_LETTER, val);
476 defs[1] = K(KT_LETTER, val ^ 32);
480 for (j = 4; j < 8; j++)
481 defs[j] = K(KT_LATIN, val & ~96);
483 for (j = 8; j < 16; j++)
484 defs[j] = K(KT_META, KVAL(defs[j-8]));
486 for (j = 0; j < keymapnr; j++) {
487 k = kmap->defining[j] - 1;
489 if ((k >= 16 && buf[j] != K_HOLE) || (k < 16 && buf[j] != defs[k]))
497 /* wipe out predictable meta bindings */
498 for (j = 0; j < keymapnr; j++)
502 for(j = 0; j < keymapnr; j++) {
505 k = kmap->defining[j] - 1;
507 ja = kmap->defining[ka] - 1;
509 if (k != ka && ja >= 0
510 && ((ktyp=KTYP(buf[j])) == KT_LATIN || ktyp == KT_LETTER)
511 && KVAL(buf[j]) < 128) {
512 if (buf[ja] != K(KT_META, KVAL(buf[j])))
513 fprintf(stderr, _("impossible: not meta?\n"));
520 fprintf(fd, "keycode %3d =", i);
523 /* print only a single entry */
524 /* suppress the + for ordinary a-zA-Z */
525 print_keysym(kmap, fd, K(KT_LATIN, val), numeric);
528 /* choose between single entry line followed by exceptions,
529 and long line followed by exceptions; avoid VoidSymbol */
533 for (j = 1; j < keymapnr; j++) {
537 if (buf[j] != buf[0])
540 if (buf[j] != K_HOLE)
544 if (bad <= count && bad < keymapnr-1) {
545 if (buf[0] != K_HOLE) {
546 print_keysym(kmap, fd, buf[0], numeric);
550 for (j = 1; j < keymapnr; j++) {
551 if (buf[j] != buf[0] && !zapped[j]) {
552 print_bind(kmap, fd, buf[j], i, kmap->defining[j]-1, numeric);
557 j < keymapnr && buf[j] != K_HOLE &&
558 (j == 0 || table_shape != UNTIL_HOLE ||
559 kmap->defining[j]-1 == kmap->defining[j-1]-1+1);
561 //print_bind(kmap, fd, buf[j], i, kmap->defining[j]-1, numeric);
562 print_keysym(kmap, fd, buf[j], numeric);
567 for (; j < keymapnr; j++) {
568 if (buf[j] != K_HOLE) {
569 print_bind(kmap, fd, buf[j], i, kmap->defining[j]-1, numeric);
578 lk_dump_keymap(struct keymap *kmap, FILE *fd, char table_shape, char numeric)
580 lk_dump_keymaps(kmap, fd);
581 lk_dump_keys(kmap, fd, table_shape, numeric);
582 lk_dump_funcs(kmap, fd);