Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1985, 1987, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 */
     26 
     27 /* Beware, here be monsters (still under construction... - JG */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include <config.h>
     31 #endif
     32 #include <X11/Xlibint.h>
     33 #include <X11/Xutil.h>
     34 #define XK_MISCELLANY
     35 #define XK_LATIN1
     36 #define XK_LATIN2
     37 #define XK_LATIN3
     38 #define XK_LATIN4
     39 #define XK_LATIN8
     40 #define XK_LATIN9
     41 #define XK_CYRILLIC
     42 #define XK_GREEK
     43 #define XK_ARMENIAN
     44 #define XK_CAUCASUS
     45 #define XK_VIETNAMESE
     46 #define XK_XKB_KEYS
     47 #define XK_SINHALA
     48 #include <X11/keysymdef.h>
     49 #include <stdio.h>
     50 
     51 #include "Xresource.h"
     52 #include "Key.h"
     53 
     54 #ifdef XKB
     55 #include "XKBlib.h"
     56 #include "XKBlibint.h"
     57 #define	XKeycodeToKeysym	_XKeycodeToKeysym
     58 #define	XKeysymToKeycode	_XKeysymToKeycode
     59 #define	XLookupKeysym		_XLookupKeysym
     60 #define	XRefreshKeyboardMapping	_XRefreshKeyboardMapping
     61 #define	XLookupString		_XLookupString
     62 /* XKBBind.c */
     63 #else
     64 #define	XkbKeysymToModifiers	_XKeysymToModifiers
     65 #endif
     66 
     67 #define AllMods (ShiftMask|LockMask|ControlMask| \
     68 		 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
     69 
     70 static void
     71 ComputeMaskFromKeytrans(
     72     Display *dpy,
     73     register struct _XKeytrans *p);
     74 
     75 struct _XKeytrans {
     76 	struct _XKeytrans *next;/* next on list */
     77 	char *string;		/* string to return when the time comes */
     78 	int len;		/* length of string (since NULL is legit)*/
     79 	KeySym key;		/* keysym rebound */
     80 	unsigned int state;	/* modifier state */
     81 	KeySym *modifiers;	/* modifier keysyms you want */
     82 	int mlen;		/* length of modifier list */
     83 };
     84 
     85 static KeySym
     86 KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
     87 {
     88     register int per = dpy->keysyms_per_keycode;
     89     register KeySym *syms;
     90     KeySym lsym, usym;
     91 
     92     if ((col < 0) || ((col >= per) && (col > 3)) ||
     93 	((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
     94       return NoSymbol;
     95 
     96     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
     97     if (col < 4) {
     98 	if (col > 1) {
     99 	    while ((per > 2) && (syms[per - 1] == NoSymbol))
    100 		per--;
    101 	    if (per < 3)
    102 		col -= 2;
    103 	}
    104 	if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
    105 	    XConvertCase(syms[col&~1], &lsym, &usym);
    106 	    if (!(col & 1))
    107 		return lsym;
    108 	    else if (usym == lsym)
    109 		return NoSymbol;
    110 	    else
    111 		return usym;
    112 	}
    113     }
    114     return syms[col];
    115 }
    116 
    117 KeySym
    118 XKeycodeToKeysym(Display *dpy,
    119 #if NeedWidePrototypes
    120 		 unsigned int kc,
    121 #else
    122 		 KeyCode kc,
    123 #endif
    124 		 int col)
    125 {
    126     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
    127 	return NoSymbol;
    128     return KeyCodetoKeySym(dpy, kc, col);
    129 }
    130 
    131 KeyCode
    132 XKeysymToKeycode(
    133     Display *dpy,
    134     KeySym ks)
    135 {
    136     register int i, j;
    137 
    138     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
    139 	return (KeyCode) 0;
    140     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
    141 	for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
    142 	    if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
    143 		return i;
    144 	}
    145     }
    146     return 0;
    147 }
    148 
    149 KeySym
    150 XLookupKeysym(
    151     register XKeyEvent *event,
    152     int col)
    153 {
    154     if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
    155 	return NoSymbol;
    156     return KeyCodetoKeySym(event->display, event->keycode, col);
    157 }
    158 
    159 static void
    160 ResetModMap(
    161     Display *dpy)
    162 {
    163     register XModifierKeymap *map;
    164     register int i, j, n;
    165     KeySym sym;
    166     register struct _XKeytrans *p;
    167 
    168     map = dpy->modifiermap;
    169     /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
    170      * else if any contains Shift_Lock, then interpret as Shift_Lock,
    171      * else ignore Lock altogether.
    172      */
    173     dpy->lock_meaning = NoSymbol;
    174     /* Lock modifiers are in the second row of the matrix */
    175     n = 2 * map->max_keypermod;
    176     for (i = map->max_keypermod; i < n; i++) {
    177 	for (j = 0; j < dpy->keysyms_per_keycode; j++) {
    178 	    sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
    179 	    if (sym == XK_Caps_Lock) {
    180 		dpy->lock_meaning = XK_Caps_Lock;
    181 		break;
    182 	    } else if (sym == XK_Shift_Lock) {
    183 		dpy->lock_meaning = XK_Shift_Lock;
    184 	    }
    185 	    else if (sym == XK_ISO_Lock) {
    186 		dpy->lock_meaning = XK_Caps_Lock;
    187 		break;
    188 	    }
    189 	}
    190     }
    191     /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
    192     dpy->mode_switch = 0;
    193     dpy->num_lock = 0;
    194     n *= 4;
    195     for (i = 3*map->max_keypermod; i < n; i++) {
    196 	for (j = 0; j < dpy->keysyms_per_keycode; j++) {
    197 	    sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
    198 	    if (sym == XK_Mode_switch)
    199 		dpy->mode_switch |= 1 << (i / map->max_keypermod);
    200 	    if (sym == XK_Num_Lock)
    201 		dpy->num_lock |= 1 << (i / map->max_keypermod);
    202 	}
    203     }
    204     for (p = dpy->key_bindings; p; p = p->next)
    205 	ComputeMaskFromKeytrans(dpy, p);
    206 }
    207 
    208 static int
    209 InitModMap(
    210     Display *dpy)
    211 {
    212     register XModifierKeymap *map;
    213 
    214     if (! (map = XGetModifierMapping(dpy)))
    215 	return 0;
    216     LockDisplay(dpy);
    217     if (dpy->modifiermap)
    218 	XFreeModifiermap(dpy->modifiermap);
    219     dpy->modifiermap = map;
    220     dpy->free_funcs->modifiermap = XFreeModifiermap;
    221     if (dpy->keysyms)
    222 	ResetModMap(dpy);
    223     UnlockDisplay(dpy);
    224     return 1;
    225 }
    226 
    227 int
    228 XRefreshKeyboardMapping(register XMappingEvent *event)
    229 {
    230 
    231     if(event->request == MappingKeyboard) {
    232 	/* XXX should really only refresh what is necessary
    233 	 * for now, make initialize test fail
    234 	 */
    235 	LockDisplay(event->display);
    236 	if (event->display->keysyms) {
    237 	     Xfree (event->display->keysyms);
    238 	     event->display->keysyms = NULL;
    239 	}
    240 	UnlockDisplay(event->display);
    241     }
    242     if(event->request == MappingModifier) {
    243 	LockDisplay(event->display);
    244 	if (event->display->modifiermap) {
    245 	    XFreeModifiermap(event->display->modifiermap);
    246 	    event->display->modifiermap = NULL;
    247 	}
    248 	UnlockDisplay(event->display);
    249 	/* go ahead and get it now, since initialize test may not fail */
    250 	if (event->display->keysyms)
    251 	    (void) InitModMap(event->display);
    252     }
    253     return 1;
    254 }
    255 
    256 int
    257 _XKeyInitialize(
    258     Display *dpy)
    259 {
    260     int per, n;
    261     KeySym *keysyms;
    262 
    263     /*
    264      * lets go get the keysyms from the server.
    265      */
    266     if (!dpy->keysyms) {
    267 	n = dpy->max_keycode - dpy->min_keycode + 1;
    268 	keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
    269 				       n, &per);
    270 	/* keysyms may be NULL */
    271 	if (! keysyms) return 0;
    272 
    273 	LockDisplay(dpy);
    274 
    275 	Xfree (dpy->keysyms);
    276 	dpy->keysyms = keysyms;
    277 	dpy->keysyms_per_keycode = per;
    278 	if (dpy->modifiermap)
    279 	    ResetModMap(dpy);
    280 
    281 	UnlockDisplay(dpy);
    282     }
    283     if (!dpy->modifiermap)
    284         return InitModMap(dpy);
    285     return 1;
    286 }
    287 
    288 static void
    289 UCSConvertCase( register unsigned code,
    290                 KeySym *lower,
    291                 KeySym *upper )
    292 {
    293     /* Case conversion for UCS, as in Unicode Data version 4.0.0. */
    294     /* NB: Only converts simple one-to-one mappings. */
    295 
    296     /* Tables are used where they take less space than     */
    297     /* the code to work out the mappings. Zero values mean */
    298     /* undefined code points.                              */
    299 
    300     static unsigned short const IPAExt_upper_mapping[] = { /* part only */
    301                             0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
    302     0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
    303     0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
    304     0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
    305     0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
    306     0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
    307     0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
    308     0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
    309     0x0290, 0x0291, 0x01B7
    310     };
    311 
    312     static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */
    313     0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
    314     0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
    315     0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
    316     0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
    317     0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
    318     0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
    319     0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
    320     0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
    321     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
    322     0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
    323     };
    324 
    325     static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */
    326     0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
    327     0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
    328     0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
    329     0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
    330     0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
    331     0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
    332     0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
    333     0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
    334     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
    335     0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
    336     };
    337 
    338     static unsigned short const Greek_upper_mapping[] = { /* updated to UD 14.0 */
    339     0x0370, 0x0370, 0x0372, 0x0372, 0x0374, 0x0375, 0x0376, 0x0376,
    340     0x0000, 0x0000, 0x037A, 0x03FD, 0x03FE, 0x03FF, 0x037E, 0x037F,
    341     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
    342     0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
    343     0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
    344     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
    345     0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
    346     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
    347     0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
    348     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
    349     0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
    350     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,
    351     0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03CF,
    352     0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
    353     0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
    354     0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
    355     0x039A, 0x03A1, 0x03F9, 0x037F, 0x03F4, 0x0395, 0x03F6, 0x03F7,
    356     0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x03FC, 0x03FD, 0x03FE, 0x03FF
    357     };
    358 
    359     static unsigned short const Greek_lower_mapping[] = { /* updated to UD 14.0 */
    360     0x0371, 0x0371, 0x0373, 0x0373, 0x0374, 0x0375, 0x0377, 0x0377,
    361     0x0000, 0x0000, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x03F3,
    362     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
    363     0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
    364     0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
    365     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
    366     0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
    367     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
    368     0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
    369     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
    370     0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
    371     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03D7,
    372     0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
    373     0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
    374     0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
    375     0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
    376     0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
    377     0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x03FC, 0x037B, 0x037C, 0x037D
    378     };
    379 
    380     static unsigned short const GreekExt_lower_mapping[] = {
    381     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
    382     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
    383     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
    384     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
    385     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
    386     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
    387     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
    388     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
    389     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
    390     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
    391     0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
    392     0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
    393     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
    394     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
    395     0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
    396     0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
    397     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
    398     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
    399     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
    400     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
    401     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
    402     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
    403     0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
    404     0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
    405     0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
    406     0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
    407     0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
    408     0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
    409     0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
    410     0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
    411     0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
    412     0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
    413     };
    414 
    415     static unsigned short const GreekExt_upper_mapping[] = {
    416     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
    417     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
    418     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
    419     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
    420     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
    421     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
    422     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
    423     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
    424     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
    425     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
    426     0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
    427     0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
    428     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
    429     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
    430     0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
    431     0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
    432     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
    433     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
    434     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
    435     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
    436     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
    437     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
    438     0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
    439     0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
    440     0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
    441     0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
    442     0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
    443     0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
    444     0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
    445     0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
    446     0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
    447     0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
    448     };
    449 
    450     *lower = code;
    451     *upper = code;
    452 
    453     /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
    454     if (code <= 0x00ff) {
    455         if (code >= 0x0041 && code <= 0x005a)             /* A-Z */
    456             *lower += 0x20;
    457         else if (code >= 0x0061 && code <= 0x007a)        /* a-z */
    458             *upper -= 0x20;
    459         else if ( (code >= 0x00c0 && code <= 0x00d6) ||
    460 	          (code >= 0x00d8 && code <= 0x00de) )
    461             *lower += 0x20;
    462         else if ( (code >= 0x00e0 && code <= 0x00f6) ||
    463 	          (code >= 0x00f8 && code <= 0x00fe) )
    464             *upper -= 0x20;
    465         /* The following code points do not map within Latin-1 and
    466          * require special handling in XConvertCase
    467          */
    468         else if (code == 0x00ff)      /* y with diaeresis */
    469             *upper = 0x0178;
    470         else if (code == 0x00b5)      /* micro sign */
    471             *upper = 0x039c;
    472         else if (code == 0x00df)      /* ssharp */
    473             *upper = 0x1e9e;
    474 	return;
    475     }
    476 
    477     /* Latin Extended-A, U+0100 to U+017F */
    478     if (code <= 0x017f) {
    479         if ( (code >= 0x0100 && code <= 0x012f) ||
    480              (code >= 0x0132 && code <= 0x0137) ||
    481              (code >= 0x014a && code <= 0x0177) ) {
    482             *upper = code & ~1;
    483             *lower = code | 1;
    484         }
    485         else if ( (code >= 0x0139 && code <= 0x0148) ||
    486                   (code >= 0x0179 && code <= 0x017e) ) {
    487             if (code & 1)
    488 	        *lower += 1;
    489             else
    490 	        *upper -= 1;
    491         }
    492         else if (code == 0x0130)
    493             *lower = 0x0069;
    494         else if (code == 0x0131)
    495             *upper = 0x0049;
    496         else if (code == 0x0178)
    497             *lower = 0x00ff;
    498         else if (code == 0x017f)
    499             *upper = 0x0053;
    500         return;
    501     }
    502 
    503     /* Latin Extended-B, U+0180 to U+024F */
    504     if (code <= 0x024f) {
    505         if (code >= 0x0180 && code <= 0x01cc) {
    506             *lower = LatinExtB_lower_mapping[code - 0x0180];
    507             *upper = LatinExtB_upper_mapping[code - 0x0180];
    508         }
    509         else if (code >= 0x01cd && code <= 0x01dc) {
    510 	    if (code & 1)
    511 	       *lower += 1;
    512 	    else
    513 	       *upper -= 1;
    514         }
    515         else if (code == 0x01dd)
    516             *upper = 0x018e;
    517         else if ( (code >= 0x01de && code <= 0x01ef) ||
    518                   (code >= 0x01f4 && code <= 0x01f5) ||
    519                   (code >= 0x01f8 && code <= 0x021f) ||
    520                   (code >= 0x0222 && code <= 0x0233) ) {
    521             *lower |= 1;
    522             *upper &= ~1;
    523         }
    524         else if (code == 0x01f1 || code == 0x01f2) {
    525             *lower = 0x01f3;
    526             *upper = 0x01f1;
    527         }
    528         else if (code == 0x01f3)
    529             *upper = 0x01f1;
    530         else if (code == 0x01f6)
    531             *lower = 0x0195;
    532         else if (code == 0x01f7)
    533             *lower = 0x01bf;
    534         else if (code == 0x0220)
    535             *lower = 0x019e;
    536         return;
    537     }
    538 
    539     /* IPA Extensions, U+0250 to U+02AF */
    540     if (code >= 0x0253 && code <= 0x0292) {
    541         *upper = IPAExt_upper_mapping[code - 0x0253];
    542         return;
    543     }
    544 
    545     /* Combining Diacritical Marks, U+0300 to U+036F */
    546     if (code == 0x0345) {
    547         *upper = 0x0399;
    548         return;
    549     }
    550 
    551     /* Greek and Coptic, U+0370 to U+03FF */
    552     if (code >= 0x0370 && code <= 0x03ff) {
    553         *lower = Greek_lower_mapping[code - 0x0370];
    554         *upper = Greek_upper_mapping[code - 0x0370];
    555         if (*upper == 0)
    556             *upper = code;
    557         if (*lower == 0)
    558             *lower = code;
    559         return;
    560     }
    561 
    562     /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
    563     if ( (code >= 0x0400 && code <= 0x052f) ) {
    564         if (code >= 0x0400 && code <= 0x040f)
    565             *lower += 0x50;
    566         else if (code >= 0x0410 && code <= 0x042f)
    567             *lower += 0x20;
    568         else if (code >= 0x0430 && code <= 0x044f)
    569             *upper -= 0x20;
    570         else if (code >= 0x0450 && code <= 0x045f)
    571             *upper -= 0x50;
    572         else if ( (code >= 0x0460 && code <= 0x0481) ||
    573                   (code >= 0x048a && code <= 0x04bf) ||
    574 	          (code >= 0x04d0 && code <= 0x04f5) ||
    575 	          (code >= 0x04f8 && code <= 0x04f9) ||
    576                   (code >= 0x0500 && code <= 0x050f) ) {
    577             *upper &= ~1;
    578             *lower |= 1;
    579         }
    580         else if (code >= 0x04c1 && code <= 0x04ce) {
    581 	    if (code & 1)
    582 	        *lower += 1;
    583 	    else
    584 	        *upper -= 1;
    585         }
    586         return;
    587     }
    588 
    589     /* Armenian, U+0530 to U+058F */
    590     if (code >= 0x0530 && code <= 0x058f) {
    591         if (code >= 0x0531 && code <= 0x0556)
    592             *lower += 0x30;
    593         else if (code >=0x0561 && code <= 0x0586)
    594             *upper -= 0x30;
    595         return;
    596     }
    597 
    598     /* Latin Extended Additional, U+1E00 to U+1EFF */
    599     if (code >= 0x1e00 && code <= 0x1eff) {
    600         if ( (code >= 0x1e00 && code <= 0x1e95) ||
    601              (code >= 0x1ea0 && code <= 0x1ef9) ) {
    602             *upper &= ~1;
    603             *lower |= 1;
    604         }
    605         else if (code == 0x1e9b)
    606             *upper = 0x1e60;
    607         else if (code == 0x1e9e)
    608             *lower = 0x00df;    /* ssharp */
    609         return;
    610     }
    611 
    612     /* Greek Extended, U+1F00 to U+1FFF */
    613     if (code >= 0x1f00 && code <= 0x1fff) {
    614         *lower = GreekExt_lower_mapping[code - 0x1f00];
    615         *upper = GreekExt_upper_mapping[code - 0x1f00];
    616         if (*upper == 0)
    617             *upper = code;
    618         if (*lower == 0)
    619             *lower = code;
    620         return;
    621     }
    622 
    623     /* Letterlike Symbols, U+2100 to U+214F */
    624     if (code >= 0x2100 && code <= 0x214f) {
    625         switch (code) {
    626         case 0x2126: *lower = 0x03c9; break;
    627         case 0x212a: *lower = 0x006b; break;
    628         case 0x212b: *lower = 0x00e5; break;
    629         }
    630     }
    631     /* Number Forms, U+2150 to U+218F */
    632     else if (code >= 0x2160 && code <= 0x216f)
    633         *lower += 0x10;
    634     else if (code >= 0x2170 && code <= 0x217f)
    635         *upper -= 0x10;
    636     /* Enclosed Alphanumerics, U+2460 to U+24FF */
    637     else if (code >= 0x24b6 && code <= 0x24cf)
    638         *lower += 0x1a;
    639     else if (code >= 0x24d0 && code <= 0x24e9)
    640         *upper -= 0x1a;
    641     /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
    642     else if (code >= 0xff21 && code <= 0xff3a)
    643         *lower += 0x20;
    644     else if (code >= 0xff41 && code <= 0xff5a)
    645         *upper -= 0x20;
    646     /* Deseret, U+10400 to U+104FF */
    647     else if (code >= 0x10400 && code <= 0x10427)
    648         *lower += 0x28;
    649     else if (code >= 0x10428 && code <= 0x1044f)
    650         *upper -= 0x28;
    651 }
    652 
    653 void
    654 XConvertCase(
    655     register KeySym sym,
    656     KeySym *lower,
    657     KeySym *upper)
    658 {
    659     /* Latin 1 keysym */
    660     if (sym < 0x100) {
    661         /* Special cases that do not map within Latin-1 */
    662         switch (sym) {
    663         case XK_ydiaeresis:
    664             *lower = sym;
    665             *upper = XK_Ydiaeresis;
    666             return;
    667         case XK_mu:
    668             *lower = sym;
    669             *upper = XK_Greek_MU;
    670             return;
    671         case XK_ssharp:
    672             *lower = sym;
    673             *upper = 0x1001e9e;
    674             return;
    675         default:
    676             UCSConvertCase(sym, lower, upper);
    677             return;
    678         }
    679     }
    680 
    681     /* Unicode keysym */
    682     if ((sym & 0xff000000) == 0x01000000) {
    683         UCSConvertCase((sym & 0x00ffffff), lower, upper);
    684         /* Use the Unicode keysym mask only for non Latin-1 */
    685         if (*upper >= 0x100)
    686             *upper |= 0x01000000;
    687         if (*lower >= 0x100)
    688             *lower |= 0x01000000;
    689         return;
    690     }
    691 
    692     /* Legacy keysym */
    693 
    694     *lower = sym;
    695     *upper = sym;
    696 
    697     switch(sym >> 8) {
    698     case 1: /* Latin 2 */
    699 	/* Assume the KeySym is a legal value (ignore discontinuities) */
    700 	if (sym == XK_Aogonek)
    701 	    *lower = XK_aogonek;
    702 	else if (sym >= XK_Lstroke && sym <= XK_Sacute)
    703 	    *lower += (XK_lstroke - XK_Lstroke);
    704 	else if (sym >= XK_Scaron && sym <= XK_Zacute)
    705 	    *lower += (XK_scaron - XK_Scaron);
    706 	else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
    707 	    *lower += (XK_zcaron - XK_Zcaron);
    708 	else if (sym == XK_aogonek)
    709 	    *upper = XK_Aogonek;
    710 	else if (sym >= XK_lstroke && sym <= XK_sacute)
    711 	    *upper -= (XK_lstroke - XK_Lstroke);
    712 	else if (sym >= XK_scaron && sym <= XK_zacute)
    713 	    *upper -= (XK_scaron - XK_Scaron);
    714 	else if (sym >= XK_zcaron && sym <= XK_zabovedot)
    715 	    *upper -= (XK_zcaron - XK_Zcaron);
    716 	else if (sym >= XK_Racute && sym <= XK_Tcedilla)
    717 	    *lower += (XK_racute - XK_Racute);
    718 	else if (sym >= XK_racute && sym <= XK_tcedilla)
    719 	    *upper -= (XK_racute - XK_Racute);
    720 	break;
    721     case 2: /* Latin 3 */
    722 	/* Assume the KeySym is a legal value (ignore discontinuities) */
    723 	if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
    724 	    *lower += (XK_hstroke - XK_Hstroke);
    725 	else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
    726 	    *lower += (XK_gbreve - XK_Gbreve);
    727 	else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
    728 	    *upper -= (XK_hstroke - XK_Hstroke);
    729 	else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
    730 	    *upper -= (XK_gbreve - XK_Gbreve);
    731 	else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
    732 	    *lower += (XK_cabovedot - XK_Cabovedot);
    733 	else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
    734 	    *upper -= (XK_cabovedot - XK_Cabovedot);
    735 	break;
    736     case 3: /* Latin 4 */
    737 	/* Assume the KeySym is a legal value (ignore discontinuities) */
    738 	if (sym >= XK_Rcedilla && sym <= XK_Tslash)
    739 	    *lower += (XK_rcedilla - XK_Rcedilla);
    740 	else if (sym >= XK_rcedilla && sym <= XK_tslash)
    741 	    *upper -= (XK_rcedilla - XK_Rcedilla);
    742 	else if (sym == XK_ENG)
    743 	    *lower = XK_eng;
    744 	else if (sym == XK_eng)
    745 	    *upper = XK_ENG;
    746 	else if (sym >= XK_Amacron && sym <= XK_Umacron)
    747 	    *lower += (XK_amacron - XK_Amacron);
    748 	else if (sym >= XK_amacron && sym <= XK_umacron)
    749 	    *upper -= (XK_amacron - XK_Amacron);
    750 	break;
    751     case 6: /* Cyrillic */
    752 	/* Assume the KeySym is a legal value (ignore discontinuities) */
    753 	if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
    754 	    *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
    755 	else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
    756 	    *upper += (XK_Serbian_DJE - XK_Serbian_dje);
    757 	else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
    758 	    *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
    759 	else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
    760 	    *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
    761         break;
    762     case 7: /* Greek */
    763 	/* Assume the KeySym is a legal value (ignore discontinuities) */
    764 	if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
    765 	    *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
    766 	else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
    767 		 sym != XK_Greek_iotaaccentdieresis &&
    768 		 sym != XK_Greek_upsilonaccentdieresis)
    769 	    *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
    770 	else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
    771 	    *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
    772 	else if (sym == XK_Greek_finalsmallsigma)
    773 	    *upper = XK_Greek_SIGMA;
    774 	else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega)
    775 	    *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
    776         break;
    777     case 0x13: /* Latin 9 */
    778         if (sym == XK_OE)
    779             *lower = XK_oe;
    780         else if (sym == XK_oe)
    781             *upper = XK_OE;
    782         else if (sym == XK_Ydiaeresis)
    783             *lower = XK_ydiaeresis;
    784         break;
    785     }
    786 }
    787 
    788 int
    789 _XTranslateKey(	register Display *dpy,
    790 		KeyCode keycode,
    791 		register unsigned int modifiers,
    792 		unsigned int *modifiers_return,
    793 		KeySym *keysym_return)
    794 {
    795     int per;
    796     register KeySym *syms;
    797     KeySym sym, lsym, usym;
    798 
    799     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
    800 	return 0;
    801     *modifiers_return = ((ShiftMask|LockMask)
    802 			 | dpy->mode_switch | dpy->num_lock);
    803     if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
    804     {
    805 	*keysym_return = NoSymbol;
    806 	return 1;
    807     }
    808     per = dpy->keysyms_per_keycode;
    809     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
    810     while ((per > 2) && (syms[per - 1] == NoSymbol))
    811 	per--;
    812     if ((per > 2) && (modifiers & dpy->mode_switch)) {
    813 	syms += 2;
    814 	per -= 2;
    815     }
    816     if ((modifiers & dpy->num_lock) &&
    817 	(per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
    818 	if ((modifiers & ShiftMask) ||
    819 	    ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
    820 	    *keysym_return = syms[0];
    821 	else
    822 	    *keysym_return = syms[1];
    823     } else if (!(modifiers & ShiftMask) &&
    824 	(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
    825 	if ((per == 1) || (syms[1] == NoSymbol))
    826 	    XConvertCase(syms[0], keysym_return, &usym);
    827 	else
    828 	    *keysym_return = syms[0];
    829     } else if (!(modifiers & LockMask) ||
    830 	       (dpy->lock_meaning != XK_Caps_Lock)) {
    831 	if ((per == 1) || ((usym = syms[1]) == NoSymbol))
    832 	    XConvertCase(syms[0], &lsym, &usym);
    833 	*keysym_return = usym;
    834     } else {
    835 	if ((per == 1) || ((sym = syms[1]) == NoSymbol))
    836 	    sym = syms[0];
    837 	XConvertCase(sym, &lsym, &usym);
    838 	if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
    839 	    ((sym != usym) || (lsym == usym)))
    840 	    XConvertCase(syms[0], &lsym, &usym);
    841 	*keysym_return = usym;
    842     }
    843     if (*keysym_return == XK_VoidSymbol)
    844 	*keysym_return = NoSymbol;
    845     return 1;
    846 }
    847 
    848 int
    849 _XTranslateKeySym(
    850     Display *dpy,
    851     register KeySym symbol,
    852     unsigned int modifiers,
    853     char *buffer,
    854     int nbytes)
    855 {
    856     register struct _XKeytrans *p;
    857     int length;
    858     unsigned long hiBytes;
    859     register unsigned char c;
    860 
    861     if (!symbol)
    862 	return 0;
    863     /* see if symbol rebound, if so, return that string. */
    864     for (p = dpy->key_bindings; p; p = p->next) {
    865 	if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
    866 	    length = p->len;
    867 	    if (length > nbytes) length = nbytes;
    868 	    memcpy (buffer, p->string, (size_t) length);
    869 	    return length;
    870 	}
    871     }
    872     /* try to convert to Latin-1, handling control */
    873     hiBytes = symbol >> 8;
    874     if (!(nbytes &&
    875 	  ((hiBytes == 0) ||
    876 	   ((hiBytes == 0xFF) &&
    877 	    (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
    878 	     (symbol == XK_Return) ||
    879 	     (symbol == XK_Escape) ||
    880 	     (symbol == XK_KP_Space) ||
    881 	     (symbol == XK_KP_Tab) ||
    882 	     (symbol == XK_KP_Enter) ||
    883 	     ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
    884 	     (symbol == XK_KP_Equal) ||
    885 	     (symbol == XK_Delete))))))
    886 	return 0;
    887 
    888     /* if X keysym, convert to ascii by grabbing low 7 bits */
    889     if (symbol == XK_KP_Space)
    890 	c = XK_space & 0x7F; /* patch encoding botch */
    891     else if (hiBytes == 0xFF)
    892 	c = symbol & 0x7F;
    893     else
    894 	c = symbol & 0xFF;
    895     /* only apply Control key if it makes sense, else ignore it */
    896     if (modifiers & ControlMask) {
    897 	if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
    898 	else if (c == '2') c = '\000';
    899 	else if (c >= '3' && c <= '7') c -= ('3' - '\033');
    900 	else if (c == '8') c = '\177';
    901 	else if (c == '/') c = '_' & 0x1F;
    902     }
    903     buffer[0] = c;
    904     return 1;
    905 }
    906 
    907 /*ARGSUSED*/
    908 int
    909 XLookupString (
    910     register XKeyEvent *event,
    911     char *buffer,	/* buffer */
    912     int nbytes,	/* space in buffer for characters */
    913     KeySym *keysym,
    914     XComposeStatus *status)	/* not implemented */
    915 {
    916     unsigned int modifiers;
    917     KeySym symbol;
    918 
    919     if (! _XTranslateKey(event->display, event->keycode, event->state,
    920 		  &modifiers, &symbol))
    921 	return 0;
    922 
    923     if (keysym)
    924 	*keysym = symbol;
    925     /* arguable whether to use (event->state & ~modifiers) here */
    926     return _XTranslateKeySym(event->display, symbol, event->state,
    927 			     buffer, nbytes);
    928 }
    929 
    930 static void
    931 _XFreeKeyBindings(
    932     Display *dpy)
    933 {
    934     register struct _XKeytrans *p, *np;
    935 
    936     for (p = dpy->key_bindings; p; p = np) {
    937 	np = p->next;
    938 	Xfree(p->string);
    939 	Xfree(p->modifiers);
    940 	Xfree(p);
    941     }
    942     dpy->key_bindings = NULL;
    943 }
    944 
    945 int
    946 XRebindKeysym (
    947     Display *dpy,
    948     KeySym keysym,
    949     KeySym *mlist,
    950     int nm,		/* number of modifiers in mlist */
    951     _Xconst unsigned char *str,
    952     int nbytes)
    953 {
    954     register struct _XKeytrans *tmp, *p;
    955     int nb;
    956 
    957     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
    958 	return 0;
    959     LockDisplay(dpy);
    960     tmp = dpy->key_bindings;
    961     nb = sizeof(KeySym) * nm;
    962 
    963     if ((! (p = Xcalloc( 1, sizeof(struct _XKeytrans)))) ||
    964 	((! (p->string = Xmalloc(nbytes))) && (nbytes > 0)) ||
    965 	((! (p->modifiers = Xmalloc(nb))) && (nb > 0))) {
    966 	if (p) {
    967 	    Xfree(p->string);
    968 	    Xfree(p->modifiers);
    969 	    Xfree(p);
    970 	}
    971 	UnlockDisplay(dpy);
    972 	return 0;
    973     }
    974 
    975     dpy->key_bindings = p;
    976     dpy->free_funcs->key_bindings = _XFreeKeyBindings;
    977     p->next = tmp;	/* chain onto list */
    978     memcpy (p->string, str, (size_t) nbytes);
    979     p->len = nbytes;
    980     memcpy ((char *) p->modifiers, (char *) mlist, (size_t) nb);
    981     p->key = keysym;
    982     p->mlen = nm;
    983     UnlockDisplay(dpy);
    984     ComputeMaskFromKeytrans(dpy, p);
    985 
    986     return 0;
    987 }
    988 
    989 unsigned
    990 _XKeysymToModifiers(
    991     Display *dpy,
    992     KeySym ks)
    993 {
    994     CARD8 code,mods;
    995     register KeySym *kmax;
    996     register KeySym *k;
    997     register XModifierKeymap *m;
    998 
    999     if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
   1000 	return 0;
   1001     kmax = dpy->keysyms +
   1002 	   (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
   1003     k = dpy->keysyms;
   1004     m = dpy->modifiermap;
   1005     mods= 0;
   1006     while (k<kmax) {
   1007 	if (*k == ks ) {
   1008 	    register int j = m->max_keypermod<<3;
   1009 
   1010 	    code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
   1011 
   1012 	    while (--j >= 0) {
   1013 		if (code == m->modifiermap[j])
   1014 		    mods|= (1<<(j/m->max_keypermod));
   1015 	    }
   1016 	}
   1017 	k++;
   1018     }
   1019     return mods;
   1020 }
   1021 
   1022 /*
   1023  * given a list of modifiers, computes the mask necessary for later matching.
   1024  * This routine must lookup the key in the Keymap and then search to see
   1025  * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
   1026  * can't map some keysym to a modifier.
   1027  */
   1028 static void
   1029 ComputeMaskFromKeytrans(
   1030     Display *dpy,
   1031     register struct _XKeytrans *p)
   1032 {
   1033     register int i;
   1034 
   1035     p->state = AnyModifier;
   1036     for (i = 0; i < p->mlen; i++) {
   1037 	p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
   1038     }
   1039     p->state &= AllMods;
   1040 }
   1041