/* $Xorg: XKBBind.c,v 1.3 2000/08/17 19:45:00 cpqbld Exp $ */ /* Copyright 1985, 1987, 1994, 1998 The Open Group All Rights Reserved. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ /* $XFree86: xc/lib/X11/XKBBind.c,v 3.13 2001/01/17 19:41:48 dawes Exp $ */ /* the new monsters ate the old ones */ #define NEED_EVENTS #include #include #include #include #include #include #include "XKBlibint.h" #ifdef USE_OWN_COMPOSE #define COMPOSE_NO_CONST_MEMBERS #include "imComp.h" #endif #define AllMods (ShiftMask|LockMask|ControlMask| \ Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) static int _XkbLoadDpy( #if NeedFunctionPrototypes Display *dpy #endif ); struct _XKeytrans { struct _XKeytrans *next;/* next on list */ char *string; /* string to return when the time comes */ int len; /* length of string (since NULL is legit)*/ KeySym key; /* keysym rebound */ unsigned int state; /* modifier state */ KeySym *modifiers; /* modifier keysyms you want */ int mlen; /* length of modifier list */ }; KeySym #if NeedFunctionPrototypes XkbKeycodeToKeysym(Display *dpy, #if NeedWidePrototypes unsigned int kc, #else KeyCode kc, #endif int group, int level) #else XkbKeycodeToKeysym(dpy, kc, group, level) Display *dpy; KeyCode kc; int group; int level; #endif { XkbDescRec *xkb; if (_XkbUnavailable(dpy)) return NoSymbol; _XkbCheckPendingRefresh(dpy,dpy->xkb_info); xkb = dpy->xkb_info->desc; if ((kcmin_key_code)||(kc>xkb->max_key_code)) return NoSymbol; if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc))) return NoSymbol; if (level>=XkbKeyGroupWidth(xkb,kc,group)) { /* for compatibility with the core protocol, _always_ allow */ /* two symbols in the first two groups. If either of the */ /* two is of type ONE_LEVEL, just replicate the first symbol */ if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)|| (level!=1)) { return NoSymbol; } level= 0; } return XkbKeySymEntry(xkb,kc,level,group); } KeySym #if NeedFunctionPrototypes XKeycodeToKeysym(Display *dpy, #if NeedWidePrototypes unsigned int kc, #else KeyCode kc, #endif int col) #else XKeycodeToKeysym(dpy, kc, col) Display *dpy; KeyCode kc; int col; #endif { XkbDescRec *xkb; if (_XkbUnavailable(dpy)) return _XKeycodeToKeysym(dpy, kc, col); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); xkb = dpy->xkb_info->desc; if ((kcmin_key_code)||(kc>xkb->max_key_code)) return NoSymbol; if (col>3) { int lastSym,tmp,nGrp; lastSym= 3; nGrp= XkbKeyNumGroups(xkb,kc); if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) { if (col<=(lastSym+tmp-2)) return XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2); lastSym+= tmp-2; } if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) { if (col<=(lastSym+tmp-2)) return XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2); lastSym+= tmp-2; } if (nGrp>2) { tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index); if (col<=lastSym+tmp) return XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym); lastSym+= tmp; } if (nGrp>3) { tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index); if (col<=lastSym+tmp) return XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym); } return NoSymbol; } return XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1)); } KeyCode #if NeedFunctionPrototypes XKeysymToKeycode(Display *dpy, KeySym ks) #else XKeysymToKeycode(dpy, ks) Display *dpy; KeySym ks; #endif { register int i, j, gotOne; if (_XkbUnavailable(dpy)) return _XKeysymToKeycode(dpy,ks); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); j= 0; do { register XkbDescRec *xkb = dpy->xkb_info->desc; gotOne= 0; for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { if ( j<(int)XkbKeyNumSyms(xkb,i) ) { gotOne = 1; if ((XkbKeySym(xkb,i,j)==ks)) return i; } } j++; } while (gotOne); return 0; } static int #if NeedFunctionPrototypes _XkbComputeModmap(Display *dpy) #else _XkbComputeModmap(dpy) Display *dpy; #endif { register XkbDescPtr xkb; xkb= dpy->xkb_info->desc; if (XkbGetUpdatedMap(dpy,XkbModifierMapMask,xkb)==Success) return 1; return 0; } unsigned #if NeedFunctionPrototypes XkbKeysymToModifiers(Display *dpy,KeySym ks) #else XkbKeysymToModifiers(dpy,ks) Display *dpy; KeySym ks; #endif { XkbDescRec *xkb; register int i,j; register KeySym *pSyms; CARD8 mods; if (_XkbUnavailable(dpy)) return _XKeysymToModifiers(dpy,ks); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); if (_XkbNeedModmap(dpy->xkb_info)&&(!_XkbComputeModmap(dpy))) return _XKeysymToModifiers(dpy,ks); xkb= dpy->xkb_info->desc; mods= 0; for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) { pSyms= XkbKeySymsPtr(xkb,i); for (j=XkbKeyNumSyms(xkb,i)-1;j>=0;j--) { if (pSyms[j]==ks) { mods|= xkb->map->modmap[i]; break; } } } return mods; } KeySym #if NeedFunctionPrototypes XLookupKeysym(register XKeyEvent *event, int col) #else XLookupKeysym(event, col) register XKeyEvent *event; int col; #endif { Display *dpy = event->display; if (_XkbUnavailable(dpy)) return _XLookupKeysym(event, col); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); return XKeycodeToKeysym(dpy, event->keycode, col); } /* * Not a public entry point -- XkbTranslateKey is an obsolete name * that is preserved here so that functions linked against the old * version will continue to work in a shared library environment. */ int #if NeedFunctionPrototypes XkbTranslateKey( register Display * dpy, KeyCode key, register unsigned int mods, unsigned int * mods_rtrn, KeySym * keysym_rtrn) #else XkbTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn) register Display *dpy; KeyCode key; register unsigned int mods; unsigned int *mods_rtrn; KeySym *keysym_rtrn; #endif { return XkbLookupKeySym(dpy,key,mods,mods_rtrn,keysym_rtrn); } Bool #if NeedFunctionPrototypes XkbLookupKeySym( register Display * dpy, KeyCode key, register unsigned int mods, unsigned int * mods_rtrn, KeySym * keysym_rtrn) #else XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn) register Display *dpy; KeyCode key; register unsigned int mods; unsigned int *mods_rtrn; KeySym *keysym_rtrn; #endif { if (_XkbUnavailable(dpy)) return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); return XkbTranslateKeyCode(dpy->xkb_info->desc,key,mods,mods_rtrn, keysym_rtrn); } Bool #if NeedFunctionPrototypes XkbTranslateKeyCode( register XkbDescPtr xkb, KeyCode key, register unsigned int mods, unsigned int * mods_rtrn, KeySym * keysym_rtrn) #else XkbTranslateKeyCode(xkb, key, mods, mods_rtrn, keysym_rtrn) register XkbDescPtr xkb; KeyCode key; register unsigned int mods; unsigned int *mods_rtrn; KeySym *keysym_rtrn; #endif { XkbKeyTypeRec *type; int col,nKeyGroups; unsigned preserve,effectiveGroup; KeySym *syms; if (mods_rtrn!=NULL) *mods_rtrn = 0; nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { if (keysym_rtrn!=NULL) *keysym_rtrn = NoSymbol; return False; } syms = XkbKeySymsPtr(xkb,key); /* find the offset of the effective group */ col = 0; effectiveGroup= XkbGroupForCoreState(mods); if ( effectiveGroup>=nKeyGroups ) { unsigned groupInfo= XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(groupInfo)) { default: effectiveGroup %= nKeyGroups; break; case XkbClampIntoRange: effectiveGroup = nKeyGroups-1; break; case XkbRedirectIntoRange: effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); if (effectiveGroup>=nKeyGroups) effectiveGroup= 0; break; } } col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); type = XkbKeyKeyType(xkb,key,effectiveGroup); preserve= 0; if (type->map) { /* find the column (shift level) within the group */ register int i; register XkbKTMapEntryPtr entry; for (i=0,entry=type->map;imap_count;i++,entry++) { if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) { col+= entry->level; if (type->preserve) preserve= type->preserve[i].mask; break; } } } if (keysym_rtrn!=NULL) *keysym_rtrn= syms[col]; if (mods_rtrn) { *mods_rtrn= type->mods.mask&(~preserve); /* The Motif VTS doesn't get the help callback called if help * is bound to Shift+, and it appears as though it * is XkbTranslateKeyCode that is causing the problem. The * core X version of XTranslateKey always OR's in ShiftMask * and LockMask for mods_rtrn, so this "fix" keeps this behavior * and solves the VTS problem. */ if ((xkb->dpy)&&(xkb->dpy->xkb_info)&& (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask); } } return (syms[col]!=NoSymbol); } Status #if NeedFunctionPrototypes XkbRefreshKeyboardMapping(register XkbMapNotifyEvent *event) #else XkbRefreshKeyboardMapping(event) register XkbMapNotifyEvent *event; #endif { Display *dpy = event->display; XkbInfoPtr xkbi; if (_XkbUnavailable(dpy)) { _XRefreshKeyboardMapping((XMappingEvent *)event); return Success; } xkbi= dpy->xkb_info; if (((event->type&0x7f)-xkbi->codes->first_event)!=XkbEventCode) return BadMatch; if (event->xkb_type==XkbNewKeyboardNotify) { _XkbReloadDpy(dpy); return Success; } if (event->xkb_type==XkbMapNotify) { XkbMapChangesRec changes; Status rtrn; if (xkbi->flags&XkbMapPending) changes= xkbi->changes; else bzero(&changes,sizeof(XkbChangesRec)); XkbNoteMapChanges(&changes,event,XKB_XLIB_MAP_MASK); LockDisplay(dpy); if ((rtrn=XkbGetMapChanges(dpy,xkbi->desc,&changes))!=Success) { #ifdef DEBUG fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n"); #endif xkbi->changes= changes; } else if (xkbi->flags&XkbMapPending) { xkbi->flags&= ~XkbMapPending; bzero(&xkbi->changes,sizeof(XkbMapChangesRec)); } UnlockDisplay(dpy); return rtrn; } return BadMatch; } int #if NeedFunctionPrototypes XRefreshKeyboardMapping(register XMappingEvent *event) #else XRefreshKeyboardMapping(event) register XMappingEvent *event; #endif { XkbEvent *xkbevent = (XkbEvent *)event; Display *dpy = event->display; XkbMapChangesRec changes; XkbInfoPtr xkbi; /* always do this for input methods, which still use the old keymap */ (void) _XRefreshKeyboardMapping(event); if (_XkbUnavailable(dpy)) return 1; xkbi = dpy->xkb_info; if (((event->type&0x7f)-xkbi->codes->first_event)==XkbEventCode) return XkbRefreshKeyboardMapping(&xkbevent->map); if (xkbi->flags&XkbXlibNewKeyboard) { _XkbReloadDpy(dpy); return 1; } if ((xkbi->flags&XkbMapPending)||(event->request==MappingKeyboard)) { if (xkbi->flags&XkbMapPending) { changes= xkbi->changes; _XkbNoteCoreMapChanges(&changes,event,XKB_XLIB_MAP_MASK); } else { bzero(&changes,sizeof(changes)); changes.changed= XkbKeySymsMask; if (xkbi->desc->min_key_codedesc->max_key_code) { changes.first_key_sym= xkbi->desc->min_key_code; changes.num_key_syms= xkbi->desc->max_key_code- xkbi->desc->min_key_code+1; } else { changes.first_key_sym= event->first_keycode; changes.num_key_syms= event->count; } } if (XkbGetMapChanges(dpy,xkbi->desc, &changes)!=Success) { #ifdef DEBUG fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n"); if (changes.changed&XkbKeyTypesMask) { int first= changes.first_type; int last= changes.first_type+changes.num_types-1; fprintf(stderr," types: %d..%d\n",first,last); } if (changes.changed&XkbKeySymsMask) { int first= changes.first_key_sym; int last= changes.first_key_sym+changes.num_key_syms-1; fprintf(stderr," symbols: %d..%d\n",first,last); } if (changes.changed&XkbKeyActionsMask) { int last,first= changes.first_key_act; last= changes.first_key_act+changes.num_key_acts-1; fprintf(stderr," acts: %d..%d\n",first,last); } if (changes.changed&XkbKeyBehaviorsMask) { int last,first= changes.first_key_behavior; last= first+changes.num_key_behaviors-1; fprintf(stderr," behaviors: %d..%d\n",first,last); } if (changes.changed&XkbVirtualModsMask) { fprintf(stderr,"virtual mods: 0x%04x\n", changes.vmods); } if (changes.changed&XkbExplicitComponentsMask) { int last,first= changes.first_key_explicit; last= first+changes.num_key_explicit-1; fprintf(stderr," explicit: %d..%d\n",first,last); } #endif } LockDisplay(dpy); if (xkbi->flags&XkbMapPending) { xkbi->flags&= ~XkbMapPending; bzero(&xkbi->changes,sizeof(XkbMapChangesRec)); } UnlockDisplay(dpy); } if (event->request==MappingModifier) { if (xkbi->desc->map->modmap) { _XkbFree(xkbi->desc->map->modmap); xkbi->desc->map->modmap= NULL; } if (dpy->key_bindings) { register struct _XKeytrans *p; for (p = dpy->key_bindings; p; p = p->next) { register int i; p->state= 0; if (p->mlen>0) { for (i = 0; i < p->mlen; i++) { p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]); } if (p->state) p->state &= AllMods; else p->state = AnyModifier; } } } UnlockDisplay(dpy); } return 1; } static int #if NeedFunctionPrototypes _XkbLoadDpy(Display *dpy) #else _XkbLoadDpy(dpy) Display *dpy; #endif { XkbInfoPtr xkbi; unsigned query,oldEvents; XkbDescRec *desc; if (!XkbUseExtension(dpy,NULL,NULL)) return 0; xkbi = dpy->xkb_info; query = XkbAllClientInfoMask; desc = XkbGetMap(dpy,query,XkbUseCoreKbd); if (!desc) { #ifdef DEBUG fprintf(stderr,"Warning! XkbGetMap failed!\n"); #endif return 0; } LockDisplay(dpy); xkbi->desc = desc; UnlockDisplay(dpy); oldEvents= xkbi->selected_events; if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) { XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbNewKeyboardNotify, XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask, XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask); } XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify, XkbAllClientInfoMask,XkbAllClientInfoMask); LockDisplay(dpy); xkbi->selected_events= oldEvents; UnlockDisplay(dpy); return 1; } void #if NeedFunctionPrototypes _XkbReloadDpy(Display *dpy) #else _XkbReloadDpy(dpy) Display *dpy; #endif { XkbInfoPtr xkbi; XkbDescRec *desc; unsigned oldDeviceID; if (_XkbUnavailable(dpy)) return; xkbi = dpy->xkb_info; LockDisplay(dpy); if (xkbi->desc) { oldDeviceID= xkbi->desc->device_spec; XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); xkbi->desc= NULL; xkbi->flags&= ~(XkbMapPending|XkbXlibNewKeyboard); xkbi->changes.changed= 0; } else oldDeviceID= XkbUseCoreKbd; UnlockDisplay(dpy); desc = XkbGetMap(dpy,XkbAllClientInfoMask,XkbUseCoreKbd); if (!desc) return; LockDisplay(dpy); xkbi->desc = desc; UnlockDisplay(dpy); if (desc->device_spec!=oldDeviceID) { /* transfer(?) event masks here */ #ifdef NOTYET unsigned oldEvents; oldEvents= xkbi->selected_events; XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify, XkbAllMapComponentsMask,XkbAllClientInfoMask); LockDisplay(dpy); xkbi->selected_events= oldEvents; UnlockDisplay(dpy); #endif } return; } int #if NeedFunctionPrototypes XkbTranslateKeySym( register Display * dpy, register KeySym * sym_rtrn, unsigned int mods, char * buffer, int nbytes, int * extra_rtrn) #else XkbTranslateKeySym(dpy, sym_rtrn, mods, buffer, nbytes, extra_rtrn) register Display *dpy; register KeySym *sym_rtrn; unsigned int mods; char *buffer; int nbytes; int *extra_rtrn; #endif { register XkbInfoPtr xkb; XkbKSToMBFunc cvtr; XPointer priv; char tmp[4]; int n; xkb= dpy->xkb_info; if (!xkb->cvt.KSToMB) { _XkbGetConverters(_XkbGetCharset(),&xkb->cvt); _XkbGetConverters("ISO8859-1",&xkb->latin1cvt); } if (extra_rtrn) *extra_rtrn= 0; if ((buffer==NULL)||(nbytes==0)) { buffer= tmp; nbytes= 4; } /* see if symbol rebound, if so, return that string. */ n = XkbLookupKeyBinding(dpy,*sym_rtrn,mods,buffer,nbytes,extra_rtrn); if (n) return n; if ( nbytes>0 ) buffer[0]= '\0'; if ( xkb->cvt.KSToUpper && (mods&LockMask) ) { *sym_rtrn = (*xkb->cvt.KSToUpper)(*sym_rtrn); } if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) { cvtr = xkb->latin1cvt.KSToMB; priv = xkb->latin1cvt.KSToMBPriv; } else { cvtr = xkb->cvt.KSToMB; priv = xkb->cvt.KSToMBPriv; } n = (*cvtr)(priv,*sym_rtrn,buffer,nbytes,extra_rtrn); if ((!xkb->cvt.KSToUpper)&&( mods&LockMask )) { register int i; int change; char ch; for (i=change=0;icvt.MBToKS)(xkb->cvt.MBToKSPriv,buffer,n,0); else *sym_rtrn= NoSymbol; } } if ( mods&ControlMask ) { if ( n==1 ) { buffer[0]= XkbToControl(buffer[0]); if ( nbytes>1 ) buffer[1]= '\0'; return 1; } if ( nbytes > 0 ) buffer[0]= '\0'; return 0; } return n; } int #if NeedFunctionPrototypes XLookupString ( register XKeyEvent * event, char * buffer, int nbytes, KeySym * keysym, XComposeStatus * status) #else XLookupString (event, buffer, nbytes, keysym, status) register XKeyEvent *event; char *buffer; /* buffer */ int nbytes; /* space in buffer for characters */ KeySym *keysym; XComposeStatus *status; #endif { KeySym dummy; int rtrnLen; unsigned int new_mods; Display *dpy = event->display; XkbDescPtr xkb; if (keysym==NULL) keysym= &dummy; xkb= dpy->xkb_info->desc; if (!XkbLookupKeySym(dpy,event->keycode,event->state, &new_mods,keysym)) return 0; new_mods= (event->state&(~new_mods)); #ifdef USE_OWN_COMPOSE if ( status ) { static int been_here= 0; if ( !been_here ) { XimCompInitTables(); been_here = 1; } if ( !XimCompLegalStatus(status) ) { status->compose_ptr = NULL; status->chars_matched = 0; } if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || XimCompIsComposeKey(*keysym,event->keycode,status) ) { XimCompRtrn rtrn; switch (XimCompProcessSym(status,*keysym,&rtrn)) { case XIM_COMP_IGNORE: break; case XIM_COMP_IN_PROGRESS: if ( keysym!=NULL ) *keysym = NoSymbol; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,True,False,NULL); } #endif return 0; case XIM_COMP_FAIL: { static Atom _ComposeFail= None; int n = 0, len= 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif #ifndef NO_BELL_ON_COMPOSE_FAIL if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) { if (_ComposeFail==None) _ComposeFail= XInternAtom(dpy,"ComposeFail",0); XkbBell(dpy,event->window,0,_ComposeFail); } #endif for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods, buffer+len,nbytes-len, NULL); } } if ( keysym!=NULL ) { if ( n==1 ) *keysym = rtrn.sym[0]; else *keysym = NoSymbol; } return len; } case XIM_COMP_SUCCEED: { int len,n = 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif *keysym = rtrn.matchSym; if ( rtrn.str[0]!='\0' ) { strncpy(buffer,rtrn.str,nbytes-1); buffer[nbytes-1]= '\0'; len = (int)strlen(buffer); } else { len = XkbTranslateKeySym(dpy,keysym,new_mods, buffer,nbytes, NULL); } for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n], event->state, buffer+len,nbytes-len, NULL); } } return len; } } } } #endif /* We *should* use the new_mods (which does not contain any modifiers */ /* that were used to compute the symbol here, but pre-XKB XLookupString */ /* did not and we have to remain compatible. Sigh. */ if ((dpy->xkb_info->xlib_ctrls&XkbLC_ConsumeLookupMods)==0) new_mods= event->state; rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL); if (rtrnLen>0) return rtrnLen; rtrnLen = XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL); if ((event->state&ControlMask)&&(nbytes>0)&& ((rtrnLen==0)|| ((rtrnLen==1)&&((unsigned char) buffer[0]>=' ')))&& (dpy->xkb_info->xlib_ctrls&XkbLC_ControlFallback)) { XKeyEvent tmp_ev; tmp_ev= *event; if (_XkbUnavailable(dpy)) { if (event->state & dpy->mode_switch) { tmp_ev.state= event->state & ~dpy->mode_switch; return XLookupString (&tmp_ev, buffer, nbytes, keysym, status); } } else { if (XkbGroupForCoreState(event->state) != XkbGroup1Index) { tmp_ev.state= XkbBuildCoreState(event->state,XkbGroup1Index); return XLookupString (&tmp_ev, buffer, nbytes, keysym, status); } } } return rtrnLen; } int #if NeedFunctionPrototypes XkbLookupKeyBinding( Display * dpy, register KeySym sym, unsigned int mods, char * buffer, int nbytes, int * extra_rtrn) #else XkbLookupKeyBinding(dpy, sym, mods, buffer, nbytes, extra_rtrn) Display *dpy; register KeySym sym; unsigned int mods; char *buffer; int nbytes; int * extra_rtrn; #endif { register struct _XKeytrans *p; if (extra_rtrn) *extra_rtrn= 0; for (p = dpy->key_bindings; p; p = p->next) { if (((mods & AllMods) == p->state) && (sym == p->key)) { int tmp = p->len; if (tmp > nbytes) { if (extra_rtrn) *extra_rtrn= (tmp-nbytes); tmp = nbytes; } memcpy (buffer, p->string, tmp); if (tmp < nbytes) buffer[tmp]= '\0'; return tmp; } } return 0; } char #if NeedFunctionPrototypes XkbToControl( char ch ) #else XkbToControl( ch ) char ch; #endif { register char c = ch; if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; else if (c == '2') c = '\000'; else if (c >= '3' && c <= '7') c -= ('3' - '\033'); else if (c == '8') c = '\177'; else if (c == '/') c = '_' & 0x1F; return c; }