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