2 * This module converts keysym values into the corresponding ISO 10646
3 * (UCS, Unicode) values.
5 * The array keysymtab[] contains pairs of X11 keysym values for graphical
6 * characters and the corresponding Unicode value. The function
7 * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
8 * therefore keysymtab[] must remain SORTED by keysym value.
10 * The keysym -> UTF-8 conversion will hopefully one day be provided
11 * by Xlib via XmbLookupString() and should ideally not have to be
12 * done in X applications. But we are not there yet.
14 * We allow to represent any UCS character in the range U-00000000 to
15 * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
16 * This admittedly does not cover the entire 31-bit space of UCS, but
17 * it does cover all of the characters up to U-10FFFF, which can be
18 * represented by UTF-16, and more, and it is very unlikely that higher
19 * UCS codes will ever be assigned by ISO. So to get Unicode character
20 * U+ABCD you can directly use keysym 0x0100abcd.
22 * NOTE: The comments in the table below contain the actual character
23 * encoded in UTF-8, so for viewing and editing best use an editor in
26 * Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
28 * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
29 * an initial draft of the mapping table.
31 * This software is in the public domain. Share and enjoy!
33 * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
36 #include "keysym2ucs.h"
42 unsigned short keysym;
46 const static struct codepair keysymtab[] = {
801 /* FIXME: there is no keysym 0x13a4? But 0x20ac is EuroSign in both
802 keysym and Unicode */
810 /* Special function keys. */
812 { 0xff08, 0x0008 }, /* XK_BackSpace */
813 { 0xff09, 0x0009 }, /* XK_Tab */
814 { 0xff0a, 0x000a }, /* XK_Linefeed */
815 { 0xff0d, 0x000d }, /* XK_Return */
816 { 0xff13, 0x0013 }, /* XK_Pause */
817 { 0xff1b, 0x001b }, /* XK_Escape */
818 { 0xff50, 0x0001 }, /* XK_Home */
819 { 0xff51, 0x001c }, /* XK_Left */
820 { 0xff52, 0x001e }, /* XK_Up */
821 { 0xff53, 0x001d }, /* XK_Right */
822 { 0xff54, 0x001f }, /* XK_Down */
823 { 0xff55, 0x000b }, /* XK_Prior */
824 { 0xff56, 0x000c }, /* XK_Next */
825 { 0xff57, 0x0004 }, /* XK_End */
826 { 0xff6a, 0x0005 }, /* XK_Help */
827 { 0xffff, 0x007f }, /* XK_Delete */
830 long keysym2ucs(int keysym)
833 int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
836 /* first check for Latin-1 characters (1:1 mapping) */
837 if ((keysym >= 0x0020 && keysym <= 0x007e) ||
838 (keysym >= 0x00a0 && keysym <= 0x00ff))
841 /* also check for directly encoded 24-bit UCS characters */
842 if ((keysym & 0xff000000) == 0x01000000)
843 return keysym & 0x00ffffff;
845 /* binary search in table */
847 mid = (min + max) / 2;
848 if (keysymtab[mid].keysym < keysym)
850 else if (keysymtab[mid].keysym > keysym)
854 return keysymtab[mid].ucs;
858 /* no matching Unicode value found */
862 static int reverse_compare (const void *a, const void *b)
864 const struct codepair *ca = a, *cb = b;
866 return ca->ucs - cb->ucs;
869 int ucs2keysym(long ucs)
871 static struct codepair *reverse_keysymtab;
874 int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
877 if (reverse_keysymtab == NULL)
879 reverse_keysymtab = malloc (sizeof (keysymtab));
880 memcpy (reverse_keysymtab, keysymtab, sizeof (keysymtab));
882 qsort (reverse_keysymtab,
883 sizeof (keysymtab) / sizeof (struct codepair),
884 sizeof (struct codepair),
888 /* first check for Latin-1 characters (1:1 mapping) */
889 if ((ucs >= 0x0020 && ucs <= 0x007e) ||
890 (ucs >= 0x00a0 && ucs <= 0x00ff))
893 /* binary search in table */
895 mid = (min + max) / 2;
896 if (reverse_keysymtab[mid].ucs < ucs)
898 else if (reverse_keysymtab[mid].ucs > ucs)
902 return reverse_keysymtab[mid].keysym;
906 /* finally, assume a directly encoded 24-bit UCS character */
907 return ucs | 0x01000000;