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