1/* 2 3Copyright 1985, 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in 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 70static void 71ComputeMaskFromKeytrans( 72 Display *dpy, 73 register struct _XKeytrans *p); 74 75struct _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 85static KeySym 86KeyCodetoKeySym(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 117KeySym 118XKeycodeToKeysym(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 131KeyCode 132XKeysymToKeycode( 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 149KeySym 150XLookupKeysym( 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 159static void 160ResetModMap( 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 208static int 209InitModMap( 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 227int 228XRefreshKeyboardMapping(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 256int 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 288static void 289UCSConvertCase( 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 653void 654XConvertCase( 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 788int 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 848int 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*/ 908int 909XLookupString ( 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 930static 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 945int 946XRebindKeysym ( 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 989unsigned 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 */ 1028static void 1029ComputeMaskFromKeytrans( 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