[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 via email to