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