Support for non-ISO-8859-1 X keysyms. So in particular, pterm in a
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 27 Apr 2003 11:10:48 +0000 (11:10 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 27 Apr 2003 11:10:48 +0000 (11:10 +0000)
Euro-supporting font with a Euro-enabled X key map will now actually
generate a Euro character rather than shrugging and doing nothing.

git-svn-id: svn://svn.tartarus.org/sgt/putty@3151 cda61777-01e9-0310-a592-d414129be87e

Recipe
unix/pterm.c
unix/unix.h
unix/xkeysym.c [new file with mode: 0644]

diff --git a/Recipe b/Recipe
index 3c9b65a..5d6f740 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -97,8 +97,9 @@
 GUITERM  = window windlg winctrls terminal sizetip wcwidth unicode ldiscucs
          + logging printing winutils dialog config wincfg tree234
 
-# Config box on Unix.
-UXCFG    = config uxcfg dialog gtkdlg gtkcols gtkpanel
+# Same thing on Unix.
+UXTERM   = pterm config uxcfg dialog gtkdlg gtkcols gtkpanel tree234
+         + terminal wcwidth uxucs ldiscucs logging uxprint xkeysym
 
 # Non-SSH back ends (putty, puttytel, plink).
 NONSSH   = telnet raw rlogin ldisc
@@ -152,15 +153,12 @@ puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
          + sshrand noise sshsha winstore misc winctrls sshrsa sshdss winmisc
          + sshpubk sshaes sshsh512 import winutils puttygen.res tree234 LIBS
 
-pterm    : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
-         + logging uxprint settings pty uxsel be_none uxstore signal CHARSET
-        + cmdline ptermm UXCFG version
-putty    : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
-         + logging uxprint settings pty uxsel be_all uxstore signal CHARSET
-        + uxputty NONSSH UXSSH UXMISC logging ux_x11 UXCFG
-puttytel : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
-         + logging uxprint settings pty uxsel be_nossh uxstore signal CHARSET
-        + uxputty NONSSH UXMISC logging UXCFG
+pterm    : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_none uxstore
+         + signal CHARSET cmdline ptermm version
+putty    : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_all uxstore
+         + signal CHARSET uxputty NONSSH UXSSH UXMISC ux_x11
+puttytel : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_nossh uxstore
+         + signal CHARSET uxputty NONSSH UXMISC
 
 plink    : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
 
index e34208c..cf52ec3 100644 (file)
@@ -440,11 +440,12 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
     struct gui_data *inst = (struct gui_data *)data;
     char output[32];
-    int start, end, special;
+    wchar_t ucsoutput[2];
+    int ucsval, start, end, special, use_ucsoutput;
 
     /* By default, nothing is generated. */
     end = start = 0;
-    special = FALSE;
+    special = use_ucsoutput = FALSE;
 
     /*
      * If Alt is being released after typing an Alt+numberpad
@@ -566,12 +567,21 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        }
 
        special = FALSE;
+       use_ucsoutput = FALSE;
 
        /* ALT+things gives leading Escape. */
        output[0] = '\033';
        strncpy(output+1, event->string, 31);
-       output[31] = '\0';
-       end = strlen(output);
+       if (!*event->string &&
+           (ucsval = keysym_to_unicode(event->keyval)) >= 0) {
+           ucsoutput[0] = '\033';
+           ucsoutput[1] = ucsval;
+           use_ucsoutput = TRUE;
+           end = 2;
+       } else {
+           output[31] = '\0';
+           end = strlen(output);
+       }
        if (event->state & GDK_MOD1_MASK) {
            start = 0;
            if (end == 1) end = 0;
@@ -582,6 +592,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        if (!event->string[0] && event->keyval == '`' &&
            (event->state & GDK_CONTROL_MASK)) {
            output[1] = '\x1C';
+           use_ucsoutput = FALSE;
            end = 2;
        }
 
@@ -589,6 +600,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        if (event->keyval == GDK_Break &&
            (event->state & GDK_CONTROL_MASK)) {
            output[1] = '\003';
+           use_ucsoutput = FALSE;
            end = 2;
            special = TRUE;
        }
@@ -597,6 +609,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
         * special to ldisc. */
        if (event->keyval == GDK_Return) {
            output[1] = '\015';
+           use_ucsoutput = FALSE;
            end = 2;
            special = TRUE;
        }
@@ -608,6 +621,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
            (event->state & (GDK_SHIFT_MASK |
                             GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) {
            output[1] = '\0';
+           use_ucsoutput = FALSE;
            end = 2;
        }
 
@@ -616,6 +630,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
            (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ==
            (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
            output[1] = '\240';
+           use_ucsoutput = FALSE;
            end = 2;
        }
 
@@ -623,6 +638,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        if (event->keyval == GDK_BackSpace &&
            !(event->state & GDK_SHIFT_MASK)) {
            output[1] = inst->cfg.bksp_is_delete ? '\x7F' : '\x08';
+           use_ucsoutput = FALSE;
            end = 2;
            special = TRUE;
        }
@@ -630,6 +646,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        if (event->keyval == GDK_BackSpace &&
            (event->state & GDK_SHIFT_MASK)) {
            output[1] = inst->cfg.bksp_is_delete ? '\x08' : '\x7F';
+           use_ucsoutput = FALSE;
            end = 2;
            special = TRUE;
        }
@@ -638,6 +655,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
        if (event->keyval == GDK_ISO_Left_Tab ||
            (event->keyval == GDK_Tab && (event->state & GDK_SHIFT_MASK))) {
            end = 1 + sprintf(output+1, "\033[Z");
+           use_ucsoutput = FALSE;
        }
 
        /*
@@ -662,6 +680,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                    output[1] = keys[1];
                else
                    output[1] = keys[0];
+               use_ucsoutput = FALSE;
                goto done;
            }
        }
@@ -714,6 +733,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                        end = 1 + sprintf(output+1, "\033?%c", xkey);
                } else
                    end = 1 + sprintf(output+1, "\033O%c", xkey);
+               use_ucsoutput = FALSE;
                goto done;
            }
        }
@@ -817,6 +837,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 
            if (inst->term->vt52_mode && code > 0 && code <= 6) {
                end = 1 + sprintf(output+1, "\x1B%c", " HLMEIG"[code]);
+               use_ucsoutput = FALSE;
                goto done;
            }
 
@@ -841,6 +862,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                if (event->state & GDK_SHIFT_MASK) index += 12;
                if (event->state & GDK_CONTROL_MASK) index += 24;
                end = 1 + sprintf(output+1, "\x1B[%c", codes[index]);
+               use_ucsoutput = FALSE;
                goto done;
            }
            if (inst->cfg.funky_type == 5 &&     /* SCO small keypad */
@@ -852,6 +874,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                } else {
                    end = 1 + sprintf(output+1, "\x1B[%c", codes[code-1]);
                }
+               use_ucsoutput = FALSE;
                goto done;
            }
            if ((inst->term->vt52_mode || inst->cfg.funky_type == 4) &&
@@ -867,10 +890,12 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                else
                    end = 1 + sprintf(output+1,
                                      "\x1BO%c", code + 'P' - 11 - offt);
+               use_ucsoutput = FALSE;
                goto done;
            }
            if (inst->cfg.funky_type == 1 && code >= 11 && code <= 15) {
                end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11);
+               use_ucsoutput = FALSE;
                goto done;
            }
            if (inst->cfg.funky_type == 2 && code >= 11 && code <= 14) {
@@ -878,14 +903,17 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                    end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11);
                else
                    end = 1 + sprintf(output+1, "\x1BO%c", code + 'P' - 11);
+               use_ucsoutput = FALSE;
                goto done;
            }
            if (inst->cfg.rxvt_homeend && (code == 1 || code == 4)) {
                end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw");
+               use_ucsoutput = FALSE;
                goto done;
            }
            if (code) {
                end = 1 + sprintf(output+1, "\x1B[%d~", code);
+               use_ucsoutput = FALSE;
                goto done;
            }
        }
