XKBBind.c revision 5efbdfc3
1/* 2 3Copyright 1985, 1987, 1994, 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 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29 /* the new monsters ate the old ones */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34#include "XKBlib.h" 35#include <X11/Xlibint.h> 36#include <X11/Xutil.h> 37#include <X11/keysym.h> 38#include <stdio.h> 39#include <ctype.h> 40 41#include <X11/extensions/XKBproto.h> 42#include "XKBlibint.h" 43 44#define AllMods (ShiftMask|LockMask|ControlMask| \ 45 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 46 47static int _XkbLoadDpy(Display *dpy); 48 49struct _XKeytrans { 50 struct _XKeytrans *next; /* next on list */ 51 char *string; /* string to return when the time comes */ 52 int len; /* length of string (since NULL is legit) */ 53 KeySym key; /* keysym rebound */ 54 unsigned int state; /* modifier state */ 55 KeySym *modifiers; /* modifier keysyms you want */ 56 int mlen; /* length of modifier list */ 57}; 58 59KeySym 60XkbKeycodeToKeysym(Display *dpy, 61#if NeedWidePrototypes 62 unsigned int kc, 63#else 64 KeyCode kc, 65#endif 66 int group, 67 int level) 68{ 69 XkbDescRec *xkb; 70 71 if (_XkbUnavailable(dpy)) 72 return NoSymbol; 73 74 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 75 76 xkb = dpy->xkb_info->desc; 77 if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 78 return NoSymbol; 79 80 if ((group < 0) || (level < 0) || (group >= XkbKeyNumGroups(xkb, kc))) 81 return NoSymbol; 82 if (level >= XkbKeyGroupWidth(xkb, kc, group)) { 83 /* for compatibility with the core protocol, _always_ allow */ 84 /* two symbols in the first two groups. If either of the */ 85 /* two is of type ONE_LEVEL, just replicate the first symbol */ 86 if ((group > XkbGroup2Index) || (XkbKeyGroupWidth(xkb, kc, group) != 1) 87 || (level != 1)) { 88 return NoSymbol; 89 } 90 level = 0; 91 } 92 return XkbKeySymEntry(xkb, kc, level, group); 93} 94 95KeySym 96XKeycodeToKeysym(Display *dpy, 97#if NeedWidePrototypes 98 unsigned int kc, 99#else 100 KeyCode kc, 101#endif 102 int col) 103{ 104 XkbDescRec *xkb; 105 106 if (_XkbUnavailable(dpy)) 107 return _XKeycodeToKeysym(dpy, kc, col); 108 109 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 110 111 xkb = dpy->xkb_info->desc; 112 if ((kc < xkb->min_key_code) || (kc > xkb->max_key_code)) 113 return NoSymbol; 114 115 if (col > 3) { 116 int firstSym, nGrp, grp; 117 118 firstSym = 4; 119 nGrp = XkbKeyNumGroups(xkb, kc); 120 for (grp = 0; grp < nGrp; grp++) { 121 int width = XkbKeyGroupWidth(xkb, kc, grp); 122 int skip = 0; 123 if (grp < 2) { 124 /* Skip the first two symbols in the first two groups, since we 125 * return them below for indexes 0-3. */ 126 skip = 2; 127 width -= skip; 128 if (width < 0) 129 width = 0; 130 } 131 if (col < firstSym + width) 132 return XkbKeycodeToKeysym(dpy, kc, grp, col - firstSym + skip); 133 firstSym += width; 134 } 135 return NoSymbol; 136 } 137 return XkbKeycodeToKeysym(dpy, kc, (col >> 1), (col & 1)); 138} 139 140KeyCode 141XKeysymToKeycode(Display *dpy, KeySym ks) 142{ 143 register int i, j, gotOne; 144 145 if (_XkbUnavailable(dpy)) 146 return _XKeysymToKeycode(dpy, ks); 147 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 148 149 j = 0; 150 do { 151 register XkbDescRec *xkb = dpy->xkb_info->desc; 152 gotOne = 0; 153 for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { 154 if (j < (int) XkbKeyNumSyms(xkb, i)) { 155 gotOne = 1; 156 if ((XkbKeySym(xkb, i, j) == ks)) 157 return i; 158 } 159 } 160 j++; 161 } while (gotOne); 162 return 0; 163} 164 165static int 166_XkbComputeModmap(Display *dpy) 167{ 168 register XkbDescPtr xkb; 169 170 xkb = dpy->xkb_info->desc; 171 if (XkbGetUpdatedMap(dpy, XkbModifierMapMask, xkb) == Success) 172 return 1; 173 return 0; 174} 175 176unsigned 177XkbKeysymToModifiers(Display *dpy, KeySym ks) 178{ 179 XkbDescRec *xkb; 180 register int i, j; 181 register KeySym *pSyms; 182 CARD8 mods; 183 184 if (_XkbUnavailable(dpy)) 185 return _XKeysymToModifiers(dpy, ks); 186 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 187 188 if (_XkbNeedModmap(dpy->xkb_info) && (!_XkbComputeModmap(dpy))) 189 return _XKeysymToModifiers(dpy, ks); 190 191 xkb = dpy->xkb_info->desc; 192 mods = 0; 193 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 194 pSyms = XkbKeySymsPtr(xkb, i); 195 for (j = XkbKeyNumSyms(xkb, i) - 1; j >= 0; j--) { 196 if (pSyms[j] == ks) { 197 mods |= xkb->map->modmap[i]; 198 break; 199 } 200 } 201 } 202 return mods; 203} 204 205KeySym 206XLookupKeysym(register XKeyEvent * event, int col) 207{ 208 Display *dpy = event->display; 209 210 if (_XkbUnavailable(dpy)) 211 return _XLookupKeysym(event, col); 212 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 213 214#ifdef __clang__ 215#pragma clang diagnostic push 216#pragma clang diagnostic ignored "-Wdeprecated-declarations" 217#elif defined(__GNUC__) 218#pragma GCC diagnostic push 219#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 220#endif 221 return XKeycodeToKeysym(dpy, event->keycode, col); 222#ifdef __clang__ 223#pragma clang diagnostic pop 224#elif defined(__GNUC__) 225#pragma GCC diagnostic pop 226#endif 227 228} 229 230 /* 231 * Not a public entry point -- XkbTranslateKey is an obsolete name 232 * that is preserved here so that functions linked against the old 233 * version will continue to work in a shared library environment. 234 */ 235int 236XkbTranslateKey(register Display *dpy, 237 KeyCode key, 238 register unsigned int mods, 239 unsigned int *mods_rtrn, 240 KeySym *keysym_rtrn); 241 242int 243XkbTranslateKey(register Display *dpy, 244 KeyCode key, 245 register unsigned int mods, 246 unsigned int *mods_rtrn, 247 KeySym *keysym_rtrn) 248{ 249 return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 250} 251 252Bool 253XkbLookupKeySym(register Display *dpy, 254 KeyCode key, 255 register unsigned int mods, 256 unsigned int *mods_rtrn, 257 KeySym *keysym_rtrn) 258{ 259 if (_XkbUnavailable(dpy)) 260 return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 261 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 262 return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 263 keysym_rtrn); 264} 265 266Bool 267XkbTranslateKeyCode(register XkbDescPtr xkb, 268 KeyCode key, 269 register unsigned int mods, 270 unsigned int *mods_rtrn, 271 KeySym *keysym_rtrn) 272{ 273 XkbKeyTypeRec *type; 274 int col, nKeyGroups; 275 unsigned preserve, effectiveGroup; 276 KeySym *syms; 277 278 if (mods_rtrn != NULL) 279 *mods_rtrn = 0; 280 281 nKeyGroups = XkbKeyNumGroups(xkb, key); 282 if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 283 if (keysym_rtrn != NULL) 284 *keysym_rtrn = NoSymbol; 285 return False; 286 } 287 288 syms = XkbKeySymsPtr(xkb, key); 289 290 /* find the offset of the effective group */ 291 col = 0; 292 effectiveGroup = XkbGroupForCoreState(mods); 293 if (effectiveGroup >= nKeyGroups) { 294 unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 295 296 switch (XkbOutOfRangeGroupAction(groupInfo)) { 297 default: 298 effectiveGroup %= nKeyGroups; 299 break; 300 case XkbClampIntoRange: 301 effectiveGroup = nKeyGroups - 1; 302 break; 303 case XkbRedirectIntoRange: 304 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 305 if (effectiveGroup >= nKeyGroups) 306 effectiveGroup = 0; 307 break; 308 } 309 } 310 col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 311 type = XkbKeyKeyType(xkb, key, effectiveGroup); 312 313 preserve = 0; 314 if (type->map) { /* find the column (shift level) within the group */ 315 register int i; 316 register XkbKTMapEntryPtr entry; 317 318 for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 319 if ((entry->active) && 320 ((mods & type->mods.mask) == entry->mods.mask)) { 321 col += entry->level; 322 if (type->preserve) 323 preserve = type->preserve[i].mask; 324 break; 325 } 326 } 327 } 328 329 if (keysym_rtrn != NULL) 330 *keysym_rtrn = syms[col]; 331 if (mods_rtrn) { 332 *mods_rtrn = type->mods.mask & (~preserve); 333 /* The Motif VTS doesn't get the help callback called if help 334 * is bound to Shift+<whatever>, and it appears as though it 335 * is XkbTranslateKeyCode that is causing the problem. The 336 * core X version of XTranslateKey always OR's in ShiftMask 337 * and LockMask for mods_rtrn, so this "fix" keeps this behavior 338 * and solves the VTS problem. 339 */ 340 if ((xkb->dpy) && (xkb->dpy->xkb_info) && 341 (xkb->dpy->xkb_info-> 342 xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 343 *mods_rtrn |= (ShiftMask | LockMask); 344 } 345 } 346 return (syms[col] != NoSymbol); 347} 348 349Status 350XkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 351{ 352 Display *dpy = event->display; 353 XkbInfoPtr xkbi; 354 355 if (_XkbUnavailable(dpy)) { 356 _XRefreshKeyboardMapping((XMappingEvent *) event); 357 return Success; 358 } 359 xkbi = dpy->xkb_info; 360 361 if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 362 return BadMatch; 363 if (event->xkb_type == XkbNewKeyboardNotify) { 364 _XkbReloadDpy(dpy); 365 return Success; 366 } 367 if (event->xkb_type == XkbMapNotify) { 368 XkbMapChangesRec changes; 369 Status rtrn; 370 371 if (xkbi->flags & XkbMapPending) 372 changes = xkbi->changes; 373 else 374 bzero(&changes, sizeof(changes)); 375 XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 376 if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 377#ifdef DEBUG 378 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 379#endif 380 xkbi->changes = changes; 381 } 382 else if (xkbi->flags & XkbMapPending) { 383 xkbi->flags &= ~XkbMapPending; 384 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 385 } 386 return rtrn; 387 } 388 return BadMatch; 389} 390 391int 392XRefreshKeyboardMapping(register XMappingEvent * event) 393{ 394 XkbEvent *xkbevent = (XkbEvent *) event; 395 Display *dpy = event->display; 396 XkbMapChangesRec changes; 397 XkbInfoPtr xkbi; 398 399 /* always do this for input methods, which still use the old keymap */ 400 (void) _XRefreshKeyboardMapping(event); 401 402 if (_XkbUnavailable(dpy)) 403 return 1; 404 405 xkbi = dpy->xkb_info; 406 407 if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 408 return XkbRefreshKeyboardMapping(&xkbevent->map); 409 410 if (xkbi->flags & XkbXlibNewKeyboard) { 411 _XkbReloadDpy(dpy); 412 return 1; 413 } 414 415 if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 416 if (xkbi->flags & XkbMapPending) { 417 changes = xkbi->changes; 418 _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 419 } 420 else { 421 bzero(&changes, sizeof(changes)); 422 changes.changed = XkbKeySymsMask; 423 if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 424 changes.first_key_sym = xkbi->desc->min_key_code; 425 changes.num_key_syms = xkbi->desc->max_key_code - 426 xkbi->desc->min_key_code + 1; 427 } 428 else { 429 changes.first_key_sym = event->first_keycode; 430 changes.num_key_syms = event->count; 431 } 432 } 433 434 if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 435#ifdef DEBUG 436 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 437 if (changes.changed & XkbKeyTypesMask) { 438 int first = changes.first_type; 439 int last = changes.first_type + changes.num_types - 1; 440 441 fprintf(stderr, " types: %d..%d\n", first, last); 442 } 443 if (changes.changed & XkbKeySymsMask) { 444 int first = changes.first_key_sym; 445 int last = changes.first_key_sym + changes.num_key_syms - 1; 446 447 fprintf(stderr, " symbols: %d..%d\n", first, last); 448 } 449 if (changes.changed & XkbKeyActionsMask) { 450 int first = changes.first_key_act; 451 int last = changes.first_key_act + changes.num_key_acts - 1; 452 453 fprintf(stderr, " acts: %d..%d\n", first, last); 454 } 455 if (changes.changed & XkbKeyBehaviorsMask) { 456 int first = changes.first_key_behavior; 457 int last = first + changes.num_key_behaviors - 1; 458 459 fprintf(stderr, " behaviors: %d..%d\n", first, last); 460 } 461 if (changes.changed & XkbVirtualModsMask) { 462 fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 463 } 464 if (changes.changed & XkbExplicitComponentsMask) { 465 int first = changes.first_key_explicit; 466 int last = first + changes.num_key_explicit - 1; 467 468 fprintf(stderr, " explicit: %d..%d\n", first, last); 469 } 470#endif 471 } 472 LockDisplay(dpy); 473 if (xkbi->flags & XkbMapPending) { 474 xkbi->flags &= ~XkbMapPending; 475 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 476 } 477 UnlockDisplay(dpy); 478 } 479 if (event->request == MappingModifier) { 480 LockDisplay(dpy); 481 if (xkbi->desc->map->modmap) { 482 _XkbFree(xkbi->desc->map->modmap); 483 xkbi->desc->map->modmap = NULL; 484 } 485 if (dpy->key_bindings) { 486 register struct _XKeytrans *p; 487 488 for (p = dpy->key_bindings; p; p = p->next) { 489 register int i; 490 491 p->state = 0; 492 if (p->mlen > 0) { 493 for (i = 0; i < p->mlen; i++) { 494 p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 495 } 496 if (p->state) 497 p->state &= AllMods; 498 else 499 p->state = AnyModifier; 500 } 501 } 502 } 503 UnlockDisplay(dpy); 504 } 505 return 1; 506} 507 508static int 509_XkbLoadDpy(Display *dpy) 510{ 511 XkbInfoPtr xkbi; 512 unsigned query, oldEvents; 513 XkbDescRec *desc; 514 515 if (!XkbUseExtension(dpy, NULL, NULL)) 516 return 0; 517 518 xkbi = dpy->xkb_info; 519 query = XkbAllClientInfoMask; 520 desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 521 if (!desc) { 522#ifdef DEBUG 523 fprintf(stderr, "Warning! XkbGetMap failed!\n"); 524#endif 525 return 0; 526 } 527 LockDisplay(dpy); 528 xkbi->desc = desc; 529 530 UnlockDisplay(dpy); 531 oldEvents = xkbi->selected_events; 532 if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 533 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 534 XkbNewKeyboardNotify, 535 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 536 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 537 } 538 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 539 XkbAllClientInfoMask, XkbAllClientInfoMask); 540 LockDisplay(dpy); 541 xkbi->selected_events = oldEvents; 542 UnlockDisplay(dpy); 543 return 1; 544} 545 546void 547_XkbReloadDpy(Display *dpy) 548{ 549 XkbInfoPtr xkbi; 550 XkbDescRec *desc; 551 unsigned oldDeviceID; 552 553 if (_XkbUnavailable(dpy)) 554 return; 555 556 xkbi = dpy->xkb_info; 557 LockDisplay(dpy); 558 if (xkbi->desc) { 559 oldDeviceID = xkbi->desc->device_spec; 560 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 561 xkbi->desc = NULL; 562 xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 563 xkbi->changes.changed = 0; 564 } 565 else 566 oldDeviceID = XkbUseCoreKbd; 567 UnlockDisplay(dpy); 568 desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 569 if (!desc) 570 return; 571 LockDisplay(dpy); 572 xkbi->desc = desc; 573 UnlockDisplay(dpy); 574 575 if (desc->device_spec != oldDeviceID) { 576 /* transfer(?) event masks here */ 577#ifdef NOTYET 578 unsigned oldEvents; 579 580 oldEvents = xkbi->selected_events; 581 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 582 XkbAllMapComponentsMask, XkbAllClientInfoMask); 583 LockDisplay(dpy); 584 xkbi->selected_events = oldEvents; 585 UnlockDisplay(dpy); 586#endif 587 } 588 return; 589} 590 591int 592XkbTranslateKeySym(Display *dpy, 593 KeySym *sym_rtrn, 594 unsigned int mods, 595 char *buffer, 596 int nbytes, 597 int *extra_rtrn) 598{ 599 register XkbInfoPtr xkb; 600 XkbKSToMBFunc cvtr; 601 XPointer priv; 602 char tmp[4]; 603 int n; 604 605 xkb = dpy->xkb_info; 606 if (!xkb->cvt.KSToMB) { 607 _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 608 _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 609 } 610 611 if (extra_rtrn) 612 *extra_rtrn = 0; 613 614 if ((buffer == NULL) || (nbytes == 0)) { 615 buffer = tmp; 616 nbytes = 4; 617 } 618 619 /* see if symbol rebound, if so, return that string. */ 620 n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 621 if (n) 622 return n; 623 624 if (nbytes > 0) 625 buffer[0] = '\0'; 626 627 if (xkb->cvt.KSToUpper && (mods & LockMask)) { 628 *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 629 } 630 if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 631 cvtr = xkb->latin1cvt.KSToMB; 632 priv = xkb->latin1cvt.KSToMBPriv; 633 } 634 else { 635 cvtr = xkb->cvt.KSToMB; 636 priv = xkb->cvt.KSToMBPriv; 637 } 638 639 n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 640 641 if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 642 register int i; 643 int change; 644 645 for (i = change = 0; i < n; i++) { 646 char ch = toupper(buffer[i]); 647 change = (change || (buffer[i] != ch)); 648 buffer[i] = ch; 649 } 650 if (change) { 651 if (n == 1) 652 *sym_rtrn = 653 (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 654 else 655 *sym_rtrn = NoSymbol; 656 } 657 } 658 659 if (mods & ControlMask) { 660 if (n == 1) { 661 buffer[0] = XkbToControl(buffer[0]); 662 if (nbytes > 1) 663 buffer[1] = '\0'; 664 return 1; 665 } 666 if (nbytes > 0) 667 buffer[0] = '\0'; 668 return 0; 669 } 670 return n; 671} 672 673int 674XLookupString(register XKeyEvent *event, 675 char *buffer, 676 int nbytes, 677 KeySym *keysym, 678 XComposeStatus *status) 679{ 680 KeySym dummy; 681 int rtrnLen; 682 unsigned int new_mods; 683 Display *dpy = event->display; 684 685 if (keysym == NULL) 686 keysym = &dummy; 687 if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 688 return 0; 689 new_mods = (event->state & (~new_mods)); 690 691 /* find the group where a symbol can be converted to control one */ 692 if (new_mods & ControlMask && *keysym > 0x7F && 693 (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 694 XKeyEvent tmp_ev = *event; 695 KeySym tmp_keysym; 696 unsigned int tmp_new_mods; 697 698 if (_XkbUnavailable(dpy)) { 699 tmp_ev.state = event->state ^ dpy->mode_switch; 700 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 701 &tmp_new_mods, &tmp_keysym) && 702 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 703 *keysym = tmp_keysym; 704 } 705 } 706 else { 707 int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 708 int i; 709 710 for (i = 0; i < n; i++) { 711 if (XkbGroupForCoreState(event->state) == i) 712 continue; 713 tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 714 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 715 &tmp_new_mods, &tmp_keysym) && 716 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 717 *keysym = tmp_keysym; 718 new_mods = (event->state & (~tmp_new_mods)); 719 break; 720 } 721 } 722 } 723 } 724 725 /* We *should* use the new_mods (which does not contain any modifiers */ 726 /* that were used to compute the symbol here, but pre-XKB XLookupString */ 727 /* did not and we have to remain compatible. Sigh. */ 728 if (_XkbUnavailable(dpy) || 729 (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 730 new_mods = event->state; 731 732 rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 733 if (rtrnLen > 0) 734 return rtrnLen; 735 736 return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 737} 738 739 740int 741XkbLookupKeyBinding(Display *dpy, 742 register KeySym sym, 743 unsigned int mods, 744 char *buffer, 745 int nbytes, 746 int *extra_rtrn) 747{ 748 register struct _XKeytrans *p; 749 750 if (extra_rtrn) 751 *extra_rtrn = 0; 752 for (p = dpy->key_bindings; p; p = p->next) { 753 if (((mods & AllMods) == p->state) && (sym == p->key)) { 754 int tmp = p->len; 755 756 if (tmp > nbytes) { 757 if (extra_rtrn) 758 *extra_rtrn = (tmp - nbytes); 759 tmp = nbytes; 760 } 761 memcpy(buffer, p->string, (size_t) tmp); 762 if (tmp < nbytes) 763 buffer[tmp] = '\0'; 764 return tmp; 765 } 766 } 767 return 0; 768} 769 770char 771XkbToControl(char ch) 772{ 773 register char c = ch; 774 775 if ((c >= '@' && c < '\177') || c == ' ') 776 c &= 0x1F; 777 else if (c == '2') 778 c = '\000'; 779 else if (c >= '3' && c <= '7') 780 c -= ('3' - '\033'); 781 else if (c == '8') 782 c = '\177'; 783 else if (c == '/') 784 c = '_' & 0x1F; 785 return c; 786} 787