KeyBind.c revision d4a3aaf4
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[] = { 339 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 340 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, 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, 0x0000, 351 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7, 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, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7, 356 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000 357 }; 358 359 static unsigned short const Greek_lower_mapping[] = { 360 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 361 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, 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, 0x0000, 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, 0x0000, 0x0000, 0x0000, 0x0000 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 else if (code == 0x00ff) /* y with diaeresis */ 466 *upper = 0x0178; 467 else if (code == 0x00b5) /* micro sign */ 468 *upper = 0x039c; 469 else if (code == 0x00df) /* ssharp */ 470 *upper = 0x1e9e; 471 return; 472 } 473 474 /* Latin Extended-A, U+0100 to U+017F */ 475 if (code >= 0x0100 && code <= 0x017f) { 476 if ( (code >= 0x0100 && code <= 0x012f) || 477 (code >= 0x0132 && code <= 0x0137) || 478 (code >= 0x014a && code <= 0x0177) ) { 479 *upper = code & ~1; 480 *lower = code | 1; 481 } 482 else if ( (code >= 0x0139 && code <= 0x0148) || 483 (code >= 0x0179 && code <= 0x017e) ) { 484 if (code & 1) 485 *lower += 1; 486 else 487 *upper -= 1; 488 } 489 else if (code == 0x0130) 490 *lower = 0x0069; 491 else if (code == 0x0131) 492 *upper = 0x0049; 493 else if (code == 0x0178) 494 *lower = 0x00ff; 495 else if (code == 0x017f) 496 *upper = 0x0053; 497 return; 498 } 499 500 /* Latin Extended-B, U+0180 to U+024F */ 501 if (code >= 0x0180 && code <= 0x024f) { 502 if (code >= 0x01cd && code <= 0x01dc) { 503 if (code & 1) 504 *lower += 1; 505 else 506 *upper -= 1; 507 } 508 else if ( (code >= 0x01de && code <= 0x01ef) || 509 (code >= 0x01f4 && code <= 0x01f5) || 510 (code >= 0x01f8 && code <= 0x021f) || 511 (code >= 0x0222 && code <= 0x0233) ) { 512 *lower |= 1; 513 *upper &= ~1; 514 } 515 else if (code >= 0x0180 && code <= 0x01cc) { 516 *lower = LatinExtB_lower_mapping[code - 0x0180]; 517 *upper = LatinExtB_upper_mapping[code - 0x0180]; 518 } 519 else if (code == 0x01dd) 520 *upper = 0x018e; 521 else if (code == 0x01f1 || code == 0x01f2) { 522 *lower = 0x01f3; 523 *upper = 0x01f1; 524 } 525 else if (code == 0x01f3) 526 *upper = 0x01f1; 527 else if (code == 0x01f6) 528 *lower = 0x0195; 529 else if (code == 0x01f7) 530 *lower = 0x01bf; 531 else if (code == 0x0220) 532 *lower = 0x019e; 533 return; 534 } 535 536 /* IPA Extensions, U+0250 to U+02AF */ 537 if (code >= 0x0253 && code <= 0x0292) { 538 *upper = IPAExt_upper_mapping[code - 0x0253]; 539 } 540 541 /* Combining Diacritical Marks, U+0300 to U+036F */ 542 if (code == 0x0345) { 543 *upper = 0x0399; 544 } 545 546 /* Greek and Coptic, U+0370 to U+03FF */ 547 if (code >= 0x0370 && code <= 0x03ff) { 548 *lower = Greek_lower_mapping[code - 0x0370]; 549 *upper = Greek_upper_mapping[code - 0x0370]; 550 if (*upper == 0) 551 *upper = code; 552 if (*lower == 0) 553 *lower = code; 554 } 555 556 /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */ 557 if ( (code >= 0x0400 && code <= 0x04ff) || 558 (code >= 0x0500 && code <= 0x052f) ) { 559 if (code >= 0x0400 && code <= 0x040f) 560 *lower += 0x50; 561 else if (code >= 0x0410 && code <= 0x042f) 562 *lower += 0x20; 563 else if (code >= 0x0430 && code <= 0x044f) 564 *upper -= 0x20; 565 else if (code >= 0x0450 && code <= 0x045f) 566 *upper -= 0x50; 567 else if ( (code >= 0x0460 && code <= 0x0481) || 568 (code >= 0x048a && code <= 0x04bf) || 569 (code >= 0x04d0 && code <= 0x04f5) || 570 (code >= 0x04f8 && code <= 0x04f9) || 571 (code >= 0x0500 && code <= 0x050f) ) { 572 *upper &= ~1; 573 *lower |= 1; 574 } 575 else if (code >= 0x04c1 && code <= 0x04ce) { 576 if (code & 1) 577 *lower += 1; 578 else 579 *upper -= 1; 580 } 581 } 582 583 /* Armenian, U+0530 to U+058F */ 584 if (code >= 0x0530 && code <= 0x058f) { 585 if (code >= 0x0531 && code <= 0x0556) 586 *lower += 0x30; 587 else if (code >=0x0561 && code <= 0x0586) 588 *upper -= 0x30; 589 } 590 591 /* Latin Extended Additional, U+1E00 to U+1EFF */ 592 if (code >= 0x1e00 && code <= 0x1eff) { 593 if ( (code >= 0x1e00 && code <= 0x1e95) || 594 (code >= 0x1ea0 && code <= 0x1ef9) ) { 595 *upper &= ~1; 596 *lower |= 1; 597 } 598 else if (code == 0x1e9b) 599 *upper = 0x1e60; 600 else if (code == 0x1e9e) 601 *lower = 0x00df; /* ssharp */ 602 } 603 604 /* Greek Extended, U+1F00 to U+1FFF */ 605 if (code >= 0x1f00 && code <= 0x1fff) { 606 *lower = GreekExt_lower_mapping[code - 0x1f00]; 607 *upper = GreekExt_upper_mapping[code - 0x1f00]; 608 if (*upper == 0) 609 *upper = code; 610 if (*lower == 0) 611 *lower = code; 612 } 613 614 /* Letterlike Symbols, U+2100 to U+214F */ 615 if (code >= 0x2100 && code <= 0x214f) { 616 switch (code) { 617 case 0x2126: *lower = 0x03c9; break; 618 case 0x212a: *lower = 0x006b; break; 619 case 0x212b: *lower = 0x00e5; break; 620 } 621 } 622 /* Number Forms, U+2150 to U+218F */ 623 else if (code >= 0x2160 && code <= 0x216f) 624 *lower += 0x10; 625 else if (code >= 0x2170 && code <= 0x217f) 626 *upper -= 0x10; 627 /* Enclosed Alphanumerics, U+2460 to U+24FF */ 628 else if (code >= 0x24b6 && code <= 0x24cf) 629 *lower += 0x1a; 630 else if (code >= 0x24d0 && code <= 0x24e9) 631 *upper -= 0x1a; 632 /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */ 633 else if (code >= 0xff21 && code <= 0xff3a) 634 *lower += 0x20; 635 else if (code >= 0xff41 && code <= 0xff5a) 636 *upper -= 0x20; 637 /* Deseret, U+10400 to U+104FF */ 638 else if (code >= 0x10400 && code <= 0x10427) 639 *lower += 0x28; 640 else if (code >= 0x10428 && code <= 0x1044f) 641 *upper -= 0x28; 642} 643 644void 645XConvertCase( 646 register KeySym sym, 647 KeySym *lower, 648 KeySym *upper) 649{ 650 /* Latin 1 keysym */ 651 if (sym < 0x100) { 652 UCSConvertCase(sym, lower, upper); 653 return; 654 } 655 656 /* Unicode keysym */ 657 if ((sym & 0xff000000) == 0x01000000) { 658 UCSConvertCase((sym & 0x00ffffff), lower, upper); 659 *upper |= 0x01000000; 660 *lower |= 0x01000000; 661 return; 662 } 663 664 /* Legacy keysym */ 665 666 *lower = sym; 667 *upper = sym; 668 669 switch(sym >> 8) { 670 case 1: /* Latin 2 */ 671 /* Assume the KeySym is a legal value (ignore discontinuities) */ 672 if (sym == XK_Aogonek) 673 *lower = XK_aogonek; 674 else if (sym >= XK_Lstroke && sym <= XK_Sacute) 675 *lower += (XK_lstroke - XK_Lstroke); 676 else if (sym >= XK_Scaron && sym <= XK_Zacute) 677 *lower += (XK_scaron - XK_Scaron); 678 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) 679 *lower += (XK_zcaron - XK_Zcaron); 680 else if (sym == XK_aogonek) 681 *upper = XK_Aogonek; 682 else if (sym >= XK_lstroke && sym <= XK_sacute) 683 *upper -= (XK_lstroke - XK_Lstroke); 684 else if (sym >= XK_scaron && sym <= XK_zacute) 685 *upper -= (XK_scaron - XK_Scaron); 686 else if (sym >= XK_zcaron && sym <= XK_zabovedot) 687 *upper -= (XK_zcaron - XK_Zcaron); 688 else if (sym >= XK_Racute && sym <= XK_Tcedilla) 689 *lower += (XK_racute - XK_Racute); 690 else if (sym >= XK_racute && sym <= XK_tcedilla) 691 *upper -= (XK_racute - XK_Racute); 692 break; 693 case 2: /* Latin 3 */ 694 /* Assume the KeySym is a legal value (ignore discontinuities) */ 695 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) 696 *lower += (XK_hstroke - XK_Hstroke); 697 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) 698 *lower += (XK_gbreve - XK_Gbreve); 699 else if (sym >= XK_hstroke && sym <= XK_hcircumflex) 700 *upper -= (XK_hstroke - XK_Hstroke); 701 else if (sym >= XK_gbreve && sym <= XK_jcircumflex) 702 *upper -= (XK_gbreve - XK_Gbreve); 703 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) 704 *lower += (XK_cabovedot - XK_Cabovedot); 705 else if (sym >= XK_cabovedot && sym <= XK_scircumflex) 706 *upper -= (XK_cabovedot - XK_Cabovedot); 707 break; 708 case 3: /* Latin 4 */ 709 /* Assume the KeySym is a legal value (ignore discontinuities) */ 710 if (sym >= XK_Rcedilla && sym <= XK_Tslash) 711 *lower += (XK_rcedilla - XK_Rcedilla); 712 else if (sym >= XK_rcedilla && sym <= XK_tslash) 713 *upper -= (XK_rcedilla - XK_Rcedilla); 714 else if (sym == XK_ENG) 715 *lower = XK_eng; 716 else if (sym == XK_eng) 717 *upper = XK_ENG; 718 else if (sym >= XK_Amacron && sym <= XK_Umacron) 719 *lower += (XK_amacron - XK_Amacron); 720 else if (sym >= XK_amacron && sym <= XK_umacron) 721 *upper -= (XK_amacron - XK_Amacron); 722 break; 723 case 6: /* Cyrillic */ 724 /* Assume the KeySym is a legal value (ignore discontinuities) */ 725 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) 726 *lower -= (XK_Serbian_DJE - XK_Serbian_dje); 727 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) 728 *upper += (XK_Serbian_DJE - XK_Serbian_dje); 729 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) 730 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); 731 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) 732 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); 733 break; 734 case 7: /* Greek */ 735 /* Assume the KeySym is a legal value (ignore discontinuities) */ 736 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) 737 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 738 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && 739 sym != XK_Greek_iotaaccentdieresis && 740 sym != XK_Greek_upsilonaccentdieresis) 741 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); 742 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) 743 *lower += (XK_Greek_alpha - XK_Greek_ALPHA); 744 else if (sym == XK_Greek_finalsmallsigma) 745 *upper = XK_Greek_SIGMA; 746 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega) 747 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); 748 break; 749 case 0x13: /* Latin 9 */ 750 if (sym == XK_OE) 751 *lower = XK_oe; 752 else if (sym == XK_oe) 753 *upper = XK_OE; 754 else if (sym == XK_Ydiaeresis) 755 *lower = XK_ydiaeresis; 756 break; 757 } 758} 759 760int 761_XTranslateKey( register Display *dpy, 762 KeyCode keycode, 763 register unsigned int modifiers, 764 unsigned int *modifiers_return, 765 KeySym *keysym_return) 766{ 767 int per; 768 register KeySym *syms; 769 KeySym sym, lsym, usym; 770 771 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) 772 return 0; 773 *modifiers_return = ((ShiftMask|LockMask) 774 | dpy->mode_switch | dpy->num_lock); 775 if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) 776 { 777 *keysym_return = NoSymbol; 778 return 1; 779 } 780 per = dpy->keysyms_per_keycode; 781 syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; 782 while ((per > 2) && (syms[per - 1] == NoSymbol)) 783 per--; 784 if ((per > 2) && (modifiers & dpy->mode_switch)) { 785 syms += 2; 786 per -= 2; 787 } 788 if ((modifiers & dpy->num_lock) && 789 (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { 790 if ((modifiers & ShiftMask) || 791 ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock))) 792 *keysym_return = syms[0]; 793 else 794 *keysym_return = syms[1]; 795 } else if (!(modifiers & ShiftMask) && 796 (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) { 797 if ((per == 1) || (syms[1] == NoSymbol)) 798 XConvertCase(syms[0], keysym_return, &usym); 799 else 800 *keysym_return = syms[0]; 801 } else if (!(modifiers & LockMask) || 802 (dpy->lock_meaning != XK_Caps_Lock)) { 803 if ((per == 1) || ((usym = syms[1]) == NoSymbol)) 804 XConvertCase(syms[0], &lsym, &usym); 805 *keysym_return = usym; 806 } else { 807 if ((per == 1) || ((sym = syms[1]) == NoSymbol)) 808 sym = syms[0]; 809 XConvertCase(sym, &lsym, &usym); 810 if (!(modifiers & ShiftMask) && (sym != syms[0]) && 811 ((sym != usym) || (lsym == usym))) 812 XConvertCase(syms[0], &lsym, &usym); 813 *keysym_return = usym; 814 } 815 if (*keysym_return == XK_VoidSymbol) 816 *keysym_return = NoSymbol; 817 return 1; 818} 819 820int 821_XTranslateKeySym( 822 Display *dpy, 823 register KeySym symbol, 824 unsigned int modifiers, 825 char *buffer, 826 int nbytes) 827{ 828 register struct _XKeytrans *p; 829 int length; 830 unsigned long hiBytes; 831 register unsigned char c; 832 833 if (!symbol) 834 return 0; 835 /* see if symbol rebound, if so, return that string. */ 836 for (p = dpy->key_bindings; p; p = p->next) { 837 if (((modifiers & AllMods) == p->state) && (symbol == p->key)) { 838 length = p->len; 839 if (length > nbytes) length = nbytes; 840 memcpy (buffer, p->string, (size_t) length); 841 return length; 842 } 843 } 844 /* try to convert to Latin-1, handling control */ 845 hiBytes = symbol >> 8; 846 if (!(nbytes && 847 ((hiBytes == 0) || 848 ((hiBytes == 0xFF) && 849 (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) || 850 (symbol == XK_Return) || 851 (symbol == XK_Escape) || 852 (symbol == XK_KP_Space) || 853 (symbol == XK_KP_Tab) || 854 (symbol == XK_KP_Enter) || 855 ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) || 856 (symbol == XK_KP_Equal) || 857 (symbol == XK_Delete)))))) 858 return 0; 859 860 /* if X keysym, convert to ascii by grabbing low 7 bits */ 861 if (symbol == XK_KP_Space) 862 c = XK_space & 0x7F; /* patch encoding botch */ 863 else if (hiBytes == 0xFF) 864 c = symbol & 0x7F; 865 else 866 c = symbol & 0xFF; 867 /* only apply Control key if it makes sense, else ignore it */ 868 if (modifiers & ControlMask) { 869 if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; 870 else if (c == '2') c = '\000'; 871 else if (c >= '3' && c <= '7') c -= ('3' - '\033'); 872 else if (c == '8') c = '\177'; 873 else if (c == '/') c = '_' & 0x1F; 874 } 875 buffer[0] = c; 876 return 1; 877} 878 879/*ARGSUSED*/ 880int 881XLookupString ( 882 register XKeyEvent *event, 883 char *buffer, /* buffer */ 884 int nbytes, /* space in buffer for characters */ 885 KeySym *keysym, 886 XComposeStatus *status) /* not implemented */ 887{ 888 unsigned int modifiers; 889 KeySym symbol; 890 891 if (! _XTranslateKey(event->display, event->keycode, event->state, 892 &modifiers, &symbol)) 893 return 0; 894 895 if (keysym) 896 *keysym = symbol; 897 /* arguable whether to use (event->state & ~modifiers) here */ 898 return _XTranslateKeySym(event->display, symbol, event->state, 899 buffer, nbytes); 900} 901 902static void 903_XFreeKeyBindings( 904 Display *dpy) 905{ 906 register struct _XKeytrans *p, *np; 907 908 for (p = dpy->key_bindings; p; p = np) { 909 np = p->next; 910 Xfree(p->string); 911 Xfree(p->modifiers); 912 Xfree(p); 913 } 914 dpy->key_bindings = NULL; 915} 916 917int 918XRebindKeysym ( 919 Display *dpy, 920 KeySym keysym, 921 KeySym *mlist, 922 int nm, /* number of modifiers in mlist */ 923 _Xconst unsigned char *str, 924 int nbytes) 925{ 926 register struct _XKeytrans *tmp, *p; 927 int nb; 928 929 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) 930 return 0; 931 LockDisplay(dpy); 932 tmp = dpy->key_bindings; 933 nb = sizeof(KeySym) * nm; 934 935 if ((! (p = Xcalloc( 1, sizeof(struct _XKeytrans)))) || 936 ((! (p->string = Xmalloc(nbytes))) && (nbytes > 0)) || 937 ((! (p->modifiers = Xmalloc(nb))) && (nb > 0))) { 938 if (p) { 939 Xfree(p->string); 940 Xfree(p->modifiers); 941 Xfree(p); 942 } 943 UnlockDisplay(dpy); 944 return 0; 945 } 946 947 dpy->key_bindings = p; 948 dpy->free_funcs->key_bindings = _XFreeKeyBindings; 949 p->next = tmp; /* chain onto list */ 950 memcpy (p->string, str, (size_t) nbytes); 951 p->len = nbytes; 952 memcpy ((char *) p->modifiers, (char *) mlist, (size_t) nb); 953 p->key = keysym; 954 p->mlen = nm; 955 ComputeMaskFromKeytrans(dpy, p); 956 UnlockDisplay(dpy); 957 return 0; 958} 959 960unsigned 961_XKeysymToModifiers( 962 Display *dpy, 963 KeySym ks) 964{ 965 CARD8 code,mods; 966 register KeySym *kmax; 967 register KeySym *k; 968 register XModifierKeymap *m; 969 970 if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) 971 return 0; 972 kmax = dpy->keysyms + 973 (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode; 974 k = dpy->keysyms; 975 m = dpy->modifiermap; 976 mods= 0; 977 while (k<kmax) { 978 if (*k == ks ) { 979 register int j = m->max_keypermod<<3; 980 981 code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode); 982 983 while (--j >= 0) { 984 if (code == m->modifiermap[j]) 985 mods|= (1<<(j/m->max_keypermod)); 986 } 987 } 988 k++; 989 } 990 return mods; 991} 992 993/* 994 * given a list of modifiers, computes the mask necessary for later matching. 995 * This routine must lookup the key in the Keymap and then search to see 996 * what modifier it is bound to, if any. Sets the AnyModifier bit if it 997 * can't map some keysym to a modifier. 998 */ 999static void 1000ComputeMaskFromKeytrans( 1001 Display *dpy, 1002 register struct _XKeytrans *p) 1003{ 1004 register int i; 1005 1006 p->state = AnyModifier; 1007 for (i = 0; i < p->mlen; i++) { 1008 p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]); 1009 } 1010 p->state &= AllMods; 1011} 1012