[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1 of 2] Fix keymap handling for vnc console



Fix keymap handling for international keyboards.

Signed-off-by: John Haxby <john.haxby@xxxxxxxxxx>


diff --git a/keymaps.c b/keymaps.c
index 1984678..4029500 100644
--- a/keymaps.c
+++ b/keymaps.c
@@ -22,60 +22,62 @@
 * THE SOFTWARE.
 */

+static int cmp_keysym(const void *a, const void *b) {
+    return strcmp(((name2keysym_t *) a)->name, ((name2keysym_t *) b)->name);
+}
+
static int get_keysym(const char *name)
{
-    name2keysym_t *p;
-    for(p = name2keysym; p->name != NULL; p++) {
-        if (!strcmp(p->name, name))
-            return p->keysym;
+    static int n = -1;
+    int l, r, m;
+
+    if (n < 0) {
+       for (n = 0; name2keysym[n].name; n++);
+       qsort(name2keysym, n, sizeof(name2keysym_t), cmp_keysym);
+    }
+    l = 0;
+    r = n-1;
+    while (l <= r) {
+       m = (l + r) / 2;
+       int cmp = strcmp(name2keysym[m].name, name);
+       if (cmp < 0)
+           l = m + 1;
+       else if (cmp > 0)
+           r = m - 1;
+       else
+           return name2keysym[m].keysym;
+    }
+    if (name[0] == 'U') {
+       /* unicode symbol key */
+       char *ptr;
+       int k = strtol(name+1, &ptr, 16);
+       return *ptr ? 0 : k;
    }
    return 0;
}

-struct key_range {
-    int start;
-    int end;
-    struct key_range *next;
-};
+#define MAX_SCANCODE 256
+#define KEY_LOCALSTATE 0x1
+#define KEY_KEYPAD 0x2

-#define MAX_NORMAL_KEYCODE 512
-#define MAX_EXTRA_COUNT 256
typedef struct {
-    uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
-    struct {
-       int keysym;
-       uint16_t keycode;
-    } keysym2keycode_extra[MAX_EXTRA_COUNT];
-    int extra_count;
-    struct key_range *keypad_range;
-    struct key_range *numlock_range;
-    struct key_range *shift_range;
-    struct key_range *localstate_range;
-} kbd_layout_t;
+    int keysym;
+    int keycode;
+} keysym2keycode_t;

-static void add_to_key_range(struct key_range **krp, int code) {
-    struct key_range *kr;
-    for (kr = *krp; kr; kr = kr->next) {
-       if (code >= kr->start && code <= kr->end)
-           break;
-       if (code == kr->start - 1) {
-           kr->start--;
-           break;
-       }
-       if (code == kr->end + 1) {
-           kr->end++;
-           break;
-       }
-    }
-    if (kr == NULL) {
-       kr = qemu_mallocz(sizeof(*kr));
-       if (kr) {
-           kr->start = kr->end = code;
-           kr->next = *krp;
-           *krp = kr;
-       }
-    }
-}
+typedef struct {
+    int n;
+    keysym2keycode_t k[MAX_SCANCODE];
+} keysym_map_t;
+
+typedef struct {
+    keysym_map_t plain;
+    keysym_map_t shift;
+    keysym_map_t altgr;
+    keysym_map_t shift_altgr;
+    keysym_map_t numlock;
+    uint32_t flags [MAX_SCANCODE];
+} kbd_layout_t;

static kbd_layout_t *parse_keyboard_layout(const char *language,
                                           kbd_layout_t * k)
@@ -97,143 +99,209 @@ static kbd_layout_t *parse_keyboard_layout(const char 
*language,
                "Could not read keymap file: '%s'\n", file_name);
        return 0;
    }
-    for(;;) {
-       if (fgets(line, 1024, f) == NULL)
-            break;
-        len = strlen(line);
-        if (len > 0 && line[len - 1] == '\n')
-            line[len - 1] = '\0';
-        if (line[0] == '#')
+    while (fgets(line, 1024, f)) {
+       char *ptr = strchr(line, '#');
+       char keyname[1024], p1[1024], p2[1024];
+       int keysym, keycode;
+       int shift = 0;
+       int altgr = 0;
+       int addupper = 0;
+       int numlock = 0;
+       int inhibit = 0;
+
+       if (ptr)
+           *ptr-- = '\0';
+       else
+           ptr = &line[strlen(line)-1];
+       while (isspace(*ptr))
+           *ptr-- = '\0';
+       if (!*line)
+           continue;
+       if (strncmp(line, "map ", 4) == 0)
+           continue;
+       if (sscanf(line, "include %s", p1) == 1) {
+           parse_keyboard_layout(p1, k);
            continue;
-       if (!strncmp(line, "map ", 4))
+       }
+       if (sscanf(line, "%s %i %s %s", keyname, &keycode, p1, p2) == 4) {
+           shift = (strcmp(p1, "shift") == 0 || strcmp(p2, "shift") == 0);
+           altgr = (strcmp(p1, "altgr") == 0 || strcmp(p2, "altgr") == 0);
+       } else if (sscanf(line, "%s %i %s", keyname, &keycode, p1) == 3) {
+           shift = (strcmp(p1, "shift") == 0);
+           altgr = (strcmp(p1, "altgr") == 0);
+           addupper = (strcmp(p1, "addupper") == 0);
+           numlock = (strcmp(p1, "numlock") == 0);
+           inhibit = (strcmp(p1, "inhibit") == 0);
+       } else if (sscanf(line, "%s %i", keyname, &keycode) != 2)
+           /* silently ignore spurious lines */
+           continue;
+
+       if (inhibit)
+           continue;
+       if ((keysym = get_keysym(keyname)) == 0) {
+           fprintf(stderr, "%s: warning: unknown keysym %s\n",
+                   file_name, keyname);
            continue;
-       if (!strncmp(line, "include ", 8)) {
-           parse_keyboard_layout(line + 8, k);
-        } else {
-           char *end_of_keysym = line;
-           while (*end_of_keysym != 0 && *end_of_keysym != ' ')
-               end_of_keysym++;
-           if (*end_of_keysym) {
-               int keysym;
-               *end_of_keysym = 0;
-               keysym = get_keysym(line);
-               if (keysym == 0) {
-                    //             fprintf(stderr, "Warning: unknown keysym 
%s\n", line);
-               } else {
-                   const char *rest = end_of_keysym + 1;
-                   char *rest2;
-                   int keycode = strtol(rest, &rest2, 0);
-
-                   if (rest && strstr(rest, "numlock")) {
-                       add_to_key_range(&k->keypad_range, keycode);
-                       add_to_key_range(&k->numlock_range, keysym);
-                       //fprintf(stderr, "keypad keysym %04x keycode %d\n", 
keysym, keycode);
-                   }
-                   if (rest && strstr(rest, "shift")) {
-                       add_to_key_range(&k->shift_range, keysym);
-                       //fprintf(stderr, "shift keysym %04x keycode %d\n", 
keysym, keycode);
-                   }
-                   if (rest && strstr(rest, "localstate")) {
-                       add_to_key_range(&k->localstate_range, keycode);
-                       //fprintf(stderr, "localstate keysym %04x keycode 
%d\n", keysym, keycode);
-                   }
-
-                   /* if(keycode&0x80)
-                      keycode=(keycode<<8)^0x80e0; */
-                   if (keysym < MAX_NORMAL_KEYCODE) {
-                       //fprintf(stderr,"Setting keysym %s (%d) to 
%d\n",line,keysym,keycode);
-                       k->keysym2keycode[keysym] = keycode;
-                   } else {
-                       if (k->extra_count >= MAX_EXTRA_COUNT) {
-                           fprintf(stderr,
-                                   "Warning: Could not assign keysym %s (0x%x) 
because of memory constraints.\n",
-                                   line, keysym);
-                       } else {
-#if 0
-                           fprintf(stderr, "Setting %d: %d,%d\n",
-                                   k->extra_count, keysym, keycode);
-#endif
-                           k->keysym2keycode_extra[k->extra_count].
-                               keysym = keysym;
-                           k->keysym2keycode_extra[k->extra_count].
-                               keycode = keycode;
-                           k->extra_count++;
-                       }
-                   }
-               }
-           }
+       }
+       if (keycode <= 0 || keycode >= MAX_SCANCODE) {
+           fprintf(stderr, "%s: warning: keycode %#x for %s out of range\n",
+                   file_name, keycode, keyname);
+           continue;
+       }
+       if (numlock)
+           k->numlock.k[keycode].keysym = keysym;
+       else if (shift && altgr)
+           k->shift_altgr.k[keycode].keysym = keysym;
+       else if (altgr)
+           k->altgr.k[keycode].keysym = keysym;
+       else if (shift)
+           k->shift.k[keycode].keysym = keysym;
+       else {
+           k->plain.k[keycode].keysym = keysym;
+           if (addupper)
+               k->shift.k[keycode].keysym = keysym + 'A' - 'a';
        }
    }
    fclose(f);
    return k;
}

