XKBBind.c revision 507fd43f
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 205#ifdef __clang__ 206#pragma clang diagnostic push 207#pragma clang diagnostic ignored "-Wdeprecated-declarations" 208#elif defined(__GNUC__) 209#pragma GCC diagnostic push 210#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 211#endif 212 213KeySym 214XLookupKeysym(register XKeyEvent * event, int col) 215{ 216 Display *dpy = event->display; 217 218 if (_XkbUnavailable(dpy)) 219 return _XLookupKeysym(event, col); 220 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 221 222 return XKeycodeToKeysym(dpy, event->keycode, col); 223} 224 225#ifdef __clang__ 226#pragma clang diagnostic pop 227#elif defined(__GNUC__) 228#pragma GCC diagnostic pop 229#endif 230 231 /* 232 * Not a public entry point -- XkbTranslateKey is an obsolete name 233 * that is preserved here so that functions linked against the old 234 * version will continue to work in a shared library environment. 235 */ 236int 237XkbTranslateKey(register Display *dpy, 238 KeyCode key, 239 register unsigned int mods, 240 unsigned int *mods_rtrn, 241 KeySym *keysym_rtrn); 242 243int 244XkbTranslateKey(register Display *dpy, 245 KeyCode key, 246 register unsigned int mods, 247 unsigned int *mods_rtrn, 248 KeySym *keysym_rtrn) 249{ 250 return XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn); 251} 252 253Bool 254XkbLookupKeySym(register Display *dpy, 255 KeyCode key, 256 register unsigned int mods, 257 unsigned int *mods_rtrn, 258 KeySym *keysym_rtrn) 259{ 260 if (_XkbUnavailable(dpy)) 261 return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); 262 _XkbCheckPendingRefresh(dpy, dpy->xkb_info); 263 return XkbTranslateKeyCode(dpy->xkb_info->desc, key, mods, mods_rtrn, 264 keysym_rtrn); 265} 266 267Bool 268XkbTranslateKeyCode(register XkbDescPtr xkb, 269 KeyCode key, 270 register unsigned int mods, 271 unsigned int *mods_rtrn, 272 KeySym *keysym_rtrn) 273{ 274 XkbKeyTypeRec *type; 275 int col, nKeyGroups; 276 unsigned preserve, effectiveGroup; 277 KeySym *syms; 278 279 if (mods_rtrn != NULL) 280 *mods_rtrn = 0; 281 282 nKeyGroups = XkbKeyNumGroups(xkb, key); 283 if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { 284 if (keysym_rtrn != NULL) 285 *keysym_rtrn = NoSymbol; 286 return False; 287 } 288 289 syms = XkbKeySymsPtr(xkb, key); 290 291 /* find the offset of the effective group */ 292 col = 0; 293 effectiveGroup = XkbGroupForCoreState(mods); 294 if (effectiveGroup >= nKeyGroups) { 295 unsigned groupInfo = XkbKeyGroupInfo(xkb, key); 296 297 switch (XkbOutOfRangeGroupAction(groupInfo)) { 298 default: 299 effectiveGroup %= nKeyGroups; 300 break; 301 case XkbClampIntoRange: 302 effectiveGroup = nKeyGroups - 1; 303 break; 304 case XkbRedirectIntoRange: 305 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); 306 if (effectiveGroup >= nKeyGroups) 307 effectiveGroup = 0; 308 break; 309 } 310 } 311 col = effectiveGroup * XkbKeyGroupsWidth(xkb, key); 312 type = XkbKeyKeyType(xkb, key, effectiveGroup); 313 314 preserve = 0; 315 if (type->map) { /* find the column (shift level) within the group */ 316 register int i; 317 register XkbKTMapEntryPtr entry; 318 319 for (i = 0, entry = type->map; i < type->map_count; i++, entry++) { 320 if ((entry->active) && 321 ((mods & type->mods.mask) == entry->mods.mask)) { 322 col += entry->level; 323 if (type->preserve) 324 preserve = type->preserve[i].mask; 325 break; 326 } 327 } 328 } 329 330 if (keysym_rtrn != NULL) 331 *keysym_rtrn = syms[col]; 332 if (mods_rtrn) { 333 *mods_rtrn = type->mods.mask & (~preserve); 334 /* The Motif VTS doesn't get the help callback called if help 335 * is bound to Shift+<whatever>, and it appears as though it 336 * is XkbTranslateKeyCode that is causing the problem. The 337 * core X version of XTranslateKey always OR's in ShiftMask 338 * and LockMask for mods_rtrn, so this "fix" keeps this behavior 339 * and solves the VTS problem. 340 */ 341 if ((xkb->dpy) && (xkb->dpy->xkb_info) && 342 (xkb->dpy->xkb_info-> 343 xlib_ctrls & XkbLC_AlwaysConsumeShiftAndLock)) { 344 *mods_rtrn |= (ShiftMask | LockMask); 345 } 346 } 347 return (syms[col] != NoSymbol); 348} 349 350Status 351XkbRefreshKeyboardMapping(register XkbMapNotifyEvent * event) 352{ 353 Display *dpy = event->display; 354 XkbInfoPtr xkbi; 355 356 if (_XkbUnavailable(dpy)) { 357 _XRefreshKeyboardMapping((XMappingEvent *) event); 358 return Success; 359 } 360 xkbi = dpy->xkb_info; 361 362 if (((event->type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 363 return BadMatch; 364 if (event->xkb_type == XkbNewKeyboardNotify) { 365 _XkbReloadDpy(dpy); 366 return Success; 367 } 368 if (event->xkb_type == XkbMapNotify) { 369 XkbMapChangesRec changes; 370 Status rtrn; 371 372 if (xkbi->flags & XkbMapPending) 373 changes = xkbi->changes; 374 else 375 bzero(&changes, sizeof(changes)); 376 XkbNoteMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 377 if ((rtrn = XkbGetMapChanges(dpy, xkbi->desc, &changes)) != Success) { 378#ifdef DEBUG 379 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 380#endif 381 xkbi->changes = changes; 382 } 383 else if (xkbi->flags & XkbMapPending) { 384 xkbi->flags &= ~XkbMapPending; 385 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 386 } 387 return rtrn; 388 } 389 return BadMatch; 390} 391 392int 393XRefreshKeyboardMapping(register XMappingEvent * event) 394{ 395 XkbEvent *xkbevent = (XkbEvent *) event; 396 Display *dpy = event->display; 397 XkbMapChangesRec changes; 398 XkbInfoPtr xkbi; 399 400 /* always do this for input methods, which still use the old keymap */ 401 (void) _XRefreshKeyboardMapping(event); 402 403 if (_XkbUnavailable(dpy)) 404 return 1; 405 406 xkbi = dpy->xkb_info; 407 408 if (((event->type & 0x7f) - xkbi->codes->first_event) == XkbEventCode) 409 return XkbRefreshKeyboardMapping(&xkbevent->map); 410 411 if (xkbi->flags & XkbXlibNewKeyboard) { 412 _XkbReloadDpy(dpy); 413 return 1; 414 } 415 416 if ((xkbi->flags & XkbMapPending) || (event->request == MappingKeyboard)) { 417 if (xkbi->flags & XkbMapPending) { 418 changes = xkbi->changes; 419 _XkbNoteCoreMapChanges(&changes, event, XKB_XLIB_MAP_MASK); 420 } 421 else { 422 bzero(&changes, sizeof(changes)); 423 changes.changed = XkbKeySymsMask; 424 if (xkbi->desc->min_key_code < xkbi->desc->max_key_code) { 425 changes.first_key_sym = xkbi->desc->min_key_code; 426 changes.num_key_syms = xkbi->desc->max_key_code - 427 xkbi->desc->min_key_code + 1; 428 } 429 else { 430 changes.first_key_sym = event->first_keycode; 431 changes.num_key_syms = event->count; 432 } 433 } 434 435 if (XkbGetMapChanges(dpy, xkbi->desc, &changes) != Success) { 436#ifdef DEBUG 437 fprintf(stderr, "Internal Error! XkbGetMapChanges failed:\n"); 438 if (changes.changed & XkbKeyTypesMask) { 439 int first = changes.first_type; 440 int last = changes.first_type + changes.num_types - 1; 441 442 fprintf(stderr, " types: %d..%d\n", first, last); 443 } 444 if (changes.changed & XkbKeySymsMask) { 445 int first = changes.first_key_sym; 446 int last = changes.first_key_sym + changes.num_key_syms - 1; 447 448 fprintf(stderr, " symbols: %d..%d\n", first, last); 449 } 450 if (changes.changed & XkbKeyActionsMask) { 451 int first = changes.first_key_act; 452 int last = changes.first_key_act + changes.num_key_acts - 1; 453 454 fprintf(stderr, " acts: %d..%d\n", first, last); 455 } 456 if (changes.changed & XkbKeyBehaviorsMask) { 457 int first = changes.first_key_behavior; 458 int last = first + changes.num_key_behaviors - 1; 459 460 fprintf(stderr, " behaviors: %d..%d\n", first, last); 461 } 462 if (changes.changed & XkbVirtualModsMask) { 463 fprintf(stderr, "virtual mods: 0x%04x\n", changes.vmods); 464 } 465 if (changes.changed & XkbExplicitComponentsMask) { 466 int first = changes.first_key_explicit; 467 int last = first + changes.num_key_explicit - 1; 468 469 fprintf(stderr, " explicit: %d..%d\n", first, last); 470 } 471#endif 472 } 473 LockDisplay(dpy); 474 if (xkbi->flags & XkbMapPending) { 475 xkbi->flags &= ~XkbMapPending; 476 bzero(&xkbi->changes, sizeof(XkbMapChangesRec)); 477 } 478 UnlockDisplay(dpy); 479 } 480 if (event->request == MappingModifier) { 481 LockDisplay(dpy); 482 if (xkbi->desc->map->modmap) { 483 _XkbFree(xkbi->desc->map->modmap); 484 xkbi->desc->map->modmap = NULL; 485 } 486 if (dpy->key_bindings) { 487 register struct _XKeytrans *p; 488 489 for (p = dpy->key_bindings; p; p = p->next) { 490 register int i; 491 492 p->state = 0; 493 if (p->mlen > 0) { 494 for (i = 0; i < p->mlen; i++) { 495 p->state |= XkbKeysymToModifiers(dpy, p->modifiers[i]); 496 } 497 if (p->state) 498 p->state &= AllMods; 499 else 500 p->state = AnyModifier; 501 } 502 } 503 } 504 UnlockDisplay(dpy); 505 } 506 return 1; 507} 508 509static int 510_XkbLoadDpy(Display *dpy) 511{ 512 XkbInfoPtr xkbi; 513 unsigned query, oldEvents; 514 XkbDescRec *desc; 515 516 if (!XkbUseExtension(dpy, NULL, NULL)) 517 return 0; 518 519 xkbi = dpy->xkb_info; 520 query = XkbAllClientInfoMask; 521 desc = XkbGetMap(dpy, query, XkbUseCoreKbd); 522 if (!desc) { 523#ifdef DEBUG 524 fprintf(stderr, "Warning! XkbGetMap failed!\n"); 525#endif 526 return 0; 527 } 528 LockDisplay(dpy); 529 xkbi->desc = desc; 530 531 UnlockDisplay(dpy); 532 oldEvents = xkbi->selected_events; 533 if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) { 534 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, 535 XkbNewKeyboardNotify, 536 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask, 537 XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask); 538 } 539 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 540 XkbAllClientInfoMask, XkbAllClientInfoMask); 541 LockDisplay(dpy); 542 xkbi->selected_events = oldEvents; 543 UnlockDisplay(dpy); 544 return 1; 545} 546 547void 548_XkbReloadDpy(Display *dpy) 549{ 550 XkbInfoPtr xkbi; 551 XkbDescRec *desc; 552 unsigned oldDeviceID; 553 554 if (_XkbUnavailable(dpy)) 555 return; 556 557 xkbi = dpy->xkb_info; 558 LockDisplay(dpy); 559 if (xkbi->desc) { 560 oldDeviceID = xkbi->desc->device_spec; 561 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 562 xkbi->desc = NULL; 563 xkbi->flags &= ~(XkbMapPending | XkbXlibNewKeyboard); 564 xkbi->changes.changed = 0; 565 } 566 else 567 oldDeviceID = XkbUseCoreKbd; 568 UnlockDisplay(dpy); 569 desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); 570 if (!desc) 571 return; 572 LockDisplay(dpy); 573 xkbi->desc = desc; 574 UnlockDisplay(dpy); 575 576 if (desc->device_spec != oldDeviceID) { 577 /* transfer(?) event masks here */ 578#ifdef NOTYET 579 unsigned oldEvents; 580 581 oldEvents = xkbi->selected_events; 582 XkbSelectEventDetails(dpy, xkbi->desc->device_spec, XkbMapNotify, 583 XkbAllMapComponentsMask, XkbAllClientInfoMask); 584 LockDisplay(dpy); 585 xkbi->selected_events = oldEvents; 586 UnlockDisplay(dpy); 587#endif 588 } 589 return; 590} 591 592int 593XkbTranslateKeySym(Display *dpy, 594 KeySym *sym_rtrn, 595 unsigned int mods, 596 char *buffer, 597 int nbytes, 598 int *extra_rtrn) 599{ 600 register XkbInfoPtr xkb; 601 XkbKSToMBFunc cvtr; 602 XPointer priv; 603 char tmp[4]; 604 int n; 605 606 xkb = dpy->xkb_info; 607 if (!xkb->cvt.KSToMB) { 608 _XkbGetConverters(_XkbGetCharset(), &xkb->cvt); 609 _XkbGetConverters("ISO8859-1", &xkb->latin1cvt); 610 } 611 612 if (extra_rtrn) 613 *extra_rtrn = 0; 614 615 if ((buffer == NULL) || (nbytes == 0)) { 616 buffer = tmp; 617 nbytes = 4; 618 } 619 620 /* see if symbol rebound, if so, return that string. */ 621 n = XkbLookupKeyBinding(dpy, *sym_rtrn, mods, buffer, nbytes, extra_rtrn); 622 if (n) 623 return n; 624 625 if (nbytes > 0) 626 buffer[0] = '\0'; 627 628 if (xkb->cvt.KSToUpper && (mods & LockMask)) { 629 *sym_rtrn = (*xkb->cvt.KSToUpper) (*sym_rtrn); 630 } 631 if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { 632 cvtr = xkb->latin1cvt.KSToMB; 633 priv = xkb->latin1cvt.KSToMBPriv; 634 } 635 else { 636 cvtr = xkb->cvt.KSToMB; 637 priv = xkb->cvt.KSToMBPriv; 638 } 639 640 n = (*cvtr) (priv, *sym_rtrn, buffer, nbytes, extra_rtrn); 641 642 if ((!xkb->cvt.KSToUpper) && (mods & LockMask)) { 643 register int i; 644 int change; 645 646 for (i = change = 0; i < n; i++) { 647 char ch = toupper(buffer[i]); 648 change = (change || (buffer[i] != ch)); 649 buffer[i] = ch; 650 } 651 if (change) { 652 if (n == 1) 653 *sym_rtrn = 654 (*xkb->cvt.MBToKS) (xkb->cvt.MBToKSPriv, buffer, n, NULL); 655 else 656 *sym_rtrn = NoSymbol; 657 } 658 } 659 660 if (mods & ControlMask) { 661 if (n == 1) { 662 buffer[0] = XkbToControl(buffer[0]); 663 if (nbytes > 1) 664 buffer[1] = '\0'; 665 return 1; 666 } 667 if (nbytes > 0) 668 buffer[0] = '\0'; 669 return 0; 670 } 671 return n; 672} 673 674int 675XLookupString(register XKeyEvent *event, 676 char *buffer, 677 int nbytes, 678 KeySym *keysym, 679 XComposeStatus *status) 680{ 681 KeySym dummy; 682 int rtrnLen; 683 unsigned int new_mods; 684 Display *dpy = event->display; 685 686 if (keysym == NULL) 687 keysym = &dummy; 688 if (!XkbLookupKeySym(dpy, event->keycode, event->state, &new_mods, keysym)) 689 return 0; 690 new_mods = (event->state & (~new_mods)); 691 692 /* find the group where a symbol can be converted to control one */ 693 if (new_mods & ControlMask && *keysym > 0x7F && 694 (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { 695 XKeyEvent tmp_ev = *event; 696 KeySym tmp_keysym; 697 unsigned int tmp_new_mods; 698 699 if (_XkbUnavailable(dpy)) { 700 tmp_ev.state = event->state ^ dpy->mode_switch; 701 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 702 &tmp_new_mods, &tmp_keysym) && 703 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 704 *keysym = tmp_keysym; 705 } 706 } 707 else { 708 int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); 709 int i; 710 711 for (i = 0; i < n; i++) { 712 if (XkbGroupForCoreState(event->state) == i) 713 continue; 714 tmp_ev.state = XkbBuildCoreState(tmp_ev.state, i); 715 if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, 716 &tmp_new_mods, &tmp_keysym) && 717 tmp_keysym != NoSymbol && tmp_keysym < 0x80) { 718 *keysym = tmp_keysym; 719 new_mods = (event->state & (~tmp_new_mods)); 720 break; 721 } 722 } 723 } 724 } 725 726 /* We *should* use the new_mods (which does not contain any modifiers */ 727 /* that were used to compute the symbol here, but pre-XKB XLookupString */ 728 /* did not and we have to remain compatible. Sigh. */ 729 if (_XkbUnavailable(dpy) || 730 (dpy->xkb_info->xlib_ctrls & XkbLC_ConsumeLookupMods) == 0) 731 new_mods = event->state; 732 733 rtrnLen = XkbLookupKeyBinding(dpy, *keysym, new_mods, buffer, nbytes, NULL); 734 if (rtrnLen > 0) 735 return rtrnLen; 736 737 return XkbTranslateKeySym(dpy, keysym, new_mods, buffer, nbytes, NULL); 738} 739 740 741int 742XkbLookupKeyBinding(Display *dpy, 743 register KeySym sym, 744 unsigned int mods, 745 char *buffer, 746 int nbytes, 747 int *extra_rtrn) 748{ 749 register struct _XKeytrans *p; 750 751 if (extra_rtrn) 752 *extra_rtrn = 0; 753 for (p = dpy->key_bindings; p; p = p->next) { 754 if (((mods & AllMods) == p->state) && (sym == p->key)) { 755 int tmp = p->len; 756 757 if (tmp > nbytes) { 758 if (extra_rtrn) 759 *extra_rtrn = (tmp - nbytes); 760 tmp = nbytes; 761 } 762 memcpy(buffer, p->string, (size_t) tmp); 763 if (tmp < nbytes) 764 buffer[tmp] = '\0'; 765 return tmp; 766 } 767 } 768 return 0; 769} 770 771char 772XkbToControl(char ch) 773{ 774 register char c = ch; 775 776 if ((c >= '@' && c < '\177') || c == ' ') 777 c &= 0x1F; 778 else if (c == '2') 779 c = '\000'; 780 else if (c >= '3' && c <= '7') 781 c -= ('3' - '\033'); 782 else if (c == '8') 783 c = '\177'; 784 else if (c == '/') 785 c = '_' & 0x1F; 786 return c; 787} 788