Hi, On Tue, Apr 21, 2009 at 12:13:45AM +0200, Pavel Vávra wrote: > Just a note: dumpkeys (from patched package kbd) still returns 0xFF as > composed characters, i.e. it will not be possible to use dumped file > as source to loadkeys. > > Well now I make a summary how to solve descibed bug in UTF-8 environment: > > 1) Apply Samuel's patch into kbd package > 2) add line 'charset "iso-8859-<n>"' into original iso 8859-<n> keymap. > 3) reload boottime.kmap.gz when it is right time to do it
May I dare ask you to try one more (quite massive :-)) patch? It applies to kbd 1.15-1 as currently in sid and squeeze and should also fix the dumpkeys problem you experience, as long as you use “dumpkeys -c iso-8859-2”. > ... and I hope squeeze users will use full console keyboard soon. The Linux console as it is today can only be close to fully functional. But of course kbd can at least catch up with what is possible :-) Cheers, -- Michael Schutte <[email protected]>
diff --git b/src/analyze.l a/src/analyze.l
index ac397a2..097703c 100644
--- b/src/analyze.l
+++ a/src/analyze.l
@@ -91,14 +91,9 @@ To to|To|TO
\- {return(DASH);}
\, {return(COMMA);}
\+ {return(PLUS);}
-{Unicode} {yylval=strtol(yytext+1,NULL,16) ^ 0xf000;
- if (yylval < 0x1000)
- lkfatal1("unicode keysym out of range: %s", yytext);
- else
- return(UNUMBER);
- }
+{Unicode} {yylval=strtol(yytext+1,NULL,16);if(yylval>=0xf000)lkfatal1("unicode keysym out of range: %s",yytext);return(UNUMBER);}
{Decimal}|{Octal}|{Hex} {yylval=strtol(yytext,NULL,0);return(NUMBER);}
-<RVALUE>{Literal} {return((yylval=ksymtocode(yytext))==-1?ERROR:LITERAL);}
+<RVALUE>{Literal} {return((yylval=ksymtocode(yytext, TO_AUTO))==-1?ERROR:LITERAL);}
{Charset} {return(CHARSET);}
{Keymaps} {return(KEYMAPS);}
{Keycode} {return(KEYCODE);}
@@ -122,8 +117,8 @@ To to|To|TO
{On} {return(ON);}
{For} {return(FOR);}
'\\{Octa}' {yylval = strtol(yytext+2,NULL,8); return(CCHAR);}
-'\\.' {yylval = yytext[2]; return(CCHAR);}
-'.' {yylval = yytext[1]; return(CCHAR);}
+'\\.' {yylval = (unsigned char) yytext[2]; return(CCHAR);}
+'.' {yylval = (unsigned char) yytext[1]; return(CCHAR);}
\" {p=(char *) kbs_buf.kb_string;
pmax=p+sizeof(kbs_buf.kb_string)-1;
BEGIN(STR);}
diff --git b/src/dumpkeys.c a/src/dumpkeys.c
index 880c369..64d8904 100644
--- b/src/dumpkeys.c
+++ a/src/dumpkeys.c
@@ -207,16 +207,28 @@ outchar (unsigned char c) {
printf("'");
}
+#ifdef KDGKBDIACRUC
+static struct kbdiacrsuc kd;
+#else
static struct kbdiacrs kd;
+#endif
static void
get_diacs(void) {
static int got_diacs = 0;
+#ifdef KDGKBDIACRUC
+ if(!got_diacs && ioctl(fd, KDGKBDIACRUC, (unsigned long)&kd)) {
+ perror("KDGKBDIACRUC");
+ exit(1);
+ }
+#else
if(!got_diacs && ioctl(fd, KDGKBDIACR, (unsigned long)&kd)) {
perror("KDGKBDIACR");
exit(1);
}
+#endif
+
got_diacs = 1;
}
@@ -231,6 +243,17 @@ dump_diacs(void) {
int i;
get_diacs();
+#ifdef KDGKBDIACRUC
+ for (i = 0; i < kd.kb_cnt; i++) {
+ printf("compose ");
+ outchar(kd.kbdiacruc[i].diacr & 0xff);
+ printf(" ");
+ outchar(kd.kbdiacruc[i].base & 0xff);
+ printf(" to ");
+ outchar(convert_code(kd.kbdiacruc[i].result ^ 0xf000, TO_8BIT));
+ printf("\n");
+ }
+#else
for (i = 0; i < kd.kb_cnt; i++) {
printf("compose ");
outchar(kd.kbdiacr[i].diacr);
@@ -240,8 +263,9 @@ dump_diacs(void) {
outchar(kd.kbdiacr[i].result);
printf("\n");
}
+#endif
}
-#endif
+#endif
static void
show_short_info(void) {
diff --git b/src/ksyms.c a/src/ksyms.c
index 9562c77..27e987c 100644
--- b/src/ksyms.c
+++ a/src/ksyms.c
@@ -1,7 +1,7 @@
-#include <linux/kd.h>
#include <linux/keyboard.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "ksyms.h"
#include "nls.h"
@@ -1645,8 +1645,8 @@ struct cs {
/* Functions for both dumpkeys and loadkeys. */
-static int prefer_unicode = 0;
-static const char *chosen_charset = NULL;
+int prefer_unicode = 0;
+static char *chosen_charset = NULL;
void
list_charsets(FILE *f) {
@@ -1685,11 +1685,6 @@ set_charset(const char *charset) {
sym *p;
int i;
- if (!strcasecmp(charset, "unicode")) {
- prefer_unicode = 1;
- return 0;
- }
-
for (i = 1; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
if (!strcasecmp(charsets[i].charset, charset)) {
charsets[0].charset = charsets[i].charset;
@@ -1700,7 +1695,9 @@ set_charset(const char *charset) {
if(p->name[0])
syms[0].table[i] = p->name;
}
- chosen_charset = charset;
+ if (chosen_charset)
+ free(chosen_charset);
+ chosen_charset = strdup(charset);
return 0;
}
}
@@ -1711,86 +1708,94 @@ set_charset(const char *charset) {
const char *
codetoksym(int code) {
- int i, j;
+ unsigned int i;
+ int j;
sym *p;
- if (KTYP(code) == KT_META)
- return NULL;
- if (KTYP(code) == KT_LETTER)
- code = K(KT_LATIN, KVAL(code));
- if (KTYP(code) < syms_size)
- return syms[KTYP(code)].table[KVAL(code)];
- code = code ^ 0xf000;
if (code < 0)
return NULL;
- if (code < 0x80)
- return iso646_syms[code];
- for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
- p = charsets[i].charnames;
- for (j = charsets[i].start; j < 256; j++, p++) {
- if (p->uni == code && p->name[0])
+
+ if (code < 0x1000) { /* "traditional" keysym */
+ if (code < 0x80)
+ return iso646_syms[code];
+ if (KTYP(code) == KT_META)
+ return NULL;
+ if (KTYP(code) == KT_LETTER)
+ code = K(KT_LATIN, KVAL(code));
+ if (KTYP(code) > KT_LATIN)
+ return syms[KTYP(code)].table[KVAL(code)];
+
+ for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
+ p = charsets[i].charnames;
+ if (!p)
+ continue;
+ p += KVAL(code) - charsets[i].start;
+ if (p->name[0])
return p->name;
}
}
+
+ else { /* Unicode keysym */
+ code ^= 0xf000;
+
+ if (code < 0x80)
+ return iso646_syms[code];
+
+ for (i = 0; i < sizeof(charsets)/sizeof(charsets[0]); i++) {
+ p = charsets[i].charnames;
+ if (!p)
+ continue;
+ for (j = charsets[i].start; j < 256; j++, p++) {
+ if (p->uni == code && p->name[0])
+ return p->name;
+ }
+ }
+ }
+
return NULL;
}
/* Functions for loadkeys. */
int
-ksymtocode(const char *s) {
+ksymtocode(const char *s, int direction) {
int i;
- int j;
+ int j, jmax;
int keycode;
- int save_prefer_unicode;
- int syms_start = 0;
sym *p;
- if (!s) {
- fprintf(stderr, "%s\n", _("null symbol found"));
- return -1;
- }
+ if (direction < 0)
+ direction = prefer_unicode;
if (!strncmp(s, "Meta_", 5)) {
- /* Temporarily set prefer_unicode to ensure that keycode is
- right. */
- save_prefer_unicode = prefer_unicode;
- prefer_unicode = 0;
- keycode = ksymtocode(s+5);
- prefer_unicode = save_prefer_unicode;
+ keycode = ksymtocode(s+5, TO_8BIT);
if (KTYP(keycode) == KT_LATIN)
return K(KT_META, KVAL(keycode));
/* Avoid error messages for Meta_acute with UTF-8 */
- else if(prefer_unicode)
+ else if(direction)
return (0);
/* fall through to error printf */
}
- if (prefer_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++)
+ for (i = 0; i < syms_size; i++) {
+ jmax = ((i == 0 && direction) ? 128 : syms[i].size);
+ for (j = 0; j < jmax; 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);
+ return ksymtocode(synonyms[i].official_name, direction);
- if (prefer_unicode) {
+ if (direction) {
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)) {
+ if (!strcmp(s,p->name))
return (p->uni ^ 0xf000);
- }
}
} else /* if (!chosen_charset) */ {
/* note: some keymaps use latin1 but with euro,
@@ -1841,32 +1846,50 @@ ksymtocode(const char *s) {
}
int
-add_number(int code)
+convert_code(int code, int direction)
{
- const char * kc;
+ const char *ksym;
+ int unicode_forced = (direction == TO_UNICODE);
+ int result;
+
+ if (direction < 0)
+ direction = prefer_unicode;
+
if (KTYP(code) == KT_META)
return code;
- if (prefer_unicode && KTYP(code) >= syms_size) {
- if ((code ^ 0xf000) < 0x80)
- return K(KT_LATIN, code ^ 0xf000);
+ else if (direction == (code >= 0x1000))
+ result = code; /* no conversion necessary */
+ else if (code < 0x80)
+ result = direction ? (code ^ 0xf000) : code;
+ else if ((code ^ 0xf000) < 0x80)
+ result = direction ? code : (code ^ 0xf000);
+ else {
+ /* depending on direction, this will give us either an 8-bit
+ * K(KTYP, KVAL) or a Unicode keysym xor 0xf000 */
+ ksym = codetoksym(code);
+ if (ksym)
+ result = ksymtocode(ksym, direction);
else
- return code;
+ result = code;
}
- if (!prefer_unicode && KTYP(code) < syms_size)
- return code;
- kc = codetoksym(code);
- if (kc == NULL)
- return code;
+
+ /* if direction was TO_UNICODE from the beginning, we return the true
+ * Unicode value (without the 0xf000 mask) */
+ if (unicode_forced && result >= 0x1000)
+ return result ^ 0xf000;
else
- return ksymtocode(kc);
+ return result;
}
int
add_capslock(int code)
{
- if (KTYP(code) == KT_LATIN)
+ if (KTYP(code) == KT_LATIN && (!prefer_unicode || code < 0x80))
return K(KT_LETTER, KVAL(code));
- if (KTYP(code ^ 0xf000) == KT_LATIN)
- return K(KT_LETTER, KVAL(code ^ 0xf000));
- return add_number(code);
+ else if ((code ^ 0xf000) < 0x100)
+ /* Unicode Latin-1 Supplement */
+ /* a bit dirty to use KT_LETTER here, but it should work */
+ return K(KT_LETTER, code ^ 0xf000);
+ else
+ return convert_code(code, TO_AUTO);
}
diff --git b/src/ksyms.h a/src/ksyms.h
index df6e275..4eddc4e 100644
--- b/src/ksyms.h
+++ a/src/ksyms.h
@@ -25,11 +25,16 @@ extern const int syn_size;
/* Returned by ksymtocode to report an unknown symbol */
#define CODE_FOR_UNKNOWN_KSYM (-1)
+/* Directions for converting keysyms */
+#define TO_AUTO (-1) /* use prefer_unicode */
+#define TO_8BIT 0
+#define TO_UNICODE 1
+
extern int set_charset(const char *name);
extern const char *codetoksym(int code);
extern void list_charsets(FILE *f);
-extern int ksymtocode(const char *s);
-extern int add_number(int code);
+extern int ksymtocode(const char *s, int direction);
+extern int convert_code(int code, int direction);
extern int add_capslock(int code);
#endif
diff --git b/src/loadkeys.y a/src/loadkeys.y
index 57fc78b..64cb8ee 100644
--- b/src/loadkeys.y
+++ a/src/loadkeys.y
@@ -44,7 +44,12 @@ int alt_is_meta = 0;
/* the kernel structures we want to set or print */
u_short *key_map[MAX_NR_KEYMAPS];
char *func_table[MAX_NR_FUNC];
-struct kbdiacr accent_table[MAX_DIACR];
+#ifdef KDSKBDIACRUC
+typedef struct kbdiacruc accent_entry;
+#else
+typedef struct kbdiacr accent_entry;
+#endif
+accent_entry accent_table[MAX_DIACR];
unsigned int accent_table_size = 0;
char key_is_constant[NR_KEYS];
@@ -63,7 +68,7 @@ static void killkey(int index, int table);
static void compose(int diacr, int base, int res);
static void do_constant(void);
static void do_constant_key (int, u_short);
-static void loadkeys(char *console, int *warned);
+static void loadkeys(char *console);
static void mktable(void);
static void bkeymap(void);
static void strings_as_usual(void);
@@ -73,6 +78,7 @@ static void strings_as_usual(void);
static void compose_as_usual(char *charset);
static void lkfatal0(const char *, int);
extern int set_charset(const char *charset);
+extern int prefer_unicode;
extern char *xstrdup(char *);
int key_buf[MAX_NR_KEYMAPS];
int mod;
@@ -231,15 +237,15 @@ rvalue1 : rvalue
}
;
rvalue : NUMBER
- {$$=add_number($1);}
- | LITERAL
- {$$=add_number($1);}
- | UNUMBER
- {$$=add_number($1);}
+ {$$=convert_code($1, TO_AUTO);}
| PLUS NUMBER
{$$=add_capslock($2);}
- | PLUS UNUMBER
- {$$=add_capslock($2);}
+ | UNUMBER
+ {$$=convert_code($1^0xf000, TO_AUTO);}
+ | PLUS UNUMBER
+ {$$=add_capslock($2^0xf000);}
+ | LITERAL
+ {$$=$1;}
| PLUS LITERAL
{$$=add_capslock($2);}
;
@@ -263,7 +269,7 @@ usage(void) {
" -h --help display this help text\n"
" -m --mktable output a \"defkeymap.c\" to stdout\n"
" -s --clearstrings clear kernel string table\n"
-" -u --unicode implicit conversion to Unicode\n"
+" -u --unicode force conversion to Unicode\n"
" -v --verbose report the changes\n"), PACKAGE_VERSION, DEFMAP);
exit(1);
}
@@ -272,7 +278,6 @@ char **args;
int optb = 0;
int optd = 0;
int optm = 0;
-int optu = 0;
int opts = 0;
int verbose = 0;
int quiet = 0;
@@ -299,7 +304,6 @@ main(int argc, char *argv[]) {
int fd;
int mode;
char *console = NULL;
- int warned = 0;
set_progname(argv[0]);
@@ -329,8 +333,7 @@ main(int argc, char *argv[]) {
opts = 1;
break;
case 'u':
- set_charset("unicode");
- optu = 1;
+ prefer_unicode = 1;
break;
case 'q':
quiet = 1;
@@ -346,17 +349,17 @@ main(int argc, char *argv[]) {
}
}
- if (!optm) {
+ if (!optm && !prefer_unicode) {
+ /* no -u option: auto-enable it if console is in Unicode mode */
fd = getfd(NULL);
- if (!optu) {
- if (ioctl(fd, KDGKBMODE, &mode)) {
- perror("KDGKBMODE");
- fprintf(stderr, _("loadkeys: error reading keyboard mode\n"));
- exit(1);
- }
- if (mode == K_UNICODE)
- set_charset("unicode");
+ if (ioctl(fd, KDGKBMODE, &mode)) {
+ perror("KDGKBMODE");
+ fprintf(stderr, _("loadkeys: error reading keyboard mode\n"));
+ exit(1);
}
+ if (mode == K_UNICODE)
+ prefer_unicode = 1;
+ close(fd);
}
args = argv + optind - 1;
@@ -384,14 +387,14 @@ main(int argc, char *argv[]) {
char c = *e;
*e = '\0';
if (verbose) printf("%s\n", s);
- loadkeys(s, &warned);
+ loadkeys(s);
*e = c;
s = e;
}
free(buf);
}
else
- loadkeys(NULL, &warned);
+ loadkeys(NULL);
exit(0);
}
@@ -808,23 +811,31 @@ addfunc(struct kbsentry kbs) {
static void
compose(int diacr, int base, int res) {
- struct kbdiacr *p;
+ accent_entry *p;
+ int direction;
+
+#ifdef KDSKBDIACRUC
+ if (prefer_unicode)
+ direction = TO_UNICODE;
+ else
+#endif
+ direction = TO_8BIT;
+
if (accent_table_size == MAX_DIACR) {
fprintf(stderr, _("compose table overflow\n"));
exit(1);
}
p = &accent_table[accent_table_size++];
- p->diacr = diacr;
- p->base = base;
- p->result = res;
+ p->diacr = convert_code(diacr, direction);
+ p->base = convert_code(base, direction);
+ p->result = convert_code(res, direction);
}
static int
-defkeys(int fd, char *cons, int *warned) {
+defkeys(int fd) {
struct kbentry ke;
int ct = 0;
int i,j,fail;
- int oldm;
for(i=0; i<MAX_NR_KEYMAPS; i++) {
if (key_map[i]) {
@@ -949,21 +960,46 @@ deffuncs(int fd){
static int
defdiacs(int fd){
- struct kbdiacrs kd;
- int i;
+ int i, count;
+ struct kbdiacrs kd;
+#ifdef KDSKBDIACRUC
+ struct kbdiacrsuc kdu;
+#endif
- kd.kb_cnt = accent_table_size;
- if (kd.kb_cnt > MAX_DIACR) {
- kd.kb_cnt = MAX_DIACR;
+ count = accent_table_size;
+ if (count > MAX_DIACR) {
+ count = MAX_DIACR;
fprintf(stderr, _("too many compose definitions\n"));
}
- for (i = 0; i < kd.kb_cnt; i++)
- kd.kbdiacr[i] = accent_table[i];
- if(ioctl(fd, KDSKBDIACR, (unsigned long) &kd)) {
- perror("KDSKBDIACR");
- exit(1);
+#ifdef KDSKBDIACRUC
+ if (prefer_unicode) {
+ kdu.kb_cnt = count;
+ for (i = 0; i < kdu.kb_cnt; i++) {
+ kdu.kbdiacruc[i].diacr = accent_table[i].diacr;
+ kdu.kbdiacruc[i].base = accent_table[i].base;
+ kdu.kbdiacruc[i].result = accent_table[i].result;
+ }
+ if(ioctl(fd, KDSKBDIACRUC, (unsigned long) &kdu)) {
+ perror("KDSKBDIACRUC");
+ exit(1);
+ }
}
+ else
+#endif
+ {
+ kd.kb_cnt = count;
+ for (i = 0; i < kd.kb_cnt; i++) {
+ kd.kbdiacr[i].diacr = accent_table[i].diacr;
+ kd.kbdiacr[i].base = accent_table[i].base;
+ kd.kbdiacr[i].result = accent_table[i].result;
+ }
+ if(ioctl(fd, KDSKBDIACR, (unsigned long) &kd)) {
+ perror("KDSKBDIACR");
+ exit(1);
+ }
+ }
+
return kd.kb_cnt;
}
@@ -1023,12 +1059,12 @@ do_constant (void) {
}
static void
-loadkeys (char *console, int *warned) {
+loadkeys (char *console) {
int fd;
int keyct, funcct, diacct = 0;
fd = getfd(console);
- keyct = defkeys(fd, console, warned);
+ keyct = defkeys(fd);
funcct = deffuncs(fd);
if (verbose) {
printf(_("\nChanged %d %s and %d %s.\n"),
@@ -1248,17 +1284,34 @@ mktable () {
printf("\t0,\n");
printf("};\n");
- printf("\nstruct kbdiacr accent_table[MAX_DIACR] = {\n");
- for (i = 0; i < accent_table_size; i++) {
- printf("\t{");
- outchar(accent_table[i].diacr, 1);
- outchar(accent_table[i].base, 1);
- outchar(accent_table[i].result, 0);
- printf("},");
+#ifdef KDSKBDIACRUC
+ if (prefer_unicode) {
+ printf("\nstruct kbdiacruc accent_table[MAX_DIACR] = {\n");
+ for (i = 0; i < accent_table_size; i++) {
+ printf("\t{");
+ outchar(accent_table[i].diacr, 1);
+ outchar(accent_table[i].base, 1);
+ printf("0x%04x},", accent_table[i].result);
+ if(i%2) printf("\n");
+ }
if(i%2) printf("\n");
+ printf("};\n\n");
+ }
+ else
+#endif
+ {
+ printf("\nstruct kbdiacr accent_table[MAX_DIACR] = {\n");
+ for (i = 0; i < accent_table_size; i++) {
+ printf("\t{");
+ outchar(accent_table[i].diacr, 1);
+ outchar(accent_table[i].base, 1);
+ outchar(accent_table[i].result, 0);
+ printf("},");
+ if(i%2) printf("\n");
+ }
+ if(i%2) printf("\n");
+ printf("};\n\n");
}
- if(i%2) printf("\n");
- printf("};\n\n");
printf("unsigned int accent_table_size = %d;\n",
accent_table_size);
signature.asc
Description: Digital signature