+static int cmp_map (const void *a, const void *b) {
+    return ((keysym2keycode_t *) b)->keysym - ((keysym2keycode_t *) a)->keysym;
+}
+
+static void sort_map (keysym_map_t *map) {
+    int i;
+    for (i = 0; i < MAX_SCANCODE; i++)
+       map->k[i].keycode = i;
+    /* sort undefined scancodes to the end */
+    qsort(map->k, MAX_SCANCODE, sizeof(keysym2keycode_t), cmp_map);
+    for (map->n = 0; map->n < MAX_SCANCODE; map->n++)
+       if (!map->k[map->n].keysym)
+           break;
+}
+
static void *init_keyboard_layout(const char *language)
{
-    return parse_keyboard_layout(language, 0);
+    kbd_layout_t *k = parse_keyboard_layout(language, NULL);
+    if (k) {
+       int i;
+       for (i = 0; i < MAX_SCANCODE; i++) {
+           if (!(k->shift.k[i].keysym
+                 || k->altgr.k[i].keysym
+                 || k->shift_altgr.k[i].keysym))
+               k->flags[i] |= KEY_LOCALSTATE;
+           if (k->numlock.k[i].keysym)
+               k->flags[i] |= KEY_KEYPAD;
+       }
+       sort_map(&k->plain);
+       sort_map(&k->shift);
+       sort_map(&k->altgr);
+       sort_map(&k->shift_altgr);
+       sort_map(&k->numlock);
+    }
+    return k;
}

-static int keysym2scancode(void *kbd_layout, int keysym)
+static int keysym2scancode_map (keysym_map_t *map, int keysym)
{
-    kbd_layout_t *k = kbd_layout;
-    if (keysym < MAX_NORMAL_KEYCODE) {
-       if (k->keysym2keycode[keysym] == 0)
-           fprintf(stderr, "Warning: no scancode found for keysym %d\n",
-                   keysym);
-       return k->keysym2keycode[keysym];
-    } else {
-       int i;
-#ifdef XK_ISO_Left_Tab
-       if (keysym == XK_ISO_Left_Tab)
-           keysym = XK_Tab;
-#endif
-       for (i = 0; i < k->extra_count; i++)
-           if (k->keysym2keycode_extra[i].keysym == keysym)
-               return k->keysym2keycode_extra[i].keycode;
+    int l = 0, r = map->n - 1, m;
+    while (l <= r) {
+       m = (l + r) / 2;
+       if (map->k[m].keysym == keysym)
+           return map->k[m].keycode;
+       else if (map->k[m].keysym < keysym)
+           r = m - 1;
+       else
+           l = m + 1;
    }
    return 0;
}

-static inline int keycode_is_keypad(void *kbd_layout, int keycode)
+static int keysym2scancode(void *kbd_layout, int keysym)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    int scancode;

-    for (kr = k->keypad_range; kr; kr = kr->next)
-        if (keycode >= kr->start && keycode <= kr->end)
-            return 1;
+    if ((scancode = keysym2scancode_map(&k->plain, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->numlock, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->shift, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->altgr, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->shift_altgr, keysym)))
+       return scancode;
    return 0;
}

-static inline int keysym_is_numlock(void *kbd_layout, int keysym)
+static int keysym2scancode1(void *kbd_layout, int keysym,
+                           int *shift, int *altgr)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    int s;
+
+    /* normal case: keysym can be found the expected modifier's map */
+    if (*shift && *altgr && (s = keysym2scancode_map(&k->shift_altgr, keysym)))
+       return s;
+    if (*altgr && (s = keysym2scancode_map(&k->altgr, keysym)))
+       return s;
+    if (*shift && (s = keysym2scancode_map(&k->shift, keysym)))
+       return s;
+    if ((s = keysym2scancode_map(&k->plain, keysym)))
+       return s;
+    if ((s = keysym2scancode_map(&k->numlock, keysym)))
+       return s;

-    for (kr = k->numlock_range; kr; kr = kr->next)
-        if (keysym >= kr->start && keysym <= kr->end)
-            return 1;
+    /* fallback for when there is some keyboard/state mismatch */
+    if ((s = keysym2scancode_map(&k->plain, keysym))) {
+       *shift = 0;
+       *altgr = 0;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->shift, keysym))) {
+       *shift = 1;
+       *altgr = 0;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->altgr, keysym))) {
+       *shift = 0;
+       *altgr = 1;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->shift_altgr, keysym))) {
+       *shift = 1;
+       *altgr = 1;
+       return s;
+    }
    return 0;
-}
+}
-static inline int keysym_is_shift(void *kbd_layout, int keysym)
+static int keycode_is_keypad(void *kbd_layout, int keycode)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
-
-    for (kr = k->shift_range; kr; kr = kr->next)
-        if (keysym >= kr->start && keysym <= kr->end)
-            return 1;
+    if (keycode >= 0 && keycode < MAX_SCANCODE)
+       return !!(k->flags[keycode] & KEY_KEYPAD);
    return 0;
}

-static inline int keycode_is_shiftable(void *kbd_layout, int keycode)
+static int keysym_is_numlock(void *kbd_layout, int keysym)
+{
+    kbd_layout_t *k = kbd_layout;
+    return (keysym2scancode_map(&k->numlock, keysym) != 0);
+}
+
+static int keysym_is_shift(void *kbd_layout, int keysym)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    return (keysym2scancode_map(&k->shift, keysym) != 0);
+}

-    for (kr = k->localstate_range; kr; kr = kr->next)
-       if (keycode >= kr->start && keycode <= kr->end)
-           return 0;
-    return 1;
+static int keycode_is_shiftable(void *kbd_layout, int keycode)
+{
+    kbd_layout_t *k = kbd_layout;
+    if (keycode >= 0 || keycode < MAX_SCANCODE)
+       return !(k->flags[keycode] & KEY_LOCALSTATE);
+    return 0;
}
diff --git a/vnc.c b/vnc.c
index 2cf3a31..a24eb39 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1258,14 +1258,22 @@ static void pointer_event(VncState *vs, int 
button_mask, int x, int y)
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
}

