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