@@ -920,6 +948,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                } else {                    
                    end = 1 + sprintf(output+1, "\033[%c", xkey);
                }
+               use_ucsoutput = FALSE;
                goto done;
            }
        }
@@ -945,19 +974,28 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
            output[end] = '\0';        /* NUL-terminate */
            ldisc_send(inst->ldisc, output+start, -2, 1);
        } else if (!inst->direct_to_font) {
-           /*
-            * The stuff we've just generated is assumed to be
-            * ISO-8859-1! This sounds insane, but `man
-            * XLookupString' agrees: strings of this type returned
-            * from the X server are hardcoded to 8859-1. Strictly
-            * speaking we should be doing this using some sort of
-            * GtkIMContext, which (if we're lucky) would give us
-            * our data directly in Unicode; but that's not
-            * supported in GTK 1.2 as far as I can tell, and it's
-            * poorly documented even in 2.0, so it'll have to
-            * wait.
-            */
-           lpage_send(inst->ldisc, CS_ISO8859_1, output+start, end-start, 1);
+           if (!use_ucsoutput) {
+               /*
+                * The stuff we've just generated is assumed to be
+                * ISO-8859-1! This sounds insane, but `man
+                * XLookupString' agrees: strings of this type
+                * returned from the X server are hardcoded to
+                * 8859-1. Strictly speaking we should be doing
+                * this using some sort of GtkIMContext, which (if
+                * we're lucky) would give us our data directly in
+                * Unicode; but that's not supported in GTK 1.2 as
+                * far as I can tell, and it's poorly documented
+                * even in 2.0, so it'll have to wait.
+                */
+               lpage_send(inst->ldisc, CS_ISO8859_1, output+start,
+                          end-start, 1);
+           } else {
+               /*
+                * We generated our own Unicode key data from the
+                * keysym, so use that instead.
+                */
+               luni_send(inst->ldisc, ucsoutput+start, end-start, 1);
+           }
        } else {
            /*
             * In direct-to-font mode, we just send the string
index 843655e..aeffead 100644 (file)
@@ -71,6 +71,9 @@ int reallyclose(void *frontend);
 char *make_default_wintitle(char *hostname);
 int process_nonoption_arg(char *arg, Config *cfg);
 
+/* pterm.c needs this special function in xkeysym.c */
+int keysym_to_unicode(int keysym);
+
 /* Things uxstore.c needs from pterm.c */
 char *x_get_default(const char *key);
 
diff --git a/unix/xkeysym.c b/unix/xkeysym.c
new file mode 100644 (file)
index 0000000..45f6a0c
--- /dev/null
@@ -0,0 +1,1011 @@
+/*
+ * xkeysym.c: mapping from X keysyms to Unicode values
+ * 
+ * The basic idea of this is shamelessly cribbed from xterm. The
+ * actual character data is generated from Markus Kuhn's proposed
+ * redraft of the X11 keysym mapping table, using the following
+ * piece of Perl/sh code:
+
+wget -q -O - http://www.cl.cam.ac.uk/~mgk25/ucs/X11.keysyms | \
+perl -ne '/^(\d+)\s+(\d+)\s+[\d\/]+\s+U\+([\dA-Fa-f]+)/ and' \
+      -e '  do { $a{$1 * 256+ $2} = hex $3; };' \
+      -e 'END { foreach $i (sort {$a <=> $b} keys %a) {' \
+      -e '  printf "    {0x%x, 0x%x},\n", $i, $a{$i} } }' \
+      -e 'BEGIN { $a{0x13a4} = 0x20ac }'
+
+ * (The BEGIN clause inserts a mapping for the Euro sign which for
+ * some reason isn't in the list but xterm supports. *shrug*.)
+ */
+
+#include "misc.h"
+
+struct keysym {
+    /*
+     * Currently nothing in here is above 0xFFFF, so I'll use
+     * `unsigned short' to save space.
+     */
+    unsigned short keysym;
+    unsigned short unicode;
+};
+
+static struct keysym keysyms[] = {
+    {0x20, 0x20},
+    {0x21, 0x21},
+    {0x22, 0x22},
+    {0x23, 0x23},
+    {0x24, 0x24},
+    {0x25, 0x25},
+    {0x26, 0x26},
+    {0x27, 0x27},
+    {0x28, 0x28},
+    {0x29, 0x29},
+    {0x2a, 0x2a},
+    {0x2b, 0x2b},
+    {0x2c, 0x2c},
+    {0x2d, 0x2d},
+    {0x2e, 0x2e},
+    {0x2f, 0x2f},
+    {0x30, 0x30},
+    {0x31, 0x31},
+    {0x32, 0x32},
+    {0x33, 0x33},
+    {0x34, 0x34},
+    {0x35, 0x35},
+    {0x36, 0x36},
+    {0x37, 0x37},
+    {0x38, 0x38},
+    {0x39, 0x39},
+    {0x3a, 0x3a},
+    {0x3b, 0x3b},
+    {0x3c, 0x3c},
+    {0x3d, 0x3d},
+    {0x3e, 0x3e},
+    {0x3f, 0x3f},
+    {0x40, 0x40},
+    {0x41, 0x41},
+    {0x42, 0x42},
+    {0x43, 0x43},
+    {0x44, 0x44},
+    {0x45, 0x45},
+    {0x46, 0x46},
+    {0x47, 0x47},
+    {0x48, 0x48},
+    {0x49, 0x49},
+    {0x4a, 0x4a},
+    {0x4b, 0x4b},
+    {0x4c, 0x4c},
+    {0x4d, 0x4d},
+    {0x4e, 0x4e},
+    {0x4f, 0x4f},
+    {0x50, 0x50},
+    {0x51, 0x51},
+    {0x52, 0x52},
+    {0x53, 0x53},
+    {0x54, 0x54},
+    {0x55, 0x55},
+    {0x56, 0x56},
+    {0x57, 0x57},
+    {0x58, 0x58},
+    {0x59, 0x59},
+    {0x5a, 0x5a},
+    {0x5b, 0x5b},
+    {0x5c, 0x5c},
+    {0x5d, 0x5d},
+    {0x5e, 0x5e},
+    {0x5f, 0x5f},
+    {0x60, 0x60},
+    {0x61, 0x61},
+    {0x62, 0x62},
+    {0x63, 0x63},
+    {0x64, 0x64},
+    {0x65, 0x65},
+    {0x66, 0x66},
+    {0x67, 0x67},
+    {0x68, 0x68},
+    {0x69, 0x69},
+    {0x6a, 0x6a},
+    {0x6b, 0x6b},
+    {0x6c, 0x6c},
+    {0x6d, 0x6d},
+    {0x6e, 0x6e},
+    {0x6f, 0x6f},
+    {0x70, 0x70},
+    {0x71, 0x71},
+    {0x72, 0x72},
+    {0x73, 0x73},
+    {0x74, 0x74},
+    {0x75, 0x75},
+    {0x76, 0x76},
+    {0x77, 0x77},
+    {0x78, 0x78},
+    {0x79, 0x79},
+    {0x7a, 0x7a},
+    {0x7b, 0x7b},
+    {0x7c, 0x7c},
+    {0x7d, 0x7d},
+    {0x7e, 0x7e},
+    {0xa0, 0xa0},
+    {0xa1, 0xa1},
+    {0xa2, 0xa2},
+    {0xa3, 0xa3},
+    {0xa4, 0xa4},
+    {0xa5, 0xa5},
+    {0xa6, 0xa6},
+    {0xa7, 0xa7},
+    {0xa8, 0xa8},
+    {0xa9, 0xa9},
+    {0xaa, 0xaa},
+    {0xab, 0xab},
+    {0xac, 0xac},
+    {0xad, 0xad},
+    {0xae, 0xae},
+    {0xaf, 0xaf},
+    {0xb0, 0xb0},
+    {0xb1, 0xb1},
+    {0xb2, 0xb2},
+    {0xb3, 0xb3},
+    {0xb4, 0xb4},
+    {0xb5, 0xb5},
+    {0xb6, 0xb6},
+    {0xb7, 0xb7},
+    {0xb8, 0xb8},
+    {0xb9, 0xb9},
+    {0xba, 0xba},
+    {0xbb, 0xbb},
+    {0xbc, 0xbc},
+    {0xbd, 0xbd},
+    {0xbe, 0xbe},
+    {0xbf, 0xbf},
+    {0xc0, 0xc0},
+    {0xc1, 0xc1},
+    {0xc2, 0xc2},
+    {0xc3, 0xc3},
+    {0xc4, 0xc4},
+    {0xc5, 0xc5},
+    {0xc6, 0xc6},
+    {0xc7, 0xc7},
+    {0xc8, 0xc8},
+    {0xc9, 0xc9},
+    {0xca, 0xca},
+    {0xcb, 0xcb},
+    {0xcc, 0xcc},
+    {0xcd, 0xcd},
+    {0xce, 0xce},
+    {0xcf, 0xcf},
+    {0xd0, 0xd0},
+    {0xd1, 0xd1},
+    {0xd2, 0xd2},
+    {0xd3, 0xd3},
+    {0xd4, 0xd4},
+    {0xd5, 0xd5},
+    {0xd6, 0xd6},
+    {0xd7, 0xd7},
+    {0xd8, 0xd8},
+    {0xd9, 0xd9},
+    {0xda, 0xda},
+    {0xdb, 0xdb},
+    {0xdc, 0xdc},
+    {0xdd, 0xdd},
+    {0xde, 0xde},
+    {0xdf, 0xdf},
+    {0xe0, 0xe0},
+    {0xe1, 0xe1},
+    {0xe2, 0xe2},
+    {0xe3, 0xe3},
+    {0xe4, 0xe4},
+    {0xe5, 0xe5},
+    {0xe6, 0xe6},
+    {0xe7, 0xe7},
+    {0xe8, 0xe8},
+    {0xe9, 0xe9},
+    {0xea, 0xea},
+    {0xeb, 0xeb},
+    {0xec, 0xec},
+    {0xed, 0xed},
+    {0xee, 0xee},
+    {0xef, 0xef},
+    {0xf0, 0xf0},
+    {0xf1, 0xf1},
+    {0xf2, 0xf2},
+    {0xf3, 0xf3},
+    {0xf4, 0xf4},
+    {0xf5, 0xf5},
+    {0xf6, 0xf6},
+    {0xf7, 0xf7},
+    {0xf8, 0xf8},
+    {0xf9, 0xf9},
+    {0xfa, 0xfa},
+    {0xfb, 0xfb},
+    {0xfc, 0xfc},
+    {0xfd, 0xfd},
+    {0xfe, 0xfe},
+    {0xff, 0xff},
+    {0x1a1, 0x104},
+    {0x1a2, 0x2d8},
+    {0x1a3, 0x141},
+    {0x1a5, 0x13d},
+    {0x1a6, 0x15a},
+    {0x1a9, 0x160},
+    {0x1aa, 0x15e},
+    {0x1ab, 0x164},
+    {0x1ac, 0x179},
+    {0x1ae, 0x17d},
+    {0x1af, 0x17b},
+    {0x1b1, 0x105},
+    {0x1b2, 0x2db},
+    {0x1b3, 0x142},
+    {0x1b5, 0x13e},
+    {0x1b6, 0x15b},
+    {0x1b7, 0x2c7},
+    {0x1b9, 0x161},
+    {0x1ba, 0x15f},
+    {0x1bb, 0x165},
+    {0x1bc, 0x17a},
+    {0x1bd, 0x2dd},
+    {0x1be, 0x17e},
+    {0x1bf, 0x17c},
+    {0x1c0, 0x154},
+    {0x1c3, 0x102},
+    {0x1c5, 0x139},
+    {0x1c6, 0x106},
+    {0x1c8, 0x10c},
+    {0x1ca, 0x118},
+    {0x1cc, 0x11a},
+    {0x1cf, 0x10e},
+    {0x1d0, 0x110},
+    {0x1d1, 0x143},
+    {0x1d2, 0x147},
+    {0x1d5, 0x150},
+    {0x1d8, 0x158},
+    {0x1d9, 0x16e},
+    {0x1db, 0x170},
+    {0x1de, 0x162},
+    {0x1e0, 0x155},
+    {0x1e3, 0x103},
+    {0x1e5, 0x13a},
+    {0x1e6, 0x107},
+    {0x1e8, 0x10d},
+    {0x1ea, 0x119},
+    {0x1ec, 0x11b},
+    {0x1ef, 0x10f},
+    {0x1f0, 0x111},
+    {0x1f1, 0x144},
+    {0x1f2, 0x148},
+    {0x1f5, 0x151},
+    {0x1f8, 0x159},
+    {0x1f9, 0x16f},
+    {0x1fb, 0x171},
+    {0x1fe, 0x163},
+    {0x1ff, 0x2d9},
+    {0x2a1, 0x126},
+    {0x2a6, 0x124},
+    {0x2a9, 0x130},
+    {0x2ab, 0x11e},
+    {0x2ac, 0x134},
+    {0x2b1, 0x127},
+    {0x2b6, 0x125},
+    {0x2b9, 0x131},
+    {0x2bb, 0x11f},
+    {0x2bc, 0x135},
+    {0x2c5, 0x10a},
+    {0x2c6, 0x108},
+    {0x2d5, 0x120},
+    {0x2d8, 0x11c},
+    {0x2dd, 0x16c},
+    {0x2de, 0x15c},
+    {0x2e5, 0x10b},
+    {0x2e6, 0x109},
+    {0x2f5, 0x121},
+    {0x2f8, 0x11d},
+    {0x2fd, 0x16d},
+    {0x2fe, 0x15d},
+    {0x3a2, 0x138},
+    {0x3a3, 0x156},
+    {0x3a5, 0x128},
+    {0x3a6, 0x13b},
+    {0x3aa, 0x112},
+    {0x3ab, 0x122},
+    {0x3ac, 0x166},
+    {0x3b3, 0x157},
+    {0x3b5, 0x129},
+    {0x3b6, 0x13c},
+    {0x3ba, 0x113},
+    {0x3bb, 0x123},
+    {0x3bc, 0x167},
+    {0x3bd, 0x14a},
+    {0x3bf, 0x14b},
+    {0x3c0, 0x100},
+    {0x3c7, 0x12e},
+    {0x3cc, 0x116},
+    {0x3cf, 0x12a},
+    {0x3d1, 0x145},
+    {0x3d2, 0x14c},
+    {0x3d3, 0x136},
+    {0x3d9, 0x172},
+    {0x3dd, 0x168},
+    {0x3de, 0x16a},
+    {0x3e0, 0x101},
+    {0x3e7, 0x12f},
+    {0x3ec, 0x117},
+    {0x3ef, 0x12b},
+    {0x3f1, 0x146},
+    {0x3f2, 0x14d},
+    {0x3f3, 0x137},
+    {0x3f9, 0x173},
+    {0x3fd, 0x169},
+    {0x3fe, 0x16b},
+    {0x47e, 0x203e},
+    {0x4a1, 0x3002},
+    {0x4a2, 0x300c},
+    {0x4a3, 0x300d},
+    {0x4a4, 0x3001},
+    {0x4a5, 0x30fb},
+    {0x4a6, 0x30f2},
+    {0x4a7, 0x30a1},
+    {0x4a8, 0x30a3},
+    {0x4a9, 0x30a5},
+    {0x4aa, 0x30a7},
+    {0x4ab, 0x30a9},
+    {0x4ac, 0x30e3},
+    {0x4ad, 0x30e5},
+    {0x4ae, 0x30e7},
+    {0x4af, 0x30c3},
+    {0x4b0, 0x30fc},
+    {0x4b1, 0x30a2},
+    {0x4b2, 0x30a4},
+    {0x4b3, 0x30a6},
+    {0x4b4, 0x30a8},
+    {0x4b5, 0x30aa},
+    {0x4b6, 0x30ab},
+    {0x4b7, 0x30ad},
+    {0x4b8, 0x30af},
+    {0x4b9, 0x30b1},
+    {0x4ba, 0x30b3},
+    {0x4bb, 0x30b5},
+    {0x4bc, 0x30b7},
+    {0x4bd, 0x30b9},
+    {0x4be, 0x30bb},
+    {0x4bf, 0x30bd},
+    {0x4c0, 0x30bf},
+    {0x4c1, 0x30c1},
+    {0x4c2, 0x30c4},
+    {0x4c3, 0x30c6},
+    {0x4c4, 0x30c8},
+    {0x4c5, 0x30ca},
+    {0x4c6, 0x30cb},
+    {0x4c7, 0x30cc},
+    {0x4c8, 0x30cd},
+    {0x4c9, 0x30ce},
+    {0x4ca, 0x30cf},
+    {0x4cb, 0x30d2},
+    {0x4cc, 0x30d5},
+    {0x4cd, 0x30d8},
+    {0x4ce, 0x30db},
+    {0x4cf, 0x30de},
+    {0x4d0, 0x30df},
+    {0x4d1, 0x30e0},
+    {0x4d2, 0x30e1},
+    {0x4d3, 0x30e2},
+    {0x4d4, 0x30e4},
+    {0x4d5, 0x30e6},
+    {0x4d6, 0x30e8},
+    {0x4d7, 0x30e9},
+    {0x4d8, 0x30ea},
+    {0x4d9, 0x30eb},
+    {0x4da, 0x30ec},
+    {0x4db, 0x30ed},
+    {0x4dc, 0x30ef},
+    {0x4dd, 0x30f3},
+    {0x4de, 0x309b},
+    {0x4df, 0x309c},
+    {0x5ac, 0x60c},
+    {0x5bb, 0x61b},
+    {0x5bf, 0x61f},
+    {0x5c1, 0x621},
+    {0x5c2, 0x622},
+    {0x5c3, 0x623},
+    {0x5c4, 0x624},
+    {0x5c5, 0x625},
+    {0x5c6, 0x626},
+    {0x5c7, 0x627},
+    {0x5c8, 0x628},
+    {0x5c9, 0x629},
+    {0x5ca, 0x62a},
+    {0x5cb, 0x62b},
+    {0x5cc, 0x62c},
+    {0x5cd, 0x62d},
+    {0x5ce, 0x62e},
+    {0x5cf, 0x62f},
+    {0x5d0, 0x630},
+    {0x5d1, 0x631},
+    {0x5d2, 0x632},
+    {0x5d3, 0x633},
+    {0x5d4, 0x634},
+    {0x5d5, 0x635},
+    {0x5d6, 0x636},
+    {0x5d7, 0x637},
+    {0x5d8, 0x638},
+    {0x5d9, 0x639},
+    {0x5da, 0x63a},
+    {0x5e0, 0x640},
+    {0x5e1, 0x641},
+    {0x5e2, 0x642},
+    {0x5e3, 0x643},
+    {0x5e4, 0x644},
+    {0x5e5, 0x645},
+    {0x5e6, 0x646},
+    {0x5e7, 0x647},
+    {0x5e8, 0x648},
+    {0x5e9, 0x649},
+    {0x5ea, 0x64a},
+    {0x5eb, 0x64b},
+    {0x5ec, 0x64c},
+    {0x5ed, 0x64d},
+    {0x5ee, 0x64e},
+    {0x5ef, 0x64f},
+    {0x5f0, 0x650},
+    {0x5f1, 0x651},
+    {0x5f2, 0x652},
+    {0x6a1, 0x452},
+    {0x6a2, 0x453},
+    {0x6a3, 0x451},
+    {0x6a4, 0x454},
+    {0x6a5, 0x455},
+    {0x6a6, 0x456},
+    {0x6a7, 0x457},
+    {0x6a8, 0x458},
+    {0x6a9, 0x459},
+    {0x6aa, 0x45a},
+    {0x6ab, 0x45b},
+    {0x6ac, 0x45c},
+    {0x6ae, 0x45e},
+    {0x6af, 0x45f},
+    {0x6b0, 0x2116},
+    {0x6b1, 0x402},
+    {0x6b2, 0x403},
+    {0x6b3, 0x401},
+    {0x6b4, 0x404},
+    {0x6b5, 0x405},
+    {0x6b6, 0x406},
+    {0x6b7, 0x407},
+    {0x6b8, 0x408},
+    {0x6b9, 0x409},
+    {0x6ba, 0x40a},
+    {0x6bb, 0x40b},
+    {0x6bc, 0x40c},
+    {0x6be, 0x40e},
+    {0x6bf, 0x40f},
+    {0x6c0, 0x44e},
+    {0x6c1, 0x430},
+    {0x6c2, 0x431},
+    {0x6c3, 0x446},
+    {0x6c4, 0x434},
+    {0x6c5, 0x435},
+    {0x6c6, 0x444},
+    {0x6c7, 0x433},
+    {0x6c8, 0x445},
+    {0x6c9, 0x438},
+    {0x6ca, 0x439},
+    {0x6cb, 0x43a},
+    {0x6cc, 0x43b},
+    {0x6cd, 0x43c},
+    {0x6ce, 0x43d},
+    {0x6cf, 0x43e},
+    {0x6d0, 0x43f},
+    {0x6d1, 0x44f},
+    {0x6d2, 0x440},
+    {0x6d3, 0x441},
+    {0x6d4, 0x442},
+    {0x6d5, 0x443},
+    {0x6d6, 0x436},
+    {0x6d7, 0x432},
+    {0x6d8, 0x44c},
+    {0x6d9, 0x44b},
+    {0x6da, 0x437},
+    {0x6db, 0x448},
+    {0x6dc, 0x44d},
+    {0x6dd, 0x449},
+    {0x6de, 0x447},
+    {0x6df, 0x44a},
+    {0x6e0, 0x42e},
+    {0x6e1, 0x410},
+    {0x6e2, 0x411},
+    {0x6e3, 0x426},
+    {0x6e4, 0x414},
+    {0x6e5, 0x415},
+    {0x6e6, 0x424},
+    {0x6e7, 0x413},
+    {0x6e8, 0x425},
+    {0x6e9, 0x418},
+    {0x6ea, 0x419},
+    {0x6eb, 0x41a},
+    {0x6ec, 0x41b},
+    {0x6ed, 0x41c},
+    {0x6ee, 0x41d},
+    {0x6ef, 0x41e},
+    {0x6f0, 0x41f},
+    {0x6f1, 0x42f},
+    {0x6f2, 0x420},
+    {0x6f3, 0x421},
+    {0x6f4, 0x422},
+    {0x6f5, 0x423},
+    {0x6f6, 0x416},
+    {0x6f7, 0x412},
+    {0x6f8, 0x42c},
+    {0x6f9, 0x42b},
+    {0x6fa, 0x417},
+    {0x6fb, 0x428},
+    {0x6fc, 0x42d},
+    {0x6fd, 0x429},
+    {0x6fe, 0x427},
+    {0x6ff, 0x42a},
+    {0x7a1, 0x386},
+    {0x7a2, 0x388},
+    {0x7a3, 0x389},
+    {0x7a4, 0x38a},
+    {0x7a5, 0x3aa},
+    {0x7a7, 0x38c},
+    {0x7a8, 0x38e},
+    {0x7a9, 0x3ab},
+    {0x7ab, 0x38f},
+    {0x7ae, 0x385},
+    {0x7af, 0x2015},
+    {0x7b1, 0x3ac},
+    {0x7b2, 0x3ad},
+    {0x7b3, 0x3ae},
+    {0x7b4, 0x3af},
+    {0x7b5, 0x3ca},
+    {0x7b6, 0x390},
+    {0x7b7, 0x3cc},
+    {0x7b8, 0x3cd},
+    {0x7b9, 0x3cb},
+    {0x7ba, 0x3b0},
+    {0x7bb, 0x3ce},
+    {0x7c1, 0x391},
+    {0x7c2, 0x392},
+    {0x7c3, 0x393},
+    {0x7c4, 0x394},
+    {0x7c5, 0x395},
+    {0x7c6, 0x396},
+    {0x7c7, 0x397},
+    {0x7c8, 0x398},
+    {0x7c9, 0x399},
+    {0x7ca, 0x39a},
+    {0x7cb, 0x39b},
+    {0x7cc, 0x39c},
+    {0x7cd, 0x39d},
+    {0x7ce, 0x39e},
+    {0x7cf, 0x39f},
+    {0x7d0, 0x3a0},
+    {0x7d1, 0x3a1},
+    {0x7d2, 0x3a3},
+    {0x7d4, 0x3a4},
+    {0x7d5, 0x3a5},
+    {0x7d6, 0x3a6},
+    {0x7d7, 0x3a7},
+    {0x7d8, 0x3a8},
+    {0x7d9, 0x3a9},
+    {0x7e1, 0x3b1},
+    {0x7e2, 0x3b2},
+    {0x7e3, 0x3b3},
+    {0x7e4, 0x3b4},
+    {0x7e5, 0x3b5},
+    {0x7e6, 0x3b6},
+    {0x7e7, 0x3b7},
+    {0x7e8, 0x3b8},
+    {0x7e9, 0x3b9},
+    {0x7ea, 0x3ba},
+    {0x7eb, 0x3bb},
+    {0x7ec, 0x3bc},
+    {0x7ed, 0x3bd},
+    {0x7ee, 0x3be},
+    {0x7ef, 0x3bf},
+    {0x7f0, 0x3c0},
+    {0x7f1, 0x3c1},
+    {0x7f2, 0x3c3},
+    {0x7f3, 0x3c2},
+    {0x7f4, 0x3c4},
+    {0x7f5, 0x3c5},
+    {0x7f6, 0x3c6},
+    {0x7f7, 0x3c7},
+    {0x7f8, 0x3c8},
+    {0x7f9, 0x3c9},
+    {0x8a1, 0x23b7},
+    {0x8a2, 0x250c},
+    {0x8a3, 0x2500},
+    {0x8a4, 0x2320},
+    {0x8a5, 0x2321},
+    {0x8a6, 0x2502},
+    {0x8a7, 0x23a1},
+    {0x8a8, 0x23a3},
+    {0x8a9, 0x23a4},
+    {0x8aa, 0x23a6},
+    {0x8ab, 0x239b},
+    {0x8ac, 0x239d},
+    {0x8ad, 0x239e},
+    {0x8ae, 0x23a0},
+    {0x8af, 0x23a8},
+    {0x8b0, 0x23ac},
+    {0x8bc, 0x2264},
+    {0x8bd, 0x2260},
+    {0x8be, 0x2265},
+    {0x8bf, 0x222b},
+    {0x8c0, 0x2234},
+    {0x8c1, 0x221d},
+    {0x8c2, 0x221e},
+    {0x8c5, 0x2207},
+    {0x8c8, 0x223c},
+    {0x8c9, 0x2243},
+    {0x8cd, 0x21d4},
+    {0x8ce, 0x21d2},
+    {0x8cf, 0x2261},
+    {0x8d6, 0x221a},
+    {0x8da, 0x2282},
+    {0x8db, 0x2283},
+    {0x8dc, 0x2229},
+    {0x8dd, 0x222a},
+    {0x8de, 0x2227},
+    {0x8df, 0x2228},
+    {0x8ef, 0x2202},
+    {0x8f6, 0x192},
+    {0x8fb, 0x2190},
+    {0x8fc, 0x2191},
+    {0x8fd, 0x2192},
+    {0x8fe, 0x2193},
+    {0x9e0, 0x25c6},
+    {0x9e1, 0x2592},
+    {0x9e2, 0x2409},
+    {0x9e3, 0x240c},
+    {0x9e4, 0x240d},
+    {0x9e5, 0x240a},
+    {0x9e8, 0x2424},
+    {0x9e9, 0x240b},
+    {0x9ea, 0x2518},
+    {0x9eb, 0x2510},
+    {0x9ec, 0x250c},
+    {0x9ed, 0x2514},
+    {0x9ee, 0x253c},
+    {0x9ef, 0x23ba},
+    {0x9f0, 0x23bb},
+    {0x9f1, 0x2500},
+    {0x9f2, 0x23bc},
+    {0x9f3, 0x23bd},
+    {0x9f4, 0x251c},
+    {0x9f5, 0x2524},
+    {0x9f6, 0x2534},
+    {0x9f7, 0x252c},
+    {0x9f8, 0x2502},
+    {0xaa1, 0x2003},
+    {0xaa2, 0x2002},
+    {0xaa3, 0x2004},
+    {0xaa4, 0x2005},
+    {0xaa5, 0x2007},
+    {0xaa6, 0x2008},
+    {0xaa7, 0x2009},
+    {0xaa8, 0x200a},
+    {0xaa9, 0x2014},
+    {0xaaa, 0x2013},
+    {0xaae, 0x2026},
+    {0xaaf, 0x2025},
+    {0xab0, 0x2153},
+    {0xab1, 0x2154},
+    {0xab2, 0x2155},
+    {0xab3, 0x2156},
+    {0xab4, 0x2157},
+    {0xab5, 0x2158},
+    {0xab6, 0x2159},
+    {0xab7, 0x215a},
+    {0xab8, 0x2105},
+    {0xabb, 0x2012},
+    {0xabc, 0x2329},
+    {0xabe, 0x232a},
+    {0xac3, 0x215b},
+    {0xac4, 0x215c},
+    {0xac5, 0x215d},
+    {0xac6, 0x215e},
+    {0xac9, 0x2122},
+    {0xaca, 0x2613},
+    {0xacc, 0x25c1},
+    {0xacd, 0x25b7},
+    {0xace, 0x25cb},
+    {0xacf, 0x25af},
+    {0xad0, 0x2018},
+    {0xad1, 0x2019},
+    {0xad2, 0x201c},
+    {0xad3, 0x201d},
+    {0xad4, 0x211e},
+    {0xad6, 0x2032},
+    {0xad7, 0x2033},
+    {0xad9, 0x271d},
+    {0xadb, 0x25ac},
+    {0xadc, 0x25c0},
+    {0xadd, 0x25b6},
+    {0xade, 0x25cf},
+    {0xadf, 0x25ae},
+    {0xae0, 0x25e6},
+    {0xae1, 0x25ab},
+    {0xae2, 0x25ad},
+    {0xae3, 0x25b3},
+    {0xae4, 0x25bd},
+    {0xae5, 0x2606},
+    {0xae6, 0x2022},
+    {0xae7, 0x25aa},
+    {0xae8, 0x25b2},
+    {0xae9, 0x25bc},
+    {0xaea, 0x261c},
+    {0xaeb, 0x261e},
+    {0xaec, 0x2663},
+    {0xaed, 0x2666},
+    {0xaee, 0x2665},
+    {0xaf0, 0x2720},
+    {0xaf1, 0x2020},
+    {0xaf2, 0x2021},
+    {0xaf3, 0x2713},
+    {0xaf4, 0x2717},
+    {0xaf5, 0x266f},
+    {0xaf6, 0x266d},
+    {0xaf7, 0x2642},
+    {0xaf8, 0x2640},
+    {0xaf9, 0x260e},
+    {0xafa, 0x2315},
+    {0xafb, 0x2117},
+    {0xafc, 0x2038},
+    {0xafd, 0x201a},
+    {0xafe, 0x201e},
+    {0xba3, 0x3c},
+    {0xba6, 0x3e},
+    {0xba8, 0x2228},
+    {0xba9, 0x2227},
+    {0xbc0, 0xaf},
+    {0xbc2, 0x22a5},
+    {0xbc3, 0x2229},
+    {0xbc4, 0x230a},
+    {0xbc6, 0x5f},
+    {0xbca, 0x2218},
+    {0xbcc, 0x2395},
+    {0xbce, 0x22a4},
+    {0xbcf, 0x25cb},
+    {0xbd3, 0x2308},
+    {0xbd6, 0x222a},
+    {0xbd8, 0x2283},
+    {0xbda, 0x2282},
+    {0xbdc, 0x22a2},
+    {0xbfc, 0x22a3},
+    {0xcdf, 0x2017},
+    {0xce0, 0x5d0},
+    {0xce1, 0x5d1},
+    {0xce2, 0x5d2},
+    {0xce3, 0x5d3},
+    {0xce4, 0x5d4},
+    {0xce5, 0x5d5},
+    {0xce6, 0x5d6},
+    {0xce7, 0x5d7},
+    {0xce8, 0x5d8},
+    {0xce9, 0x5d9},
+    {0xcea, 0x5da},
+    {0xceb, 0x5db},
+    {0xcec, 0x5dc},
+    {0xced, 0x5dd},
+    {0xcee, 0x5de},
+    {0xcef, 0x5df},
+    {0xcf0, 0x5e0},
+    {0xcf1, 0x5e1},
+    {0xcf2, 0x5e2},
+    {0xcf3, 0x5e3},
+    {0xcf4, 0x5e4},
+    {0xcf5, 0x5e5},
+    {0xcf6, 0x5e6},
+    {0xcf7, 0x5e7},
+    {0xcf8, 0x5e8},
+    {0xcf9, 0x5e9},
+    {0xcfa, 0x5ea},
+    {0xda1, 0xe01},
+    {0xda2, 0xe02},
+    {0xda3, 0xe03},
+    {0xda4, 0xe04},
+    {0xda5, 0xe05},
+    {0xda6, 0xe06},
+    {0xda7, 0xe07},
+    {0xda8, 0xe08},
+    {0xda9, 0xe09},
+    {0xdaa, 0xe0a},
+    {0xdab, 0xe0b},
+    {0xdac, 0xe0c},
+    {0xdad, 0xe0d},
+    {0xdae, 0xe0e},
+    {0xdaf, 0xe0f},
+    {0xdb0, 0xe10},
+    {0xdb1, 0xe11},
+    {0xdb2, 0xe12},
+    {0xdb3, 0xe13},
+    {0xdb4, 0xe14},
+    {0xdb5, 0xe15},
+    {0xdb6, 0xe16},
+    {0xdb7, 0xe17},
+    {0xdb8, 0xe18},
+    {0xdb9, 0xe19},
+    {0xdba, 0xe1a},
+    {0xdbb, 0xe1b},
+    {0xdbc, 0xe1c},
+    {0xdbd, 0xe1d},
+    {0xdbe, 0xe1e},
+    {0xdbf, 0xe1f},
+    {0xdc0, 0xe20},
+    {0xdc1, 0xe21},
+    {0xdc2, 0xe22},
+    {0xdc3, 0xe23},
+    {0xdc4, 0xe24},
+    {0xdc5, 0xe25},
+    {0xdc6, 0xe26},
+    {0xdc7, 0xe27},
+    {0xdc8, 0xe28},
+    {0xdc9, 0xe29},
+    {0xdca, 0xe2a},
+    {0xdcb, 0xe2b},
+    {0xdcc, 0xe2c},
+    {0xdcd, 0xe2d},
+    {0xdce, 0xe2e},
+    {0xdcf, 0xe2f},
+    {0xdd0, 0xe30},
+    {0xdd1, 0xe31},
+    {0xdd2, 0xe32},
+    {0xdd3, 0xe33},
+    {0xdd4, 0xe34},
+    {0xdd5, 0xe35},
+    {0xdd6, 0xe36},
+    {0xdd7, 0xe37},
+    {0xdd8, 0xe38},
+    {0xdd9, 0xe39},
+    {0xdda, 0xe3a},
+    {0xddf, 0xe3f},
+    {0xde0, 0xe40},
+    {0xde1, 0xe41},
+    {0xde2, 0xe42},
+    {0xde3, 0xe43},
+    {0xde4, 0xe44},
+    {0xde5, 0xe45},
+    {0xde6, 0xe46},
+    {0xde7, 0xe47},
+    {0xde8, 0xe48},
+    {0xde9, 0xe49},
+    {0xdea, 0xe4a},
+    {0xdeb, 0xe4b},
+    {0xdec, 0xe4c},
+    {0xded, 0xe4d},
+    {0xdf0, 0xe50},
+    {0xdf1, 0xe51},
+    {0xdf2, 0xe52},
+    {0xdf3, 0xe53},
+    {0xdf4, 0xe54},
+    {0xdf5, 0xe55},
+    {0xdf6, 0xe56},
+    {0xdf7, 0xe57},
+    {0xdf8, 0xe58},
+    {0xdf9, 0xe59},
+    {0xea1, 0x3131},
+    {0xea2, 0x3132},
+    {0xea3, 0x3133},
+    {0xea4, 0x3134},
+    {0xea5, 0x3135},
+    {0xea6, 0x3136},
+    {0xea7, 0x3137},
+    {0xea8, 0x3138},
+    {0xea9, 0x3139},
+    {0xeaa, 0x313a},
+    {0xeab, 0x313b},
+    {0xeac, 0x313c},
+    {0xead, 0x313d},
+    {0xeae, 0x313e},
+    {0xeaf, 0x313f},
+    {0xeb0, 0x3140},
+    {0xeb1, 0x3141},
+    {0xeb2, 0x3142},
+    {0xeb3, 0x3143},
+    {0xeb4, 0x3144},
+    {0xeb5, 0x3145},
+    {0xeb6, 0x3146},
+    {0xeb7, 0x3147},
+    {0xeb8, 0x3148},
+    {0xeb9, 0x3149},
+    {0xeba, 0x314a},
+    {0xebb, 0x314b},
+    {0xebc, 0x314c},
+    {0xebd, 0x314d},
+    {0xebe, 0x314e},
+    {0xebf, 0x314f},
+    {0xec0, 0x3150},
+    {0xec1, 0x3151},
+    {0xec2, 0x3152},
+    {0xec3, 0x3153},
+    {0xec4, 0x3154},
+    {0xec5, 0x3155},
+    {0xec6, 0x3156},
+    {0xec7, 0x3157},
+    {0xec8, 0x3158},
+    {0xec9, 0x3159},
+    {0xeca, 0x315a},
+    {0xecb, 0x315b},
+    {0xecc, 0x315c},
+    {0xecd, 0x315d},
+    {0xece, 0x315e},
+    {0xecf, 0x315f},
+    {0xed0, 0x3160},
+    {0xed1, 0x3161},
+    {0xed2, 0x3162},
+    {0xed3, 0x3163},
+    {0xed4, 0x11a8},
+    {0xed5, 0x11a9},
+    {0xed6, 0x11aa},
+    {0xed7, 0x11ab},
+    {0xed8, 0x11ac},
+    {0xed9, 0x11ad},
+    {0xeda, 0x11ae},
+    {0xedb, 0x11af},
+    {0xedc, 0x11b0},
+    {0xedd, 0x11b1},
+    {0xede, 0x11b2},
+    {0xedf, 0x11b3},
+    {0xee0, 0x11b4},
+    {0xee1, 0x11b5},
+    {0xee2, 0x11b6},
+    {0xee3, 0x11b7},
+    {0xee4, 0x11b8},
+    {0xee5, 0x11b9},
+    {0xee6, 0x11ba},
+    {0xee7, 0x11bb},
+    {0xee8, 0x11bc},
+    {0xee9, 0x11bd},
+    {0xeea, 0x11be},
+    {0xeeb, 0x11bf},
+    {0xeec, 0x11c0},
+    {0xeed, 0x11c1},
+    {0xeee, 0x11c2},
+    {0xeef, 0x316d},
+    {0xef0, 0x3171},
+    {0xef1, 0x3178},
+    {0xef2, 0x317f},
+    {0xef3, 0x3181},
+    {0xef4, 0x3184},
+    {0xef5, 0x3186},
+    {0xef6, 0x318d},
+    {0xef7, 0x318e},
+    {0xef8, 0x11eb},
+    {0xef9, 0x11f0},
+    {0xefa, 0x11f9},
+    {0xeff, 0x20a9},
+    {0x13a4, 0x20ac},
+    {0x13bc, 0x152},
+    {0x13bd, 0x153},
+    {0x13be, 0x178},
+    {0x20a0, 0x20a0},
+    {0x20a1, 0x20a1},
+    {0x20a2, 0x20a2},
+    {0x20a3, 0x20a3},
+    {0x20a4, 0x20a4},
+    {0x20a5, 0x20a5},
+    {0x20a6, 0x20a6},
+    {0x20a7, 0x20a7},
+    {0x20a8, 0x20a8},
+    {0x20aa, 0x20aa},
+    {0x20ab, 0x20ab},
+    {0x20ac, 0x20ac},
+};
+
+int keysym_to_unicode(int keysym)
+{
+    int i, j, k;
+
+    i = -1;
+    j = lenof(keysyms);
+
+    while (j - i >= 2) {
+       k = (j + i) / 2;
+       if (keysyms[k].keysym == keysym)
+           return keysyms[k].unicode;
+       else if (keysyms[k].keysym < keysym)
+           i = k;
+       else
+           j = k;
+    }
+    return -1;
+}