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