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