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