XKBMisc.c revision 4642e01f
105b261ecSmrg/************************************************************ 205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 305b261ecSmrg 405b261ecSmrgPermission to use, copy, modify, and distribute this 505b261ecSmrgsoftware and its documentation for any purpose and without 605b261ecSmrgfee is hereby granted, provided that the above copyright 705b261ecSmrgnotice appear in all copies and that both that copyright 805b261ecSmrgnotice and this permission notice appear in supporting 905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be 1005b261ecSmrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 1205b261ecSmrgSilicon Graphics makes no representation about the suitability 1305b261ecSmrgof this software for any purpose. It is provided "as is" 1405b261ecSmrgwithout any express or implied warranty. 1505b261ecSmrg 1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#elif defined(HAVE_CONFIG_H) 3005b261ecSmrg#include <config.h> 3105b261ecSmrg#endif 3205b261ecSmrg 3305b261ecSmrg#include <stdio.h> 3405b261ecSmrg#include <X11/X.h> 3505b261ecSmrg#define NEED_EVENTS 3605b261ecSmrg#define NEED_REPLIES 3705b261ecSmrg#include <X11/Xproto.h> 3805b261ecSmrg#include "misc.h" 3905b261ecSmrg#include "inputstr.h" 4005b261ecSmrg#include <X11/keysym.h> 4105b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 4205b261ecSmrg#include <xkbsrv.h> 4305b261ecSmrg 4405b261ecSmrg/***====================================================================***/ 4505b261ecSmrg 4605b261ecSmrg#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 4705b261ecSmrg#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 4805b261ecSmrg 4905b261ecSmrgint 5005b261ecSmrgXkbKeyTypesForCoreSymbols( XkbDescPtr xkb, 5105b261ecSmrg int map_width, 5205b261ecSmrg KeySym * core_syms, 5305b261ecSmrg unsigned int protected, 5405b261ecSmrg int * types_inout, 5505b261ecSmrg KeySym * xkb_syms_rtrn) 5605b261ecSmrg{ 5705b261ecSmrgregister int i; 5805b261ecSmrgunsigned int empty; 5905b261ecSmrgint nSyms[XkbNumKbdGroups]; 6005b261ecSmrgint nGroups,tmp,groupsWidth; 6105b261ecSmrg 6205b261ecSmrg /* Section 12.2 of the protocol describes this process in more detail */ 6305b261ecSmrg /* Step 1: find the # of symbols in the core mapping per group */ 6405b261ecSmrg groupsWidth= 2; 6505b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 6605b261ecSmrg if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { 6705b261ecSmrg nSyms[i]= xkb->map->types[types_inout[i]].num_levels; 6805b261ecSmrg if (nSyms[i]>groupsWidth) 6905b261ecSmrg groupsWidth= nSyms[i]; 7005b261ecSmrg } 7105b261ecSmrg else { 7205b261ecSmrg types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ 7305b261ecSmrg nSyms[i]= 2; 7405b261ecSmrg } 7505b261ecSmrg } 7605b261ecSmrg if (nSyms[XkbGroup1Index]<2) 7705b261ecSmrg nSyms[XkbGroup1Index]= 2; 7805b261ecSmrg if (nSyms[XkbGroup2Index]<2) 7905b261ecSmrg nSyms[XkbGroup2Index]= 2; 8005b261ecSmrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 8105b261ecSmrg /* symbols in the core are in the order: */ 8205b261ecSmrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 8305b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); 8405b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); 8505b261ecSmrg for (i=2;i<nSyms[XkbGroup1Index];i++) { 8605b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); 8705b261ecSmrg } 8805b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); 8905b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); 9005b261ecSmrg tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ 9105b261ecSmrg for (i=2;i<nSyms[XkbGroup2Index];i++) { 9205b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); 9305b261ecSmrg } 9405b261ecSmrg tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; 9505b261ecSmrg if ((tmp>=map_width)&& 9605b261ecSmrg ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { 9705b261ecSmrg nSyms[XkbGroup3Index]= 0; 9805b261ecSmrg nSyms[XkbGroup4Index]= 0; 9905b261ecSmrg nGroups= 2; 10005b261ecSmrg } 10105b261ecSmrg else { 10205b261ecSmrg nGroups= 3; 10305b261ecSmrg for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { 10405b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); 10505b261ecSmrg } 10605b261ecSmrg if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { 10705b261ecSmrg nGroups= 4; 10805b261ecSmrg for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { 10905b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); 11005b261ecSmrg } 11105b261ecSmrg } 11205b261ecSmrg else { 11305b261ecSmrg nSyms[XkbGroup4Index]= 0; 11405b261ecSmrg } 11505b261ecSmrg } 11605b261ecSmrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 11705b261ecSmrg empty= 0; 11805b261ecSmrg for (i=0;i<nGroups;i++) { 11905b261ecSmrg KeySym *syms; 12005b261ecSmrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 12105b261ecSmrg if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { 12205b261ecSmrg KeySym upper,lower; 12305b261ecSmrg XConvertCase(syms[0],&lower,&upper); 12405b261ecSmrg if (upper!=lower) { 12505b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; 12605b261ecSmrg xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; 12705b261ecSmrg if ((protected&(1<<i))==0) 12805b261ecSmrg types_inout[i]= XkbAlphabeticIndex; 12905b261ecSmrg } 13005b261ecSmrg else if ((protected&(1<<i))==0) { 13105b261ecSmrg types_inout[i]= XkbOneLevelIndex; 13205b261ecSmrg /* nSyms[i]= 1;*/ 13305b261ecSmrg } 13405b261ecSmrg } 13505b261ecSmrg if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { 13605b261ecSmrg if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1])) 13705b261ecSmrg types_inout[i]= XkbKeypadIndex; 13805b261ecSmrg else { 13905b261ecSmrg KeySym upper,lower; 14005b261ecSmrg XConvertCase(syms[0],&lower,&upper); 14105b261ecSmrg if ((syms[0]==lower)&&(syms[1]==upper)) 14205b261ecSmrg types_inout[i]= XkbAlphabeticIndex; 14305b261ecSmrg } 14405b261ecSmrg } 14505b261ecSmrg if (syms[0]==NoSymbol) { 14605b261ecSmrg register int n; 14705b261ecSmrg Bool found; 14805b261ecSmrg for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) { 14905b261ecSmrg found= (syms[n]!=NoSymbol); 15005b261ecSmrg } 15105b261ecSmrg if (!found) 15205b261ecSmrg empty|= (1<<i); 15305b261ecSmrg } 15405b261ecSmrg } 15505b261ecSmrg /* step 5: squoosh out empty groups */ 15605b261ecSmrg if (empty) { 15705b261ecSmrg for (i=nGroups-1;i>=0;i--) { 15805b261ecSmrg if (((empty&(1<<i))==0)||(protected&(1<<i))) 15905b261ecSmrg break; 16005b261ecSmrg nGroups--; 16105b261ecSmrg } 16205b261ecSmrg } 16305b261ecSmrg if (nGroups<1) 16405b261ecSmrg return 0; 16505b261ecSmrg 16605b261ecSmrg /* step 6: replicate group 1 into group two, if necessary */ 16705b261ecSmrg if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { 16805b261ecSmrg if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { 16905b261ecSmrg nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; 17005b261ecSmrg types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; 17105b261ecSmrg memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, 17205b261ecSmrg 2*sizeof(KeySym)); 17305b261ecSmrg } 17405b261ecSmrg else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { 17505b261ecSmrg memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], 17605b261ecSmrg (char *)xkb_syms_rtrn, 17705b261ecSmrg nSyms[XkbGroup1Index]*sizeof(KeySym)); 17805b261ecSmrg } 17905b261ecSmrg } 18005b261ecSmrg 1814642e01fSmrg /* step 7: check for all groups identical or all width 1 1824642e01fSmrg * 1834642e01fSmrg * Special feature: if group 1 has an explicit type and all other groups 1844642e01fSmrg * have canonical types with same symbols, we assume it's info lost from 1854642e01fSmrg * the core replication. 1864642e01fSmrg */ 18705b261ecSmrg if (nGroups>1) { 1884642e01fSmrg Bool sameType,allOneLevel, canonical = True; 18905b261ecSmrg allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); 19005b261ecSmrg for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) { 19105b261ecSmrg sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); 19205b261ecSmrg if (allOneLevel) 19305b261ecSmrg allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); 1944642e01fSmrg if (types_inout[i] > XkbLastRequiredType) 1954642e01fSmrg canonical = False; 19605b261ecSmrg } 1974642e01fSmrg if (((sameType) || canonical)&& 19805b261ecSmrg (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ 19905b261ecSmrg register int s; 20005b261ecSmrg Bool identical; 20105b261ecSmrg for (i=1,identical=True;identical&&(i<nGroups);i++) { 20205b261ecSmrg KeySym *syms; 20305b261ecSmrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 20405b261ecSmrg for (s=0;identical&&(s<nSyms[i]);s++) { 20505b261ecSmrg if (syms[s]!=xkb_syms_rtrn[s]) 20605b261ecSmrg identical= False; 20705b261ecSmrg } 20805b261ecSmrg } 20905b261ecSmrg if (identical) 21005b261ecSmrg nGroups= 1; 21105b261ecSmrg } 21205b261ecSmrg if (allOneLevel && (nGroups>1)) { 21305b261ecSmrg KeySym *syms; 21405b261ecSmrg syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 21505b261ecSmrg nSyms[XkbGroup1Index]= 1; 21605b261ecSmrg for (i=1;i<nGroups;i++) { 21705b261ecSmrg xkb_syms_rtrn[i]= syms[0]; 21805b261ecSmrg syms+= nSyms[i]; 21905b261ecSmrg nSyms[i]= 1; 22005b261ecSmrg } 22105b261ecSmrg } 22205b261ecSmrg } 22305b261ecSmrg return nGroups; 22405b261ecSmrg} 22505b261ecSmrg 22605b261ecSmrgstatic XkbSymInterpretPtr 22705b261ecSmrg_XkbFindMatchingInterp( XkbDescPtr xkb, 22805b261ecSmrg KeySym sym, 22905b261ecSmrg unsigned int real_mods, 23005b261ecSmrg unsigned int level) 23105b261ecSmrg{ 23205b261ecSmrgregister unsigned i; 23305b261ecSmrgXkbSymInterpretPtr interp,rtrn; 23405b261ecSmrgCARD8 mods; 23505b261ecSmrg 23605b261ecSmrg rtrn= NULL; 23705b261ecSmrg interp= xkb->compat->sym_interpret; 23805b261ecSmrg for (i=0;i<xkb->compat->num_si;i++,interp++) { 23905b261ecSmrg if ((interp->sym==NoSymbol)||(sym==interp->sym)) { 24005b261ecSmrg int match; 24105b261ecSmrg if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) 24205b261ecSmrg mods= real_mods; 24305b261ecSmrg else mods= 0; 24405b261ecSmrg switch (interp->match&XkbSI_OpMask) { 24505b261ecSmrg case XkbSI_NoneOf: 24605b261ecSmrg match= ((interp->mods&mods)==0); 24705b261ecSmrg break; 24805b261ecSmrg case XkbSI_AnyOfOrNone: 24905b261ecSmrg match= ((mods==0)||((interp->mods&mods)!=0)); 25005b261ecSmrg break; 25105b261ecSmrg case XkbSI_AnyOf: 25205b261ecSmrg match= ((interp->mods&mods)!=0); 25305b261ecSmrg break; 25405b261ecSmrg case XkbSI_AllOf: 25505b261ecSmrg match= ((interp->mods&mods)==interp->mods); 25605b261ecSmrg break; 25705b261ecSmrg case XkbSI_Exactly: 25805b261ecSmrg match= (interp->mods==mods); 25905b261ecSmrg break; 26005b261ecSmrg default: 26105b261ecSmrg match= 0; 26205b261ecSmrg break; 26305b261ecSmrg } 26405b261ecSmrg if (match) { 26505b261ecSmrg if (interp->sym!=NoSymbol) { 26605b261ecSmrg return interp; 26705b261ecSmrg } 26805b261ecSmrg else if (rtrn==NULL) { 26905b261ecSmrg rtrn= interp; 27005b261ecSmrg } 27105b261ecSmrg } 27205b261ecSmrg } 27305b261ecSmrg } 27405b261ecSmrg return rtrn; 27505b261ecSmrg} 27605b261ecSmrg 27705b261ecSmrgstatic void 27805b261ecSmrg_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) 27905b261ecSmrg{ 28005b261ecSmrgKeyCode last; 28105b261ecSmrg 28205b261ecSmrg last= (*pFirst)+(*pNum); 28305b261ecSmrg if (newKey<*pFirst) { 28405b261ecSmrg *pFirst= newKey; 28505b261ecSmrg *pNum= (last-newKey)+1; 28605b261ecSmrg } 28705b261ecSmrg else if (newKey>last) { 28805b261ecSmrg *pNum= (last-*pFirst)+1; 28905b261ecSmrg } 29005b261ecSmrg return; 29105b261ecSmrg} 29205b261ecSmrg 29305b261ecSmrgstatic void 29405b261ecSmrg_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 29505b261ecSmrg{ 29605b261ecSmrgunsigned tmp; 29705b261ecSmrg 29805b261ecSmrg switch (act->type) { 29905b261ecSmrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 30005b261ecSmrg if (act->mods.flags&XkbSA_UseModMapMods) 30105b261ecSmrg act->mods.real_mods= act->mods.mask= mods; 30205b261ecSmrg if ((tmp= XkbModActionVMods(&act->mods))!=0) { 30305b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 30405b261ecSmrg act->mods.mask|= tmp; 30505b261ecSmrg } 30605b261ecSmrg break; 30705b261ecSmrg case XkbSA_ISOLock: 30805b261ecSmrg if (act->iso.flags&XkbSA_UseModMapMods) 30905b261ecSmrg act->iso.real_mods= act->iso.mask= mods; 31005b261ecSmrg if ((tmp= XkbModActionVMods(&act->iso))!=0) { 31105b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 31205b261ecSmrg act->iso.mask|= tmp; 31305b261ecSmrg } 31405b261ecSmrg break; 31505b261ecSmrg } 31605b261ecSmrg return; 31705b261ecSmrg} 31805b261ecSmrg 31905b261ecSmrg#define IBUF_SIZE 8 32005b261ecSmrg 32105b261ecSmrgBool 32205b261ecSmrgXkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) 32305b261ecSmrg{ 32405b261ecSmrgKeySym * syms; 32505b261ecSmrgunsigned char explicit,mods; 32605b261ecSmrgXkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; 32705b261ecSmrgint n,nSyms,found; 32805b261ecSmrgunsigned changed,tmp; 32905b261ecSmrg 33005b261ecSmrg if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| 33105b261ecSmrg (!xkb->compat)||(!xkb->compat->sym_interpret)|| 33205b261ecSmrg (key<xkb->min_key_code)||(key>xkb->max_key_code)) { 33305b261ecSmrg return False; 33405b261ecSmrg } 33505b261ecSmrg if (((!xkb->server)||(!xkb->server->key_acts))&& 33605b261ecSmrg (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { 33705b261ecSmrg return False; 33805b261ecSmrg } 33905b261ecSmrg changed= 0; /* keeps track of what has changed in _this_ call */ 34005b261ecSmrg explicit= xkb->server->explicit[key]; 34105b261ecSmrg if (explicit&XkbExplicitInterpretMask) /* nothing to do */ 34205b261ecSmrg return True; 34305b261ecSmrg mods= (xkb->map->modmap?xkb->map->modmap[key]:0); 34405b261ecSmrg nSyms= XkbKeyNumSyms(xkb,key); 34505b261ecSmrg syms= XkbKeySymsPtr(xkb,key); 34605b261ecSmrg if (nSyms>IBUF_SIZE) { 34705b261ecSmrg interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); 34805b261ecSmrg if (interps==NULL) { 34905b261ecSmrg interps= ibuf; 35005b261ecSmrg nSyms= IBUF_SIZE; 35105b261ecSmrg } 35205b261ecSmrg } 35305b261ecSmrg else { 35405b261ecSmrg interps= ibuf; 35505b261ecSmrg } 35605b261ecSmrg found= 0; 35705b261ecSmrg for (n=0;n<nSyms;n++) { 35805b261ecSmrg unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); 35905b261ecSmrg interps[n]= NULL; 36005b261ecSmrg if (syms[n]!=NoSymbol) { 36105b261ecSmrg interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); 36205b261ecSmrg if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) 36305b261ecSmrg found++; 36405b261ecSmrg else interps[n]= NULL; 36505b261ecSmrg } 36605b261ecSmrg } 36705b261ecSmrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 36805b261ecSmrg if (!found) { 36905b261ecSmrg if (xkb->server->key_acts[key]!=0) { 37005b261ecSmrg xkb->server->key_acts[key]= 0; 37105b261ecSmrg changed|= XkbKeyActionsMask; 37205b261ecSmrg } 37305b261ecSmrg } 37405b261ecSmrg else { 37505b261ecSmrg XkbAction *pActs; 37605b261ecSmrg unsigned int new_vmodmask; 37705b261ecSmrg changed|= XkbKeyActionsMask; 37805b261ecSmrg pActs= XkbResizeKeyActions(xkb,key,nSyms); 37905b261ecSmrg if (!pActs) { 38005b261ecSmrg if (nSyms > IBUF_SIZE) 38105b261ecSmrg xfree(interps); 38205b261ecSmrg return False; 38305b261ecSmrg } 38405b261ecSmrg new_vmodmask= 0; 38505b261ecSmrg for (n=0;n<nSyms;n++) { 38605b261ecSmrg if (interps[n]) { 38705b261ecSmrg unsigned effMods; 38805b261ecSmrg 38905b261ecSmrg pActs[n]= *((XkbAction *)&interps[n]->act); 39005b261ecSmrg if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { 39105b261ecSmrg effMods= mods; 39205b261ecSmrg if (interps[n]->virtual_mod!=XkbNoModifier) 39305b261ecSmrg new_vmodmask|= (1<<interps[n]->virtual_mod); 39405b261ecSmrg } 39505b261ecSmrg else effMods= 0; 39605b261ecSmrg _XkbSetActionKeyMods(xkb,&pActs[n],effMods); 39705b261ecSmrg } 39805b261ecSmrg else pActs[n].type= XkbSA_NoAction; 39905b261ecSmrg } 40005b261ecSmrg if (((explicit&XkbExplicitVModMapMask)==0)&& 40105b261ecSmrg (xkb->server->vmodmap[key]!=new_vmodmask)) { 40205b261ecSmrg changed|= XkbVirtualModMapMask; 40305b261ecSmrg xkb->server->vmodmap[key]= new_vmodmask; 40405b261ecSmrg } 40505b261ecSmrg if (interps[0]) { 40605b261ecSmrg if ((interps[0]->flags&XkbSI_LockingKey)&& 40705b261ecSmrg ((explicit&XkbExplicitBehaviorMask)==0)) { 40805b261ecSmrg xkb->server->behaviors[key].type= XkbKB_Lock; 40905b261ecSmrg changed|= XkbKeyBehaviorsMask; 41005b261ecSmrg } 41105b261ecSmrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 41205b261ecSmrg CARD8 old; 41305b261ecSmrg old= xkb->ctrls->per_key_repeat[key/8]; 41405b261ecSmrg if (interps[0]->flags&XkbSI_AutoRepeat) 41505b261ecSmrg xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 41605b261ecSmrg else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); 41705b261ecSmrg if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 41805b261ecSmrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 41905b261ecSmrg } 42005b261ecSmrg } 42105b261ecSmrg } 42205b261ecSmrg if ((!found)||(interps[0]==NULL)) { 42305b261ecSmrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 42405b261ecSmrg CARD8 old; 42505b261ecSmrg old= xkb->ctrls->per_key_repeat[key/8]; 4264642e01fSmrg xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 42705b261ecSmrg if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 42805b261ecSmrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 42905b261ecSmrg } 43005b261ecSmrg if (((explicit&XkbExplicitBehaviorMask)==0)&& 43105b261ecSmrg (xkb->server->behaviors[key].type==XkbKB_Lock)) { 43205b261ecSmrg xkb->server->behaviors[key].type= XkbKB_Default; 43305b261ecSmrg changed|= XkbKeyBehaviorsMask; 43405b261ecSmrg } 43505b261ecSmrg } 43605b261ecSmrg if (changes) { 43705b261ecSmrg XkbMapChangesPtr mc; 43805b261ecSmrg mc= &changes->map; 43905b261ecSmrg tmp= (changed&mc->changed); 44005b261ecSmrg if (tmp&XkbKeyActionsMask) 44105b261ecSmrg _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); 44205b261ecSmrg else if (changed&XkbKeyActionsMask) { 44305b261ecSmrg mc->changed|= XkbKeyActionsMask; 44405b261ecSmrg mc->first_key_act= key; 44505b261ecSmrg mc->num_key_acts= 1; 44605b261ecSmrg } 44705b261ecSmrg if (tmp&XkbKeyBehaviorsMask) { 44805b261ecSmrg _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, 44905b261ecSmrg key); 45005b261ecSmrg } 45105b261ecSmrg else if (changed&XkbKeyBehaviorsMask) { 45205b261ecSmrg mc->changed|= XkbKeyBehaviorsMask; 45305b261ecSmrg mc->first_key_behavior= key; 45405b261ecSmrg mc->num_key_behaviors= 1; 45505b261ecSmrg } 45605b261ecSmrg if (tmp&XkbVirtualModMapMask) 45705b261ecSmrg _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); 45805b261ecSmrg else if (changed&XkbVirtualModMapMask) { 45905b261ecSmrg mc->changed|= XkbVirtualModMapMask; 46005b261ecSmrg mc->first_vmodmap_key= key; 46105b261ecSmrg mc->num_vmodmap_keys= 1; 46205b261ecSmrg } 46305b261ecSmrg mc->changed|= changed; 46405b261ecSmrg } 46505b261ecSmrg if (interps!=ibuf) 46605b261ecSmrg _XkbFree(interps); 46705b261ecSmrg return True; 46805b261ecSmrg} 46905b261ecSmrg 47005b261ecSmrgStatus 47105b261ecSmrgXkbChangeTypesOfKey( XkbDescPtr xkb, 47205b261ecSmrg int key, 47305b261ecSmrg int nGroups, 47405b261ecSmrg unsigned groups, 47505b261ecSmrg int * newTypesIn, 47605b261ecSmrg XkbMapChangesPtr changes) 47705b261ecSmrg{ 47805b261ecSmrgXkbKeyTypePtr pOldType,pNewType; 47905b261ecSmrgregister int i; 48005b261ecSmrgint width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; 48105b261ecSmrg 48205b261ecSmrg if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || 4834642e01fSmrg (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)|| 48405b261ecSmrg (nGroups>XkbNumKbdGroups)) { 48505b261ecSmrg return BadMatch; 48605b261ecSmrg } 48705b261ecSmrg if (nGroups==0) { 48805b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 48905b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; 49005b261ecSmrg } 49105b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 49205b261ecSmrg i= XkbSetNumGroups(i,0); 49305b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 49405b261ecSmrg XkbResizeKeySyms(xkb,key,0); 49505b261ecSmrg return Success; 49605b261ecSmrg } 49705b261ecSmrg 49805b261ecSmrg nOldGroups= XkbKeyNumGroups(xkb,key); 49905b261ecSmrg oldWidth= XkbKeyGroupsWidth(xkb,key); 50005b261ecSmrg for (width=i=0;i<nGroups;i++) { 50105b261ecSmrg if (groups&(1<<i)) 50205b261ecSmrg newTypes[i]= newTypesIn[i]; 50305b261ecSmrg else if (i<nOldGroups) 50405b261ecSmrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); 50505b261ecSmrg else if (nOldGroups>0) 50605b261ecSmrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 50705b261ecSmrg else newTypes[i]= XkbTwoLevelIndex; 50805b261ecSmrg if (newTypes[i]>xkb->map->num_types) 50905b261ecSmrg return BadMatch; 51005b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 51105b261ecSmrg if (pNewType->num_levels>width) 51205b261ecSmrg width= pNewType->num_levels; 51305b261ecSmrg } 51405b261ecSmrg if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) 51505b261ecSmrg xkb->ctrls->num_groups= nGroups; 51605b261ecSmrg if ((width!=oldWidth)||(nGroups!=nOldGroups)) { 51705b261ecSmrg KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; 51805b261ecSmrg int nCopy; 51905b261ecSmrg 52005b261ecSmrg if (nOldGroups==0) { 52105b261ecSmrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 52205b261ecSmrg if (pSyms!=NULL) { 52305b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 52405b261ecSmrg i= XkbSetNumGroups(i,nGroups); 52505b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 52605b261ecSmrg xkb->map->key_sym_map[key].width= width; 52705b261ecSmrg for (i=0;i<nGroups;i++) { 52805b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 52905b261ecSmrg } 53005b261ecSmrg return Success; 53105b261ecSmrg } 53205b261ecSmrg return BadAlloc; 53305b261ecSmrg } 53405b261ecSmrg pSyms= XkbKeySymsPtr(xkb,key); 53505b261ecSmrg memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 53605b261ecSmrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 53705b261ecSmrg if (pSyms==NULL) 53805b261ecSmrg return BadAlloc; 53905b261ecSmrg bzero(pSyms,width*nGroups*sizeof(KeySym)); 54005b261ecSmrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 54105b261ecSmrg pOldType= XkbKeyKeyType(xkb,key,i); 54205b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 54305b261ecSmrg if (pNewType->num_levels>pOldType->num_levels) 54405b261ecSmrg nCopy= pOldType->num_levels; 54505b261ecSmrg else nCopy= pNewType->num_levels; 54605b261ecSmrg memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); 54705b261ecSmrg } 54805b261ecSmrg if (XkbKeyHasActions(xkb,key)) { 54905b261ecSmrg XkbAction oldActs[XkbMaxSymsPerKey],*pActs; 55005b261ecSmrg pActs= XkbKeyActionsPtr(xkb,key); 55105b261ecSmrg memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); 55205b261ecSmrg pActs= XkbResizeKeyActions(xkb,key,width*nGroups); 55305b261ecSmrg if (pActs==NULL) 55405b261ecSmrg return BadAlloc; 55505b261ecSmrg bzero(pActs,width*nGroups*sizeof(XkbAction)); 55605b261ecSmrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 55705b261ecSmrg pOldType= XkbKeyKeyType(xkb,key,i); 55805b261ecSmrg pNewType= &xkb->map->types[newTypes[i]]; 55905b261ecSmrg if (pNewType->num_levels>pOldType->num_levels) 56005b261ecSmrg nCopy= pOldType->num_levels; 56105b261ecSmrg else nCopy= pNewType->num_levels; 56205b261ecSmrg memcpy(&pActs[i*width],&oldActs[i*oldWidth], 56305b261ecSmrg nCopy*sizeof(XkbAction)); 56405b261ecSmrg } 56505b261ecSmrg } 56605b261ecSmrg i= xkb->map->key_sym_map[key].group_info; 56705b261ecSmrg i= XkbSetNumGroups(i,nGroups); 56805b261ecSmrg xkb->map->key_sym_map[key].group_info= i; 56905b261ecSmrg xkb->map->key_sym_map[key].width= width; 57005b261ecSmrg } 57105b261ecSmrg width= 0; 57205b261ecSmrg for (i=0;i<nGroups;i++) { 57305b261ecSmrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 57405b261ecSmrg if (xkb->map->types[newTypes[i]].num_levels>width) 57505b261ecSmrg width= xkb->map->types[newTypes[i]].num_levels; 57605b261ecSmrg } 57705b261ecSmrg xkb->map->key_sym_map[key].width= width; 57805b261ecSmrg if (changes!=NULL) { 57905b261ecSmrg if (changes->changed&XkbKeySymsMask) { 58005b261ecSmrg _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, 58105b261ecSmrg key); 58205b261ecSmrg } 58305b261ecSmrg else { 58405b261ecSmrg changes->changed|= XkbKeySymsMask; 58505b261ecSmrg changes->first_key_sym= key; 58605b261ecSmrg changes->num_key_syms= 1; 58705b261ecSmrg } 58805b261ecSmrg } 58905b261ecSmrg return Success; 59005b261ecSmrg} 59105b261ecSmrg 59205b261ecSmrg/***====================================================================***/ 59305b261ecSmrg 59405b261ecSmrgBool 59505b261ecSmrgXkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) 59605b261ecSmrg{ 59705b261ecSmrgregister int i,bit; 59805b261ecSmrgregister unsigned mask; 59905b261ecSmrg 60005b261ecSmrg if (xkb==NULL) 60105b261ecSmrg return False; 60205b261ecSmrg if (virtual_mask==0) { 60305b261ecSmrg *mask_rtrn= 0; 60405b261ecSmrg return True; 60505b261ecSmrg } 60605b261ecSmrg if (xkb->server==NULL) 60705b261ecSmrg return False; 60805b261ecSmrg for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 60905b261ecSmrg if (virtual_mask&bit) 61005b261ecSmrg mask|= xkb->server->vmods[i]; 61105b261ecSmrg } 61205b261ecSmrg *mask_rtrn= mask; 61305b261ecSmrg return True; 61405b261ecSmrg} 61505b261ecSmrg 61605b261ecSmrg/***====================================================================***/ 61705b261ecSmrg 61805b261ecSmrgstatic Bool 61905b261ecSmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) 62005b261ecSmrg{ 62105b261ecSmrgunsigned int tmp; 62205b261ecSmrg 62305b261ecSmrg switch (act->type) { 62405b261ecSmrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 62505b261ecSmrg if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { 62605b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 62705b261ecSmrg act->mods.mask= act->mods.real_mods; 62805b261ecSmrg act->mods.mask|= tmp; 62905b261ecSmrg return True; 63005b261ecSmrg } 63105b261ecSmrg break; 63205b261ecSmrg case XkbSA_ISOLock: 63305b261ecSmrg if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { 63405b261ecSmrg XkbVirtualModsToReal(xkb,tmp,&tmp); 63505b261ecSmrg act->iso.mask= act->iso.real_mods; 63605b261ecSmrg act->iso.mask|= tmp; 63705b261ecSmrg return True; 63805b261ecSmrg } 63905b261ecSmrg break; 64005b261ecSmrg } 64105b261ecSmrg return False; 64205b261ecSmrg} 64305b261ecSmrg 64405b261ecSmrgstatic void 64505b261ecSmrgXkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, 64605b261ecSmrg XkbKeyTypePtr type, 64705b261ecSmrg unsigned int changed, 64805b261ecSmrg XkbChangesPtr changes) 64905b261ecSmrg{ 65005b261ecSmrgregister unsigned int i; 65105b261ecSmrgunsigned int mask; 65205b261ecSmrg 65305b261ecSmrg XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); 65405b261ecSmrg type->mods.mask= type->mods.real_mods|mask; 65505b261ecSmrg if ((type->map_count>0)&&(type->mods.vmods!=0)) { 65605b261ecSmrg XkbKTMapEntryPtr entry; 65705b261ecSmrg for (i=0,entry=type->map;i<type->map_count;i++,entry++) { 65805b261ecSmrg if (entry->mods.vmods!=0) { 65905b261ecSmrg XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); 66005b261ecSmrg entry->mods.mask=entry->mods.real_mods|mask; 66105b261ecSmrg /* entry is active if vmods are bound*/ 66205b261ecSmrg entry->active= (mask!=0); 66305b261ecSmrg } 66405b261ecSmrg else entry->active= 1; 66505b261ecSmrg } 66605b261ecSmrg } 66705b261ecSmrg if (changes) { 66805b261ecSmrg int type_ndx; 66905b261ecSmrg type_ndx= type-xkb->map->types; 67005b261ecSmrg if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) 67105b261ecSmrg return; 67205b261ecSmrg if (changes->map.changed&XkbKeyTypesMask) { 67305b261ecSmrg int last; 67405b261ecSmrg last= changes->map.first_type+changes->map.num_types-1; 67505b261ecSmrg if (type_ndx<changes->map.first_type) { 67605b261ecSmrg changes->map.first_type= type_ndx; 67705b261ecSmrg changes->map.num_types= (last-type_ndx)+1; 67805b261ecSmrg } 67905b261ecSmrg else if (type_ndx>last) { 68005b261ecSmrg changes->map.num_types= (type_ndx-changes->map.first_type)+1; 68105b261ecSmrg } 68205b261ecSmrg } 68305b261ecSmrg else { 68405b261ecSmrg changes->map.changed|= XkbKeyTypesMask; 68505b261ecSmrg changes->map.first_type= type_ndx; 68605b261ecSmrg changes->map.num_types= 1; 68705b261ecSmrg } 68805b261ecSmrg } 68905b261ecSmrg return; 69005b261ecSmrg} 69105b261ecSmrg 69205b261ecSmrgBool 69305b261ecSmrgXkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) 69405b261ecSmrg{ 69505b261ecSmrgregister int i; 69605b261ecSmrgunsigned int checkState = 0; 69705b261ecSmrg 69805b261ecSmrg if ((!xkb) || (!xkb->map) || (changed==0)) 69905b261ecSmrg return False; 70005b261ecSmrg for (i=0;i<xkb->map->num_types;i++) { 70105b261ecSmrg if (xkb->map->types[i].mods.vmods & changed) 70205b261ecSmrg XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); 70305b261ecSmrg } 70405b261ecSmrg if (changed&xkb->ctrls->internal.vmods) { 70505b261ecSmrg unsigned int newMask; 70605b261ecSmrg XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); 70705b261ecSmrg newMask|= xkb->ctrls->internal.real_mods; 70805b261ecSmrg if (xkb->ctrls->internal.mask!=newMask) { 70905b261ecSmrg xkb->ctrls->internal.mask= newMask; 71005b261ecSmrg if (changes) { 71105b261ecSmrg changes->ctrls.changed_ctrls|= XkbInternalModsMask; 71205b261ecSmrg checkState= True; 71305b261ecSmrg } 71405b261ecSmrg } 71505b261ecSmrg } 71605b261ecSmrg if (changed&xkb->ctrls->ignore_lock.vmods) { 71705b261ecSmrg unsigned int newMask; 71805b261ecSmrg XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); 71905b261ecSmrg newMask|= xkb->ctrls->ignore_lock.real_mods; 72005b261ecSmrg if (xkb->ctrls->ignore_lock.mask!=newMask) { 72105b261ecSmrg xkb->ctrls->ignore_lock.mask= newMask; 72205b261ecSmrg if (changes) { 72305b261ecSmrg changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; 72405b261ecSmrg checkState= True; 72505b261ecSmrg } 72605b261ecSmrg } 72705b261ecSmrg } 72805b261ecSmrg if (xkb->indicators!=NULL) { 72905b261ecSmrg XkbIndicatorMapPtr map; 73005b261ecSmrg map= &xkb->indicators->maps[0]; 73105b261ecSmrg for (i=0;i<XkbNumIndicators;i++,map++) { 73205b261ecSmrg if (map->mods.vmods&changed) { 73305b261ecSmrg unsigned int newMask; 73405b261ecSmrg XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); 73505b261ecSmrg newMask|= map->mods.real_mods; 73605b261ecSmrg if (newMask!=map->mods.mask) { 73705b261ecSmrg map->mods.mask= newMask; 73805b261ecSmrg if (changes) { 73905b261ecSmrg changes->indicators.map_changes|= (1<<i); 74005b261ecSmrg checkState= True; 74105b261ecSmrg } 74205b261ecSmrg } 74305b261ecSmrg } 74405b261ecSmrg } 74505b261ecSmrg } 74605b261ecSmrg if (xkb->compat!=NULL) { 74705b261ecSmrg XkbCompatMapPtr compat; 74805b261ecSmrg compat= xkb->compat; 74905b261ecSmrg for (i=0;i<XkbNumKbdGroups;i++) { 75005b261ecSmrg unsigned int newMask; 75105b261ecSmrg XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); 75205b261ecSmrg newMask|= compat->groups[i].real_mods; 75305b261ecSmrg if (compat->groups[i].mask!=newMask) { 75405b261ecSmrg compat->groups[i].mask= newMask; 75505b261ecSmrg if (changes) { 75605b261ecSmrg changes->compat.changed_groups|= (1<<i); 75705b261ecSmrg checkState= True; 75805b261ecSmrg } 75905b261ecSmrg } 76005b261ecSmrg } 76105b261ecSmrg } 76205b261ecSmrg if (xkb->map && xkb->server) { 76305b261ecSmrg int highChange = 0, lowChange = -1; 76405b261ecSmrg for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 76505b261ecSmrg if (XkbKeyHasActions(xkb,i)) { 76605b261ecSmrg register XkbAction *pAct; 76705b261ecSmrg register int n; 76805b261ecSmrg 76905b261ecSmrg pAct= XkbKeyActionsPtr(xkb,i); 77005b261ecSmrg for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { 77105b261ecSmrg if ((pAct->type!=XkbSA_NoAction)&& 77205b261ecSmrg XkbUpdateActionVirtualMods(xkb,pAct,changed)) { 77305b261ecSmrg if (lowChange<0) 77405b261ecSmrg lowChange= i; 77505b261ecSmrg highChange= i; 77605b261ecSmrg } 77705b261ecSmrg } 77805b261ecSmrg } 77905b261ecSmrg } 78005b261ecSmrg if (changes && (lowChange>0)) { /* something changed */ 78105b261ecSmrg if (changes->map.changed&XkbKeyActionsMask) { 78205b261ecSmrg int last; 78305b261ecSmrg if (changes->map.first_key_act<lowChange) 78405b261ecSmrg lowChange= changes->map.first_key_act; 78505b261ecSmrg last= changes->map.first_key_act+changes->map.num_key_acts-1; 78605b261ecSmrg if (last>highChange) 78705b261ecSmrg highChange= last; 78805b261ecSmrg } 78905b261ecSmrg changes->map.changed|= XkbKeyActionsMask; 79005b261ecSmrg changes->map.first_key_act= lowChange; 79105b261ecSmrg changes->map.num_key_acts= (highChange-lowChange)+1; 79205b261ecSmrg } 79305b261ecSmrg } 79405b261ecSmrg return checkState; 79505b261ecSmrg} 796