+static void put_keycode(int keycode, int down)
+{
+    if (keycode & 0x80)
+       kbd_put_keycode(0xe0);
+    if (down)
+       kbd_put_keycode(keycode & 0x7f);
+    else
+       kbd_put_keycode(keycode | 0x80);
+}
+
static void reset_keys(VncState *vs)
{
    int i;
    for(i = 0; i < 256; i++) {
        if (vs->modifiers_state[i]) {
-            if (i & 0x80)
-                kbd_put_keycode(0xe0);
-            kbd_put_keycode(i | 0x80);
+           put_keycode(i, 0);
            vs->modifiers_state[i] = 0;
        }
    }
@@ -1273,69 +1281,34 @@ static void reset_keys(VncState *vs)

static void press_key(VncState *vs, int keysym)
{
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
+    put_keycode(keysym2scancode(vs->kbd_layout, keysym), 1);
+    put_keycode(keysym2scancode(vs->kbd_layout, keysym), 0);
}

-static void press_key_shift_down(VncState *vs, int down, int keycode)
+static void twiddle_modifiers(VncState *vs, int down, int shift, int altgr)
{
-    if (down)
-        kbd_put_keycode(0x2a & 0x7f);
-
-    if (keycode & 0x80)
-        kbd_put_keycode(0xe0);
-    if (down)
-        kbd_put_keycode(keycode & 0x7f);
-    else
-        kbd_put_keycode(keycode | 0x80);
-
-    if (!down)
-        kbd_put_keycode(0x2a | 0x80);
-}
-
-static void press_key_shift_up(VncState *vs, int down, int keycode)
-{
-    if (down) {
-        if (vs->modifiers_state[0x2a])
-            kbd_put_keycode(0x2a | 0x80);
- if (vs->modifiers_state[0x36]) - kbd_put_keycode(0x36 | 0x80);
-    }
-
-    if (keycode & 0x80)
-        kbd_put_keycode(0xe0);
-    if (down)
-        kbd_put_keycode(keycode & 0x7f);
-    else
-        kbd_put_keycode(keycode | 0x80);
-
-    if (!down) {
-        if (vs->modifiers_state[0x2a])
-            kbd_put_keycode(0x2a & 0x7f);
- if (vs->modifiers_state[0x36]) - kbd_put_keycode(0x36 & 0x7f);
-    }
+    if (shift && !(vs->modifiers_state[0x2a] || vs->modifiers_state[0x36]))
+       put_keycode(0x2a, down);
+    if (!shift && vs->modifiers_state[0x2a])
+       put_keycode(0x2a, !down);
+    if (!shift && vs->modifiers_state[0x36])
+       put_keycode(0x36, !down);
+    if (altgr && !vs->modifiers_state[0xb8])
+       put_keycode(0xb8, down);
+    if (!altgr && vs->modifiers_state[0xb8])
+       put_keycode(0xb8, !down);
}

static void do_key_event(VncState *vs, int down, uint32_t sym)
{
    int keycode;
-    int shift_keys = 0;
+    int altgr = 0;
    int shift = 0;
    int keypad = 0;

-    if (is_graphic_console()) {
-        if (sym >= 'A' && sym <= 'Z') {
-            sym = sym - 'A' + 'a';
-            shift = 1;
-        }
-        else {
-            shift = keysym_is_shift(vs->kbd_layout, sym & 0xFFFF);
-        }
-    }
-    shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
-
-    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+    shift = (vs->modifiers_state[0x2a] || vs->modifiers_state[0x36]);
+    altgr = vs->modifiers_state[0xb8];
+    keycode = keysym2scancode1(vs->kbd_layout, sym & 0xFFFF, &shift, &altgr);
    if (keycode == 0) {
        fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
        return;
@@ -1348,17 +1321,9 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
    case 0x1d:                          /* Left CTRL */
    case 0x9d:                          /* Right CTRL */
    case 0x38:                          /* Left ALT */
-    case 0xb8:                          /* Right ALT */
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        if (down) {
-            vs->modifiers_state[keycode] = 1;
-            kbd_put_keycode(keycode & 0x7f);
-        }
-        else {
-            vs->modifiers_state[keycode] = 0;
-            kbd_put_keycode(keycode | 0x80);
-        }
+    case 0xb8:                          /* Right ALT aka AltGr */
+       vs->modifiers_state[keycode] = down;
+       put_keycode(keycode, down);
        return;
case 0x02 ... 0x0a: /* '1' to '9' keys */ if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
@@ -1369,13 +1334,15 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
        }
        break;
    case 0x3a:                  /* CapsLock */
+       if (is_graphic_console())
+           return;
    case 0x45:                  /* NumLock */
        if (down) {
-            kbd_put_keycode(keycode & 0x7f);
+            put_keycode(keycode, 1);
        }
        else {  
            vs->modifiers_state[keycode] ^= 1;
-            kbd_put_keycode(keycode | 0x80);
+            put_keycode(keycode, 0);
        }
        return;
    }
@@ -1384,7 +1351,10 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
    if (keypad) {
        /* If the numlock state needs to change then simulate an additional
           keypress before sending this one.  This will happen if the user
-           toggles numlock away from the VNC window.
+           toggles numlock away from the VNC window.  This isn't perfect as
+          pressing the shift key will typically and temporarily have the
+          effect of inverting the numlock setting: the shift key will be
+          effectively cancelled out.
        */
        if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) {
            if (!vs->modifiers_state[0x45]) {
@@ -1403,22 +1373,14 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
        /*  If the shift state needs to change then simulate an additional
            keypress before sending this one. Ignore for non shiftable keys.
        */
-        if (shift && !shift_keys) {
-            press_key_shift_down(vs, down, keycode);
-            return;
-        }
-        else if (!shift && shift_keys && !keypad &&
-                 keycode_is_shiftable(vs->kbd_layout, keycode)) {
-            press_key_shift_up(vs, down, keycode);
-            return;
-        }
-
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        if (down)
-            kbd_put_keycode(keycode & 0x7f);
-        else
-            kbd_put_keycode(keycode | 0x80);
+       if (keycode_is_shiftable(vs->kbd_layout, keycode) && !keypad) {
+           if (down)
+               twiddle_modifiers(vs, down, shift, altgr);
+           put_keycode(keycode, down);
+           if (!down)
+               twiddle_modifiers(vs, down, shift, altgr);
+       } else
+           put_keycode(keycode, down);
    } else {
        /* QEMU console emulation */
        if (down) {
@@ -2514,7 +2476,7 @@ void vnc_display_init(DisplayState *ds)
    vs->kbd_layout = init_keyboard_layout(keyboard_layout);
    if (!vs->kbd_layout)
        exit(1);
-    vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
+    vs->modifiers_state[0x45] = 0; /* NumLock off - on boot */

    vs->ds->data = NULL;
    vs->ds->dpy_update = vnc_dpy_update;
diff --git a/vnc_keysym.h b/vnc_keysym.h
index aa0fd9b..226789a 100644
--- a/vnc_keysym.h
+++ b/vnc_keysym.h
@@ -262,6 +262,783 @@ static name2keysym_t name2keysym[]={
{ "tcedilla",             0x01fe},
{ "abovedot",             0x01ff},

+    /* latin3 extensions */
+    { "Hstroke",                       0x02a1 },
+    { "Hcircumflex",                   0x02a6 },
+    { "Iabovedot",                     0x02a9 },
+    { "Gbreve",                        0x02ab },
+    { "Jcircumflex",                   0x02ac },
+    { "hstroke",                       0x02b1 },
+    { "hcircumflex",                   0x02b6 },
+    { "idotless",                      0x02b9 },
+    { "gbreve",                        0x02bb },
+    { "jcircumflex",                   0x02bc },
+    { "Cabovedot",                     0x02c5 },
+    { "Ccircumflex",                   0x02c6 },
+    { "Gabovedot",                     0x02d5 },
+    { "Gcircumflex",                   0x02d8 },
+    { "Ubreve",                        0x02dd },
+    { "Scircumflex",                   0x02de },
+    { "cabovedot",                     0x02e5 },
+    { "ccircumflex",                   0x02e6 },
+    { "gabovedot",                     0x02f5 },
+    { "gcircumflex",                   0x02f8 },
+    { "ubreve",                        0x02fd },
+    { "scircumflex",                   0x02fe },
+
+    /* latin4 extensions */
+    { "kra",                           0x03a2 },
+    { "kappa",                         0x03a2 },
+    { "Rcedilla",                      0x03a3 },
+    { "Itilde",                        0x03a5 },
+    { "Lcedilla",                      0x03a6 },
+    { "Emacron",                       0x03aa },
+    { "Gcedilla",                      0x03ab },
+    { "Tslash",                        0x03ac },
+    { "rcedilla",                      0x03b3 },
+    { "itilde",                        0x03b5 },
+    { "lcedilla",                      0x03b6 },
+    { "emacron",                       0x03ba },
+    { "gcedilla",                      0x03bb },
+    { "tslash",                        0x03bc },
+    { "ENG",                           0x03bd },
+    { "eng",                           0x03bf },
+    { "Amacron",                       0x03c0 },
+    { "Iogonek",                       0x03c7 },
+    { "Eabovedot",                     0x03cc },
+    { "Imacron",                       0x03cf },
+    { "Ncedilla",                      0x03d1 },
+    { "Omacron",                       0x03d2 },
+    { "Kcedilla",                      0x03d3 },
+    { "Uogonek",                       0x03d9 },
+    { "Utilde",                        0x03dd },
+    { "Umacron",                       0x03de },
+    { "amacron",                       0x03e0 },
+    { "iogonek",                       0x03e7 },
+    { "eabovedot",                     0x03ec },
+    { "imacron",                       0x03ef },
+    { "ncedilla",                      0x03f1 },
+    { "omacron",                       0x03f2 },
+    { "kcedilla",                      0x03f3 },
+    { "uogonek",                       0x03f9 },
+    { "utilde",                        0x03fd },
+    { "umacron",                       0x03fe },
+
+    /* latin8 extensions */
+    { "Babovedot",                  0x1001e02 },
+    { "babovedot",                  0x1001e03 },
+    { "Dabovedot",                  0x1001e0a },
+    { "Wgrave",                     0x1001e80 },
+    { "Wacute",                     0x1001e82 },
+    { "dabovedot",                  0x1001e0b },
+    { "Ygrave",                     0x1001ef2 },
+    { "Fabovedot",                  0x1001e1e },
+    { "fabovedot",                  0x1001e1f },
+    { "Mabovedot",                  0x1001e40 },
+    { "mabovedot",                  0x1001e41 },
+    { "Pabovedot",                  0x1001e56 },
+    { "wgrave",                     0x1001e81 },
+    { "pabovedot",                  0x1001e57 },
+    { "wacute",                     0x1001e83 },
+    { "Sabovedot",                  0x1001e60 },
+    { "ygrave",                     0x1001ef3 },
+    { "Wdiaeresis",                 0x1001e84 },
+    { "wdiaeresis",                 0x1001e85 },
+    { "sabovedot",                  0x1001e61 },
+    { "Wcircumflex",                0x1000174 },
+    { "Tabovedot",                  0x1001e6a },
+    { "Ycircumflex",                0x1000176 },
+    { "wcircumflex",                0x1000175 },
+    { "tabovedot",                  0x1001e6b },
+    { "ycircumflex",                0x1000177 },
+
+    /* latin9 extensions */
+    { "OE",                            0x13bc },
+    { "oe",                            0x13bd },
+    { "Ydiaeresis",                    0x13be },
+
+    /* katakana */
+    { "overline",                      0x047e },
+    { "kana_fullstop",                 0x04a1 },
+    { "kana_openingbracket",           0x04a2 },
+    { "kana_closingbracket",           0x04a3 },
+    { "kana_comma",                    0x04a4 },
+    { "kana_conjunctive",              0x04a5 },
+    { "kana_middledot",                0x04a5 },
+    { "kana_WO",                       0x04a6 },
+    { "kana_a",                        0x04a7 },
+    { "kana_i",                        0x04a8 },
+    { "kana_u",                        0x04a9 },
+    { "kana_e",                        0x04aa },
+    { "kana_o",                        0x04ab },
+    { "kana_ya",                       0x04ac },
+    { "kana_yu",                       0x04ad },
+    { "kana_yo",                       0x04ae },
+    { "kana_tsu",                      0x04af },
+    { "kana_tu",                       0x04af },
+    { "prolongedsound",                0x04b0 },
+    { "kana_A",                        0x04b1 },
+    { "kana_I",                        0x04b2 },
+    { "kana_U",                        0x04b3 },
+    { "kana_E",                        0x04b4 },
+    { "kana_O",                        0x04b5 },
+    { "kana_KA",                       0x04b6 },
+    { "kana_KI",                       0x04b7 },
+    { "kana_KU",                       0x04b8 },
+    { "kana_KE",                       0x04b9 },
+    { "kana_KO",                       0x04ba },
+    { "kana_SA",                       0x04bb },
+    { "kana_SHI",                      0x04bc },
+    { "kana_SU",                       0x04bd },
+    { "kana_SE",                       0x04be },
+    { "kana_SO",                       0x04bf },
+    { "kana_TA",                       0x04c0 },
+    { "kana_CHI",                      0x04c1 },
+    { "kana_TI",                       0x04c1 },
+    { "kana_TSU",                      0x04c2 },
+    { "kana_TU",                       0x04c2 },
+    { "kana_TE",                       0x04c3 },
+    { "kana_TO",                       0x04c4 },
+    { "kana_NA",                       0x04c5 },
+    { "kana_NI",                       0x04c6 },
+    { "kana_NU",                       0x04c7 },
+    { "kana_NE",                       0x04c8 },
+    { "kana_NO",                       0x04c9 },
+    { "kana_HA",                       0x04ca },
+    { "kana_HI",                       0x04cb },
+    { "kana_FU",                       0x04cc },
+    { "kana_HU",                       0x04cc },
+    { "kana_HE",                       0x04cd },
+    { "kana_HO",                       0x04ce },
+    { "kana_MA",                       0x04cf },
+    { "kana_MI",                       0x04d0 },
+    { "kana_MU",                       0x04d1 },
+    { "kana_ME",                       0x04d2 },
+    { "kana_MO",                       0x04d3 },
+    { "kana_YA",                       0x04d4 },
+    { "kana_YU",                       0x04d5 },
+    { "kana_YO",                       0x04d6 },
+    { "kana_RA",                       0x04d7 },
+    { "kana_RI",                       0x04d8 },
+    { "kana_RU",                       0x04d9 },
+    { "kana_RE",                       0x04da },
+    { "kana_RO",                       0x04db },
+    { "kana_WA",                       0x04dc },
+    { "kana_N",                        0x04dd },
+    { "voicedsound",                   0x04de },
+    { "semivoicedsound",               0x04df },
+    { "kana_switch",                   0xff7e },
+ + /* arabic */
+    { "Farsi_0",                    0x10006f0 },
+    { "Farsi_1",                    0x10006f1 },
+    { "Farsi_2",                    0x10006f2 },
+    { "Farsi_3",                    0x10006f3 },
+    { "Farsi_4",                    0x10006f4 },
+    { "Farsi_5",                    0x10006f5 },
+    { "Farsi_6",                    0x10006f6 },
+    { "Farsi_7",                    0x10006f7 },
+    { "Farsi_8",                    0x10006f8 },
+    { "Farsi_9",                    0x10006f9 },
+    { "Arabic_percent",             0x100066a },
+    { "Arabic_superscript_alef",    0x1000670 },
+    { "Arabic_tteh",                0x1000679 },
+    { "Arabic_peh",                 0x100067e },
+    { "Arabic_tcheh",               0x1000686 },
+    { "Arabic_ddal",                0x1000688 },
+    { "Arabic_rreh",                0x1000691 },
+    { "Arabic_comma",                  0x05ac },
+    { "Arabic_fullstop",            0x10006d4 },
+    { "Arabic_0",                   0x1000660 },
+    { "Arabic_1",                   0x1000661 },
+    { "Arabic_2",                   0x1000662 },
+    { "Arabic_3",                   0x1000663 },
+    { "Arabic_4",                   0x1000664 },
+    { "Arabic_5",                   0x1000665 },
+    { "Arabic_6",                   0x1000666 },
+    { "Arabic_7",                   0x1000667 },
+    { "Arabic_8",                   0x1000668 },
+    { "Arabic_9",                   0x1000669 },
+    { "Arabic_semicolon",              0x05bb },
+    { "Arabic_question_mark",          0x05bf },
+    { "Arabic_hamza",                  0x05c1 },
+    { "Arabic_maddaonalef",            0x05c2 },
+    { "Arabic_hamzaonalef",            0x05c3 },
+    { "Arabic_hamzaonwaw",             0x05c4 },
+    { "Arabic_hamzaunderalef",         0x05c5 },
+    { "Arabic_hamzaonyeh",             0x05c6 },
+    { "Arabic_alef",                   0x05c7 },
+    { "Arabic_beh",                    0x05c8 },
+    { "Arabic_tehmarbuta",             0x05c9 },
+    { "Arabic_teh",                    0x05ca },
+    { "Arabic_theh",                   0x05cb },
+    { "Arabic_jeem",                   0x05cc },
+    { "Arabic_hah",                    0x05cd },
+    { "Arabic_khah",                   0x05ce },
+    { "Arabic_dal",                    0x05cf },
+    { "Arabic_thal",                   0x05d0 },
+    { "Arabic_ra",                     0x05d1 },
+    { "Arabic_zain",                   0x05d2 },
+    { "Arabic_seen",                   0x05d3 },
+    { "Arabic_sheen",                  0x05d4 },
+    { "Arabic_sad",                    0x05d5 },
+    { "Arabic_dad",                    0x05d6 },
+    { "Arabic_tah",                    0x05d7 },
+    { "Arabic_zah",                    0x05d8 },
+    { "Arabic_ain",                    0x05d9 },
+    { "Arabic_ghain",                  0x05da },
+    { "Arabic_tatweel",                0x05e0 },
+    { "Arabic_feh",                    0x05e1 },
+    { "Arabic_qaf",                    0x05e2 },
+    { "Arabic_kaf",                    0x05e3 },
+    { "Arabic_lam",                    0x05e4 },
+    { "Arabic_meem",                   0x05e5 },
+    { "Arabic_noon",                   0x05e6 },
+    { "Arabic_ha",                     0x05e7 },
+    { "Arabic_heh",                    0x05e7 },
+    { "Arabic_waw",                    0x05e8 },
+    { "Arabic_alefmaksura",            0x05e9 },
+    { "Arabic_yeh",                    0x05ea },
+    { "Arabic_fathatan",               0x05eb },
+    { "Arabic_dammatan",               0x05ec },
+    { "Arabic_kasratan",               0x05ed },
+    { "Arabic_fatha",                  0x05ee },
+    { "Arabic_damma",                  0x05ef },
+    { "Arabic_kasra",                  0x05f0 },
+    { "Arabic_shadda",                 0x05f1 },
+    { "Arabic_sukun",                  0x05f2 },
+    { "Arabic_madda_above",         0x1000653 },
+    { "Arabic_hamza_above",         0x1000654 },
+    { "Arabic_hamza_below",         0x1000655 },
+    { "Arabic_jeh",                 0x1000698 },
+    { "Arabic_veh",                 0x10006a4 },
+    { "Arabic_keheh",               0x10006a9 },
+    { "Arabic_gaf",                 0x10006af },
+    { "Arabic_noon_ghunna",         0x10006ba },
+    { "Arabic_heh_doachashmee",     0x10006be },
+    { "Farsi_yeh",                  0x10006cc },
+    { "Arabic_farsi_yeh",           0x10006cc },
+    { "Arabic_yeh_baree",           0x10006d2 },
+    { "Arabic_heh_goal",            0x10006c1 },
+    { "Arabic_switch",                 0xff7e },
+
+    /* japanese keyboard */
+    { "Kanji",                         0xff21 },
+    { "BackApostrophe",                0xff21 }, /* ??? */
+    { "Muhenkan",                      0xff22 },
+    { "Henkan_Mode",                   0xff23 },
+    { "Henkan",                        0xff23 },
+    { "Henkan_Mode_Real",              0xff23 }, /* deprecated */
+    { "Romaji",                        0xff24 },
+    { "Hiragana",                      0xff25 },
+    { "Katakana_Real",                 0xff25 }, /* deprecated */
+    { "Katakana",                      0xff26 },
+    { "Hiragana_Katakana",             0xff27 },
+    { "Zenkaku",                       0xff28 },
+    { "Hankaku",                       0xff29 },
+    { "Zenkaku_Hankaku",               0xff2a },
+    { "Touroku",                       0xff2b },
+    { "Massyo",                        0xff2c },
+    { "Kana_Lock",                     0xff2d },
+    { "Kana_Shift",                    0xff2e },
+    { "Eisu_Shift",                    0xff2f },
+    { "Eisu_toggle",                   0xff30 },
+    { "Kanji_Bangou",                  0xff37 },
+    { "Zen_Koho",                      0xff3d },
+    { "Mae_Koho",                      0xff3e },
+    { "Henkan_Mode_Ultra",             0xff3e }, /* deprecated */
+    { "backslash_ja",                  0xffa5 }, /* ??? */
+
+    /* dead keys */
+    { "dead_grave",                    0xfe50 },
+    { "dead_acute",                    0xfe51 },
+    { "dead_circumflex",               0xfe52 },
+    { "dead_tilde",                    0xfe53 },
+    { "dead_macron",                   0xfe54 },
+    { "dead_breve",                    0xfe55 },
+    { "dead_abovedot",                 0xfe56 },
+    { "dead_diaeresis",                0xfe57 },
+    { "dead_abovering",                0xfe58 },
+    { "dead_doubleacute",              0xfe59 },
+    { "dead_caron",                    0xfe5a },
+    { "dead_cedilla",                  0xfe5b },
+    { "dead_ogonek",                   0xfe5c },
+    { "dead_iota",                     0xfe5d },
+    { "dead_voiced_sound",             0xfe5e },
+    { "dead_semivoiced_sound",         0xfe5f },
+    { "dead_belowdot",                 0xfe60 },
+    { "dead_hook",                     0xfe61 },
+    { "dead_horn",                     0xfe62 },
+    { "dead_stroke",                   0xfe63 },
+    { "dead_abovecomma",               0xfe64 },
+    { "dead_psili",                    0xfe64 },
+    { "dead_abovereversedcomma",       0xfe65 },
+    { "dead_dasia",                    0xfe66 },
+    { "dead_belowring",                0xfe67 },
+    { "dead_belowmacron",              0xfe68 },
+    { "dead_belowcircumflex",          0xfe69 },
+    { "dead_belowtilde",               0xfe6a },
+    { "dead_belowbreve",               0xfe6b },
+    { "dead_belowdiaeresis",           0xfe6c },
+
+    /* cyrillic */
+    { "Cyrillic_GHE_bar",           0x1000492 },
+    { "Cyrillic_ghe_bar",           0x1000493 },
+    { "Cyrillic_ZHE_descender",     0x1000496 },
+    { "Cyrillic_zhe_descender",     0x1000497 },
+    { "Cyrillic_KA_descender",      0x100049a },
+    { "Cyrillic_ka_descender",      0x100049b },
+    { "Cyrillic_KA_vertstroke",     0x100049c },
+    { "Cyrillic_ka_vertstroke",     0x100049d },
+    { "Cyrillic_EN_descender",      0x10004a2 },
+    { "Cyrillic_en_descender",      0x10004a3 },
+    { "Cyrillic_U_straight",        0x10004ae },
+    { "Cyrillic_u_straight",        0x10004af },
+    { "Cyrillic_U_straight_bar",    0x10004b0 },
+    { "Cyrillic_u_straight_bar",    0x10004b1 },
+    { "Cyrillic_HA_descender",      0x10004b2 },
+    { "Cyrillic_ha_descender",      0x10004b3 },
+    { "Cyrillic_CHE_descender",     0x10004b6 },
+    { "Cyrillic_che_descender",     0x10004b7 },
+    { "Cyrillic_CHE_vertstroke",    0x10004b8 },
+    { "Cyrillic_che_vertstroke",    0x10004b9 },
+    { "Cyrillic_SHHA",              0x10004ba },
+    { "Cyrillic_shha",              0x10004bb },
+    { "Cyrillic_SCHWA",             0x10004d8 },
+    { "Cyrillic_schwa",             0x10004d9 },
+    { "Cyrillic_I_macron",          0x10004e2 },
+    { "Cyrillic_i_macron",          0x10004e3 },
+    { "Cyrillic_O_bar",             0x10004e8 },
+    { "Cyrillic_o_bar",             0x10004e9 },
+    { "Cyrillic_U_macron",          0x10004ee },
+    { "Cyrillic_u_macron",          0x10004ef },
+    { "Serbian_dje",                   0x06a1 },
+    { "Macedonia_gje",                 0x06a2 },
+    { "Cyrillic_io",                   0x06a3 },
+    { "Ukrainian_ie",                  0x06a4 },
+    { "Ukranian_je",                   0x06a4 },
+    { "Macedonia_dse",                 0x06a5 },
+    { "Ukrainian_i",                   0x06a6 },
+    { "Ukranian_i",                    0x06a6 },
+    { "Ukrainian_yi",                  0x06a7 },
+    { "Ukranian_yi",                   0x06a7 },
+    { "Cyrillic_je",                   0x06a8 },
+    { "Serbian_je",                    0x06a8 },
+    { "Cyrillic_lje",                  0x06a9 },
+    { "Serbian_lje",                   0x06a9 },
+    { "Cyrillic_nje",                  0x06aa },
+    { "Serbian_nje",                   0x06aa },
+    { "Serbian_tshe",                  0x06ab },
+    { "Macedonia_kje",                 0x06ac },
+    { "Ukrainian_ghe_with_upturn",     0x06ad },
+    { "Byelorussian_shortu",           0x06ae },
+    { "Cyrillic_dzhe",                 0x06af },
+    { "Serbian_dze",                   0x06af },
+    { "numerosign",                    0x06b0 },
+    { "Serbian_DJE",                   0x06b1 },
+    { "Macedonia_GJE",                 0x06b2 },
+    { "Cyrillic_IO",                   0x06b3 },
+    { "Ukrainian_IE",                  0x06b4 },
+    { "Ukranian_JE",                   0x06b4 },
+    { "Macedonia_DSE",                 0x06b5 },
+    { "Ukrainian_I",                   0x06b6 },
+    { "Ukranian_I",                    0x06b6 },
+    { "Ukrainian_YI",                  0x06b7 },
+    { "Ukranian_YI",                   0x06b7 },
+    { "Cyrillic_JE",                   0x06b8 },
+    { "Serbian_JE",                    0x06b8 },
+    { "Cyrillic_LJE",                  0x06b9 },
+    { "Serbian_LJE",                   0x06b9 },
+    { "Cyrillic_NJE",                  0x06ba },
+    { "Serbian_NJE",                   0x06ba },
+    { "Serbian_TSHE",                  0x06bb },
+    { "Macedonia_KJE",                 0x06bc },
+    { "Ukrainian_GHE_WITH_UPTURN",     0x06bd },
+    { "Byelorussian_SHORTU",           0x06be },
+    { "Cyrillic_DZHE",                 0x06bf },
+    { "Serbian_DZE",                   0x06bf },
+    { "Cyrillic_yu",                   0x06c0 },
+    { "Cyrillic_a",                    0x06c1 },
+    { "Cyrillic_be",                   0x06c2 },
+    { "Cyrillic_tse",                  0x06c3 },
+    { "Cyrillic_de",                   0x06c4 },
+    { "Cyrillic_ie",                   0x06c5 },
+    { "Cyrillic_ef",                   0x06c6 },
+    { "Cyrillic_ghe",                  0x06c7 },
+    { "Cyrillic_ha",                   0x06c8 },
+    { "Cyrillic_i",                    0x06c9 },
+    { "Cyrillic_shorti",               0x06ca },
+    { "Cyrillic_ka",                   0x06cb },
+    { "Cyrillic_el",                   0x06cc },
+    { "Cyrillic_em",                   0x06cd },
+    { "Cyrillic_en",                   0x06ce },
+    { "Cyrillic_o",                    0x06cf },
+    { "Cyrillic_pe",                   0x06d0 },
+    { "Cyrillic_ya",                   0x06d1 },
+    { "Cyrillic_er",                   0x06d2 },
+    { "Cyrillic_es",                   0x06d3 },
+    { "Cyrillic_te",                   0x06d4 },
+    { "Cyrillic_u",                    0x06d5 },
+    { "Cyrillic_zhe",                  0x06d6 },
+    { "Cyrillic_ve",                   0x06d7 },
+    { "Cyrillic_softsign",             0x06d8 },
+    { "Cyrillic_yeru",                 0x06d9 },
+    { "Cyrillic_ze",                   0x06da },
+    { "Cyrillic_sha",                  0x06db },
+    { "Cyrillic_e",                    0x06dc },
+    { "Cyrillic_shcha",                0x06dd },
+    { "Cyrillic_che",                  0x06de },
+    { "Cyrillic_hardsign",             0x06df },
+    { "Cyrillic_YU",                   0x06e0 },
+    { "Cyrillic_A",                    0x06e1 },
+    { "Cyrillic_BE",                   0x06e2 },
+    { "Cyrillic_TSE",                  0x06e3 },
+    { "Cyrillic_DE",                   0x06e4 },
+    { "Cyrillic_IE",                   0x06e5 },
+    { "Cyrillic_EF",                   0x06e6 },
+    { "Cyrillic_GHE",                  0x06e7 },
+    { "Cyrillic_HA",                   0x06e8 },
+    { "Cyrillic_I",                    0x06e9 },
+    { "Cyrillic_SHORTI",               0x06ea },
+    { "Cyrillic_KA",                   0x06eb },
+    { "Cyrillic_EL",                   0x06ec },
+    { "Cyrillic_EM",                   0x06ed },
+    { "Cyrillic_EN",                   0x06ee },
+    { "Cyrillic_O",                    0x06ef },
+    { "Cyrillic_PE",                   0x06f0 },
+    { "Cyrillic_YA",                   0x06f1 },
+    { "Cyrillic_ER",                   0x06f2 },
+    { "Cyrillic_ES",                   0x06f3 },
+    { "Cyrillic_TE",                   0x06f4 },
+    { "Cyrillic_U",                    0x06f5 },
+    { "Cyrillic_ZHE",                  0x06f6 },
+    { "Cyrillic_VE",                   0x06f7 },
+    { "Cyrillic_SOFTSIGN",             0x06f8 },
+    { "Cyrillic_YERU",                 0x06f9 },
+    { "Cyrillic_ZE",                   0x06fa },
+    { "Cyrillic_SHA",                  0x06fb },
+    { "Cyrillic_E",                    0x06fc },
+    { "Cyrillic_SHCHA",                0x06fd },
+    { "Cyrillic_CHE",                  0x06fe },
+    { "Cyrillic_HARDSIGN",             0x06ff },
+
+    /* Greek */
+    { "Greek_ALPHAaccent",             0x07a1 },
+    { "Greek_EPSILONaccent",           0x07a2 },
+    { "Greek_ETAaccent",               0x07a3 },
+    { "Greek_IOTAaccent",              0x07a4 },
+    { "Greek_IOTAdieresis",            0x07a5 },
+    { "Greek_IOTAdiaeresis",           0x07a5 },
+    { "Greek_OMICRONaccent",           0x07a7 },
+    { "Greek_UPSILONaccent",           0x07a8 },
+    { "Greek_UPSILONdieresis",         0x07a9 },
+    { "Greek_OMEGAaccent",             0x07ab },
+    { "Greek_accentdieresis",          0x07ae },
+    { "Greek_horizbar",                0x07af },
+    { "Greek_alphaaccent",             0x07b1 },
+    { "Greek_epsilonaccent",           0x07b2 },
+    { "Greek_etaaccent",               0x07b3 },
+    { "Greek_iotaaccent",              0x07b4 },
+    { "Greek_iotadieresis",            0x07b5 },
+    { "Greek_iotaaccentdieresis",      0x07b6 },
+    { "Greek_omicronaccent",           0x07b7 },
+    { "Greek_upsilonaccent",           0x07b8 },
+    { "Greek_upsilondieresis",         0x07b9 },
+    { "Greek_upsilonaccentdieresis",   0x07ba },
+    { "Greek_omegaaccent",             0x07bb },
+    { "Greek_ALPHA",                   0x07c1 },
+    { "Greek_BETA",                    0x07c2 },
+    { "Greek_GAMMA",                   0x07c3 },
+    { "Greek_DELTA",                   0x07c4 },
+    { "Greek_EPSILON",                 0x07c5 },
+    { "Greek_ZETA",                    0x07c6 },
+    { "Greek_ETA",                     0x07c7 },
+    { "Greek_THETA",                   0x07c8 },
+    { "Greek_IOTA",                    0x07c9 },
+    { "Greek_KAPPA",                   0x07ca },
+    { "Greek_LAMDA",                   0x07cb },
+    { "Greek_LAMBDA",                  0x07cb },
+    { "Greek_MU",                      0x07cc },
+    { "Greek_NU",                      0x07cd },
+    { "Greek_XI",                      0x07ce },
+    { "Greek_OMICRON",                 0x07cf },
+    { "Greek_PI",                      0x07d0 },
+    { "Greek_RHO",                     0x07d1 },
+    { "Greek_SIGMA",                   0x07d2 },
+    { "Greek_TAU",                     0x07d4 },
+    { "Greek_UPSILON",                 0x07d5 },
+    { "Greek_PHI",                     0x07d6 },
+    { "Greek_CHI",                     0x07d7 },
+    { "Greek_PSI",                     0x07d8 },
+    { "Greek_OMEGA",                   0x07d9 },
+    { "Greek_alpha",                   0x07e1 },
+    { "Greek_beta",                    0x07e2 },
+    { "Greek_gamma",                   0x07e3 },
+    { "Greek_delta",                   0x07e4 },
+    { "Greek_epsilon",                 0x07e5 },
+    { "Greek_zeta",                    0x07e6 },
+    { "Greek_eta",                     0x07e7 },
+    { "Greek_theta",                   0x07e8 },
+    { "Greek_iota",                    0x07e9 },
+    { "Greek_kappa",                   0x07ea },
+    { "Greek_lamda",                   0x07eb },
+    { "Greek_lambda",                  0x07eb },
+    { "Greek_mu",                      0x07ec },
+    { "Greek_nu",                      0x07ed },
+    { "Greek_xi",                      0x07ee },
+    { "Greek_omicron",                 0x07ef },
+    { "Greek_pi",                      0x07f0 },
+    { "Greek_rho",                     0x07f1 },
+    { "Greek_sigma",                   0x07f2 },
+    { "Greek_finalsmallsigma",         0x07f3 },
+    { "Greek_tau",                     0x07f4 },
+    { "Greek_upsilon",                 0x07f5 },
+    { "Greek_phi",                     0x07f6 },
+    { "Greek_chi",                     0x07f7 },
+    { "Greek_psi",                     0x07f8 },
+    { "Greek_omega",                   0x07f9 },
+    { "Greek_switch",                  0xff7e },
+
+    /* technical */
+    { "leftradical",                   0x08a1 },
+    { "topleftradical",                0x08a2 },
+    { "horizconnector",                0x08a3 },
+    { "topintegral",                   0x08a4 },
+    { "botintegral",                   0x08a5 },
+    { "vertconnector",                 0x08a6 },
+    { "topleftsqbracket",              0x08a7 },
+    { "botleftsqbracket",              0x08a8 },
+    { "toprightsqbracket",             0x08a9 },
+    { "botrightsqbracket",             0x08aa },
+    { "topleftparens",                 0x08ab },
+    { "botleftparens",                 0x08ac },
+    { "toprightparens",                0x08ad },
+    { "botrightparens",                0x08ae },
+    { "leftmiddlecurlybrace",          0x08af },
+    { "rightmiddlecurlybrace",         0x08b0 },
+    { "topleftsummation",              0x08b1 },
+    { "botleftsummation",              0x08b2 },
+    { "topvertsummationconnector",     0x08b3 },
+    { "botvertsummationconnector",     0x08b4 },
+    { "toprightsummation",             0x08b5 },
+    { "botrightsummation",             0x08b6 },
+    { "rightmiddlesummation",          0x08b7 },
+    { "lessthanequal",                 0x08bc },
+    { "notequal",                      0x08bd },
+    { "greaterthanequal",              0x08be },
+    { "integral",                      0x08bf },
+    { "therefore",                     0x08c0 },
+    { "variation",                     0x08c1 },
+    { "infinity",                      0x08c2 },
+    { "nabla",                         0x08c5 },
+    { "approximate",                   0x08c8 },
+    { "similarequal",                  0x08c9 },
+    { "ifonlyif",                      0x08cd },
+    { "implies",                       0x08ce },
+    { "identical",                     0x08cf },
+    { "radical",                       0x08d6 },
+    { "includedin",                    0x08da },
+    { "includes",                      0x08db },
+    { "intersection",                  0x08dc },
+    { "union",                         0x08dd },
+    { "logicaland",                    0x08de },
+    { "logicalor",                     0x08df },
+    { "partialderivative",             0x08ef },
+    { "function",                      0x08f6 },
+    { "leftarrow",                     0x08fb },
+    { "uparrow",                       0x08fc },
+    { "rightarrow",                    0x08fd },
+    { "downarrow",                     0x08fe },
+
+    /* publishing */
+    { "emspace",                       0x0aa1 },
+    { "enspace",                       0x0aa2 },
+    { "em3space",                      0x0aa3 },
+    { "em4space",                      0x0aa4 },
+    { "digitspace",                    0x0aa5 },
+    { "punctspace",                    0x0aa6 },
+    { "thinspace",                     0x0aa7 },
+    { "hairspace",                     0x0aa8 },
+    { "emdash",                        0x0aa9 },
+    { "endash",                        0x0aaa },
+    { "signifblank",                   0x0aac },
+    { "ellipsis",                      0x0aae },
+    { "doubbaselinedot",               0x0aaf },
+    { "onethird",                      0x0ab0 },
+    { "twothirds",                     0x0ab1 },
+    { "onefifth",                      0x0ab2 },
+    { "twofifths",                     0x0ab3 },
+    { "threefifths",                   0x0ab4 },
+    { "fourfifths",                    0x0ab5 },
+    { "onesixth",                      0x0ab6 },
+    { "fivesixths",                    0x0ab7 },
+    { "careof",                        0x0ab8 },
+    { "figdash",                       0x0abb },
+    { "leftanglebracket",              0x0abc },
+    { "decimalpoint",                  0x0abd },
+    { "rightanglebracket",             0x0abe },
+    { "marker",                        0x0abf },
+    { "oneeighth",                     0x0ac3 },
+    { "threeeighths",                  0x0ac4 },
+    { "fiveeighths",                   0x0ac5 },
+    { "seveneighths",                  0x0ac6 },
+    { "trademark",                     0x0ac9 },
+    { "signaturemark",                 0x0aca },
+    { "trademarkincircle",             0x0acb },
+    { "leftopentriangle",              0x0acc },
+    { "rightopentriangle",             0x0acd },
+    { "emopencircle",                  0x0ace },
+    { "emopenrectangle",               0x0acf },
+    { "leftsinglequotemark",           0x0ad0 },
+    { "rightsinglequotemark",          0x0ad1 },
+    { "leftdoublequotemark",           0x0ad2 },
+    { "rightdoublequotemark",          0x0ad3 },
+    { "prescription",                  0x0ad4 },
+    { "minutes",                       0x0ad6 },
+    { "seconds",                       0x0ad7 },
+    { "latincross",                    0x0ad9 },
+    { "hexagram",                      0x0ada },
+    { "filledrectbullet",              0x0adb },
+    { "filledlefttribullet",           0x0adc },
+    { "filledrighttribullet",          0x0add },
+    { "emfilledcircle",                0x0ade },
+    { "emfilledrect",                  0x0adf },
+    { "enopencircbullet",              0x0ae0 },
+    { "enopensquarebullet",            0x0ae1 },
+    { "openrectbullet",                0x0ae2 },
+    { "opentribulletup",               0x0ae3 },
+    { "opentribulletdown",             0x0ae4 },
+    { "openstar",                      0x0ae5 },
+    { "enfilledcircbullet",            0x0ae6 },
+    { "enfilledsqbullet",              0x0ae7 },
+    { "filledtribulletup",             0x0ae8 },
+    { "filledtribulletdown",           0x0ae9 },
+    { "leftpointer",                   0x0aea },
+    { "rightpointer",                  0x0aeb },
+    { "club",                          0x0aec },
+    { "diamond",                       0x0aed },
+    { "heart",                         0x0aee },
+    { "maltesecross",                  0x0af0 },
+    { "dagger",                        0x0af1 },
+    { "doubledagger",                  0x0af2 },
+    { "checkmark",                     0x0af3 },
+    { "ballotcross",                   0x0af4 },
+    { "musicalsharp",                  0x0af5 },
+    { "musicalflat",                   0x0af6 },
+    { "malesymbol",                    0x0af7 },
+    { "femalesymbol",                  0x0af8 },
+    { "telephone",                     0x0af9 },
+    { "telephonerecorder",             0x0afa },
+    { "phonographcopyright",           0x0afb },
+    { "caret",                         0x0afc },
+    { "singlelowquotemark",            0x0afd },
+    { "doublelowquotemark",            0x0afe },
+    { "cursor",                        0x0aff },
+
+    /* Caucasus */
+    { "Xabovedot",                  0x1001e8a },
+    { "Ibreve",                     0x100012c },
+    { "Zstroke",                    0x10001b5 },
+    { "Gcaron",                     0x10001e6 },
+    { "Ocaron",                     0x10001d1 },
+    { "Obarred",                    0x100019f },
+    { "xabovedot",                  0x1001e8b },
+    { "ibreve",                     0x100012d },
+    { "zstroke",                    0x10001b6 },
+    { "gcaron",                     0x10001e7 },
+    { "ocaron",                     0x10001d2 },
+    { "obarred",                    0x1000275 },
+    { "SCHWA",                      0x100018f },
+    { "schwa",                      0x1000259 },
+    { "Lbelowdot",                  0x1001e36 },
+    { "lbelowdot",                  0x1001e37 },
+
+    /* Thai */
+    { "Thai_kokai",                    0x0da1 },
+    { "Thai_khokhai",                  0x0da2 },
+    { "Thai_khokhuat",                 0x0da3 },
+    { "Thai_khokhwai",                 0x0da4 },
+    { "Thai_khokhon",                  0x0da5 },
+    { "Thai_khorakhang",               0x0da6 },
+    { "Thai_ngongu",                   0x0da7 },
+    { "Thai_chochan",                  0x0da8 },
+    { "Thai_choching",                 0x0da9 },
+    { "Thai_chochang",                 0x0daa },
+    { "Thai_soso",                     0x0dab },
+    { "Thai_chochoe",                  0x0dac },
+    { "Thai_yoying",                   0x0dad },
+    { "Thai_dochada",                  0x0dae },
+    { "Thai_topatak",                  0x0daf },
+    { "Thai_thothan",                  0x0db0 },
+    { "Thai_thonangmontho",            0x0db1 },
+    { "Thai_thophuthao",               0x0db2 },
+    { "Thai_nonen",                    0x0db3 },
+    { "Thai_dodek",                    0x0db4 },
+    { "Thai_totao",                    0x0db5 },
+    { "Thai_thothung",                 0x0db6 },
+    { "Thai_thothahan",                0x0db7 },
+    { "Thai_thothong",                 0x0db8 },
+    { "Thai_nonu",                     0x0db9 },
+    { "Thai_bobaimai",                 0x0dba },
+    { "Thai_popla",                    0x0dbb },
+    { "Thai_phophung",                 0x0dbc },
+    { "Thai_fofa",                     0x0dbd },
+    { "Thai_phophan",                  0x0dbe },
+    { "Thai_fofan",                    0x0dbf },
+    { "Thai_phosamphao",               0x0dc0 },
+    { "Thai_moma",                     0x0dc1 },
+    { "Thai_yoyak",                    0x0dc2 },
+    { "Thai_rorua",                    0x0dc3 },
+    { "Thai_ru",                       0x0dc4 },
+    { "Thai_loling",                   0x0dc5 },
+    { "Thai_lu",                       0x0dc6 },
+    { "Thai_wowaen",                   0x0dc7 },
+    { "Thai_sosala",                   0x0dc8 },
+    { "Thai_sorusi",                   0x0dc9 },
+    { "Thai_sosua",                    0x0dca },
+    { "Thai_hohip",                    0x0dcb },
+    { "Thai_lochula",                  0x0dcc },
+    { "Thai_oang",                     0x0dcd },
+    { "Thai_honokhuk",                 0x0dce },
+    { "Thai_paiyannoi",                0x0dcf },
+    { "Thai_saraa",                    0x0dd0 },
+    { "Thai_maihanakat",               0x0dd1 },
+    { "Thai_saraaa",                   0x0dd2 },
+    { "Thai_saraam",                   0x0dd3 },
+    { "Thai_sarai",                    0x0dd4 },
+    { "Thai_saraii",                   0x0dd5 },
+    { "Thai_saraue",                   0x0dd6 },
+    { "Thai_sarauee",                  0x0dd7 },
+    { "Thai_sarau",                    0x0dd8 },
+    { "Thai_sarauu",                   0x0dd9 },
+    { "Thai_phinthu",                  0x0dda },
+    { "Thai_maihanakat_maitho",        0x0dde },
+    { "Thai_baht",                     0x0ddf },
+    { "Thai_sarae",                    0x0de0 },
+    { "Thai_saraae",                   0x0de1 },
+    { "Thai_sarao",                    0x0de2 },
+    { "Thai_saraaimaimuan",            0x0de3 },
+    { "Thai_saraaimaimalai",           0x0de4 },
+    { "Thai_lakkhangyao",              0x0de5 },
+    { "Thai_maiyamok",                 0x0de6 },
+    { "Thai_maitaikhu",                0x0de7 },
+    { "Thai_maiek",                    0x0de8 },
+    { "Thai_maitho",                   0x0de9 },
+    { "Thai_maitri",                   0x0dea },
+    { "Thai_maichattawa",              0x0deb },
+    { "Thai_thanthakhat",              0x0dec },
+    { "Thai_nikhahit",                 0x0ded },
+    { "Thai_leksun",                   0x0df0 },
+    { "Thai_leknung",                  0x0df1 },
+    { "Thai_leksong",                  0x0df2 },
+    { "Thai_leksam",                   0x0df3 },
+    { "Thai_leksi",                    0x0df4 },
+    { "Thai_lekha",                    0x0df5 },
+    { "Thai_lekhok",                   0x0df6 },
+    { "Thai_lekchet",                  0x0df7 },
+    { "Thai_lekpaet",                  0x0df8 },
+    { "Thai_lekkao",                   0x0df9 },
+
    /* modifiers */
{"Control_L", 0xffe3}, /* XK_Control_L */
{"Control_R", 0xffe4}, /* XK_Control_R */
@@ -339,48 +1116,20 @@ static name2keysym_t name2keysym[]={
{"KP_Multiply", 0xffaa}, /* XK_KP_Multiply */
{"KP_Subtract", 0xffad}, /* XK_KP_Subtract */
{"help", 0xff6a},        /* XK_Help */
+    { "Break",                         0xff6b },
{"Menu", 0xff67},        /* XK_Menu */
{"Print", 0xff61},       /* XK_Print */
+    { "Execute",                       0xff62 },
{"Mode_switch", 0xff7e}, /* XK_Mode_switch */
{"Num_Lock", 0xff7f},    /* XK_Num_Lock */
{"Pause", 0xff13},       /* XK_Pause */
{"Escape", 0xff1b},      /* XK_Escape */
{"ISO_Left_Tab", 0xfe20},/* XK_ISO_Left_Tab */
+    { "Multi_key",                     0xff20 },
+    { "ISO_Next_Group",                0xfe08 },
+    { "ISO_First_Group",               0xfe0c },
+    { "ISO_Last_Group",                0xfe0e },

-    /* localized keys */
-{"BackApostrophe", 0xff21},
-{"Muhenkan", 0xff22},
-{"Katakana", 0xff27},
-{"Hankaku", 0xff29},
-{"Zenkaku_Hankaku", 0xff2a},
-{"Henkan_Mode_Real", 0xff23},
-{"Henkan_Mode_Ultra", 0xff3e},
-{"backslash_ja", 0xffa5},
-{"Katakana_Real", 0xff25},
-{"Eisu_toggle", 0xff30},
-
-    /* dead keys */
-{"dead_grave", 0xfe50},
-{"dead_acute", 0xfe51},
-{"dead_circumflex", 0xfe52},
-{"dead_tilde", 0xfe53},
-{"dead_macron", 0xfe54},
-{"dead_brev", 0xfe55},
-{"dead_abovedot", 0xfe56},
-{"dead_diaeresis", 0xfe57},
-{"dead_abovering", 0xfe58},
-{"dead_doubleacute", 0xfe59},
-{"dead_caron", 0xfe5a},
-{"dead_cedilla", 0xfe5b},
-{"dead_ogonek", 0xfe5c},
-{"dead_iota", 0xfe5d},
-{"dead_voiced_sound", 0xfe5e},
-{"dead_semivoiced_sound", 0xfe5f},
-{"dead_belowdot", 0xfe60},
-{"dead_hook", 0xfe61},
-{"dead_horn", 0xfe62},
-
-
-{0,0},
+    {0,0},
};




_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.