[Christian Perrier] > So, this bug should finally be assigned to console-data with the > request for creating Unicode keymaps for layouts which don't have > one (Recai mentions Turkish for instance)?
This is a solution. IMO a better one is to patch loadkeys as explained in my previous post. Here is a first try, I patched kbd 1.12 instead of console-tools because I do not know dpatch. Keymap files must declare a charset so that conversion between Unicode, literal and decimal notations can be performed. > What about kbd? You mentioned me in another mail this supposedly more > recent system for handling keyboard layouts.... Not exactly, Turkish keymaps are better in console-data than in kbd, but others are better in kbd. As I said months ago, I do not see the point in maintaining console-tools when it is dead upstream, and am quite upset to see that fr-latin0 was chosen as default for French when it is obsolete and has been removed from kbd. > Should we start to build a fr-latin0u keyboard, german people a > Unicode german keyboard layout and so on? It depends whether Alastair is willing to patch loadkeys or not. > Or could a switch to another keyboard handling system help? No, kbd and console-tools are mostly similar, and kbd has the same problem, Denis
diff -ur kbd-1.12.orig/src/analyze.l kbd-1.12/src/analyze.l --- kbd-1.12.orig/src/analyze.l 2004-01-16 22:51:44.000000000 +0100 +++ kbd-1.12/src/analyze.l 2004-06-24 21:28:14.000000000 +0200 @@ -77,7 +77,7 @@ \- {return(DASH);} \, {return(COMMA);} \+ {return(PLUS);} -{Unicode} {yylval=strtol(yytext+1,NULL,16);return(UNUMBER);} +{Unicode} {yylval=strtol(yytext+1,NULL,16) ^ 0xf000;return(UNUMBER);} {Decimal}|{Octal}|{Hex} {yylval=strtol(yytext,NULL,0);return(NUMBER);} <RVALUE>{Literal} {return((yylval=ksymtocode(yytext))==-1?ERROR:LITERAL);} {Charset} {return(CHARSET);} diff -ur kbd-1.12.orig/src/dumpkeys.c kbd-1.12/src/dumpkeys.c --- kbd-1.12.orig/src/dumpkeys.c 2004-01-16 20:45:31.000000000 +0100 +++ kbd-1.12/src/dumpkeys.c 2004-06-24 23:50:48.000000000 +0200 @@ -131,11 +131,10 @@ t = KTYP(code); v = KVAL(code); if (t >= syms_size) { - code = code ^ 0xf000; - if (!numeric && (p = unicodetoksym(code)) != NULL) + if (!numeric && (p = codetoksym(code)) != NULL) printf("%-16s", p); else - printf("U+%04x ", code); + printf("U+%04x ", code ^ 0xf000); return; } if (t == KT_LETTER) { diff -ur kbd-1.12.orig/src/ksyms.c kbd-1.12/src/ksyms.c --- kbd-1.12.orig/src/ksyms.c 2004-01-16 20:45:31.000000000 +0100 +++ kbd-1.12/src/ksyms.c 2004-06-25 01:14:42.000000000 +0200 @@ -1,7 +1,9 @@ +#include <linux/kd.h> #include <linux/keyboard.h> #include <stdio.h> #include <string.h> #include "ksyms.h" +#include "getfd.h" #include "nls.h" /* Keysyms whose KTYP is KT_LATIN or KT_LETTER and whose KVAL is 0..127. */ @@ -1615,9 +1617,6 @@ /* Functions for both dumpkeys and loadkeys. */ -static int prefer_unicode = 0; -static const char *chosen_charset = NULL; - void list_charsets(FILE *f) { int i,j,lth,ct; @@ -1655,10 +1654,8 @@ sym *p; int i; - if (!strcasecmp(charset, "unicode")) { - prefer_unicode = 1; + if (!strcasecmp(charset, "unicode")) return 0; - } for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) { if (!strcasecmp(charsets[i].charset, charset)) { @@ -1667,7 +1664,6 @@ if(p->name[0]) syms[0].table[i] = p->name; } - chosen_charset = charset; return 0; } } @@ -1677,10 +1673,15 @@ } const char * -unicodetoksym(int code) { +codetoksym(int code) { int i, j; sym *p; + if (KTYP(code) == KT_META) + return NULL; + if (KTYP(code) < syms_size) + return syms[KTYP(code)].table[KVAL(code)]; + code = code ^ 0xf000; if (code < 0) return NULL; if (code < 0x80) @@ -1697,49 +1698,60 @@ /* Functions for loadkeys. */ -int unicode_used = 0; - int ksymtocode(const char *s) { int i; - int j, jmax; + int j; int keycode; + int fd; + int kbd_mode; + int syms_start = 0; sym *p; + if (!s) { + fprintf(stderr, "%s\n", _("null symbol found")); + return -1; + } + + fd = getfd(NULL); + ioctl(fd, KDGKBMODE, &kbd_mode); if (!strncmp(s, "Meta_", 5)) { + /* Temporarily change kbd_mode to ensure that keycode is + right. */ + ioctl(fd, KDSKBMODE, K_XLATE); keycode = ksymtocode(s+5); + ioctl(fd, KDSKBMODE, kbd_mode); if (KTYP(keycode) == KT_LATIN) return K(KT_META, KVAL(keycode)); /* fall through to error printf */ } - for (i = 0; i < syms_size; i++) { - jmax = ((i == 0 && prefer_unicode) ? 128 : syms[i].size); - for (j = 0; j < jmax; j++) + if (kbd_mode == K_UNICODE) { + for (j = 0; j < 0x80; j++) + if (!strcmp(s,iso646_syms[j])) + return (j ^ 0xf000); + syms_start = 1; + } + for (i = syms_start; i < syms_size; i++) { + for (j = 0; j < syms[i].size; j++) if (!strcmp(s,syms[i].table[j])) return K(i, j); } - for (i = 0; i < syn_size; i++) if (!strcmp(s, synonyms[i].synonym)) return ksymtocode(synonyms[i].official_name); - if (prefer_unicode) { + if (kbd_mode == K_UNICODE) { for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) { p = charsets[i].charnames; for (j = charsets[i].start; j < 256; j++, p++) - if (!strcmp(s,p->name)) { - unicode_used = 1; - return (p->uni ^ 0xf000); /* %%% */ - } + if (!strcmp(s,p->name)) + return (p->uni ^ 0xf000); } - } else /* if (!chosen_charset) */ { - /* note: some keymaps use latin1 but with euro, - so set_charset() would fail */ + } else { /* note: some keymaps with charset line still use symbols from more than one character set, - so we cannot have the `if (!chosen_charset)' here */ - + so we cannot have get charset from set_charset() */ for (i = 0; i < 256 - 160; i++) if (!strcmp(s, latin1_syms[i].name)) { fprintf(stderr, @@ -1782,38 +1794,23 @@ } int -unicodetocode(int code) { - const char *s; - - s = unicodetoksym(code); - if (s) - return ksymtocode(s); - else { - unicode_used = 1; - return (code ^ 0xf000); /* %%% */ - } +add_number(int code) +{ + int kbd_mode; + if (KTYP(code) == KT_META) + return code; + ioctl(getfd(NULL), KDGKBMODE, &kbd_mode); + if (kbd_mode == K_UNICODE && KTYP(code) >= syms_size) + return code; + if (kbd_mode != K_UNICODE && KTYP(code) < syms_size) + return code; + return ksymtocode(codetoksym(code)); } int add_capslock(int code) { - char buf[7]; - const char *p; - if (KTYP(code) == KT_LATIN) return K(KT_LETTER, KVAL(code)); - if (KTYP(code) >= syms_size) { - if ((p = unicodetoksym(code ^ 0xf000)) == NULL) { - sprintf(buf, "U+%04x", code ^ 0xf000); - p = buf; - } - } else { - sprintf(buf, "0x%04x", code); - p = buf; - } -#if 0 - /* silence the common usage dumpkeys | loadkeys -u */ - fprintf(stderr, _("plus before %s ignored\n"), p); -#endif return code; } diff -ur kbd-1.12.orig/src/ksyms.h kbd-1.12/src/ksyms.h --- kbd-1.12.orig/src/ksyms.h 1999-10-05 13:42:16.000000000 +0200 +++ kbd-1.12/src/ksyms.h 2004-06-25 00:38:08.000000000 +0200 @@ -23,10 +23,10 @@ extern const int syn_size; extern int set_charset(const char *name); -extern const char *unicodetoksym(int code); +extern const char *codetoksym(int code); extern void list_charsets(FILE *f); extern int ksymtocode(const char *s); -extern int unicodetocode(int code); +extern int add_number(int code); extern int add_capslock(int code); #endif diff -ur kbd-1.12.orig/src/loadkeys.y kbd-1.12/src/loadkeys.y --- kbd-1.12.orig/src/loadkeys.y 2004-01-16 22:51:25.000000000 +0100 +++ kbd-1.12/src/loadkeys.y 2004-06-25 00:37:21.000000000 +0200 @@ -74,7 +74,6 @@ extern char *xstrdup(char *); int key_buf[MAX_NR_KEYMAPS]; int mod; -extern int unicode_used; int private_error_ct = 0; extern int rvalct; @@ -227,13 +226,15 @@ } ; rvalue : NUMBER - {$$=$1;} + {$$=add_number($1);} + | LITERAL + {$$=add_number($1);} | UNUMBER - {$$=($1 ^ 0xf000); unicode_used=1;} + {$$=add_number($1);} | PLUS NUMBER {$$=add_capslock($2);} - | LITERAL - {$$=$1;} + | PLUS UNUMBER + {$$=add_capslock($2);} | PLUS LITERAL {$$=add_capslock($2);} ; @@ -319,7 +320,6 @@ } args = argv + optind - 1; - unicode_used = 0; yywrap(); /* set up the first input file, if any */ if (yyparse() || private_error_ct) { fprintf(stderr, _("syntax error in map file\n")); @@ -766,15 +766,6 @@ int i,j,fail; int oldm; - if (unicode_used) { - /* Switch keyboard mode for a moment - - do not complain about errors. - Do not attempt a reset if the change failed. */ - if (ioctl(fd, KDGKBMODE, &oldm) - || (oldm != K_UNICODE && ioctl(fd, KDSKBMODE, K_UNICODE))) - oldm = K_UNICODE; - } - for(i=0; i<MAX_NR_KEYMAPS; i++) { if (key_map[i]) { for(j=0; j<NR_KEYS; j++) { @@ -839,16 +830,6 @@ } } } - - if(unicode_used && oldm != K_UNICODE) { - if (ioctl(fd, KDSKBMODE, oldm)) { - fprintf(stderr, _("%s: failed to restore keyboard mode\n"), - progname); - } - fprintf(stderr, _("%s: warning: this map uses Unicode symbols\n" - " (perhaps you want to do `kbd_mode -u'?)\n"), - progname); - } return ct; }