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