Support Unicode compose tables
authorMichael Schutte <michi@uiae.at>
Tue, 28 Apr 2009 13:45:28 +0000 (15:45 +0200)
committerMichael Schutte <michi@uiae.at>
Fri, 1 May 2009 18:29:25 +0000 (20:29 +0200)
Use KDSKBDIACRUC, kbdiacruc etc., if available, to allow the use of
composed characters from more than a single 8-bit charset.  Because the
majority of the existing keymaps uses “compose '…' '…' to '…'”
specifications which allow only 8-bit characters, perform automatical
conversions using the existing infrastructure.

Signed-off-by: Michael Schutte <michi@uiae.at>
src/analyze.l
src/dumpkeys.c
src/ksyms.c
src/loadkeys.y

index cb5a369..b231564 100644 (file)
@@ -122,8 +122,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);}
index 580d480..30900a5 100644 (file)
@@ -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) {
        unsigned 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) {
index faceba6..5bbcfd0 100644 (file)
@@ -1850,6 +1850,8 @@ int
 convert_code(int code, int direction)
 {
        const char *ksym;
+       int unicode_forced = (direction == TO_UNICODE);
+       int result;
 
        if (direction < 0)
                direction = prefer_unicode;
index b1665e6..70b48f9 100644 (file)
@@ -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];
@@ -814,15 +819,24 @@ addfunc(struct kbsentry kbs) {
 
 static void
 compose(int diacr, int base, int res) {
-        struct kbdiacr *ptr;
+        accent_entry *ptr;
+       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);
        }
        ptr = &accent_table[accent_table_size++];
-       ptr->diacr = diacr;
-       ptr->base = base;
-       ptr->result = res;
+       ptr->diacr = convert_code(diacr, direction);
+       ptr->base = convert_code(base, direction);
+       ptr->result = convert_code(res, direction);
 }
 
 static int
@@ -954,21 +968,46 @@ deffuncs(int fd){
 
 static int
 defdiacs(int fd){
-        struct kbdiacrs kd;
-       unsigned int i;
+       unsigned 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;
 }
 
@@ -1254,17 +1293,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);