Bug#251550: Keyboard freezes when typing non-ASCII letters
[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;
}
Reply to: