1706f2543Smrg/************************************************************ 2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3706f2543Smrg 4706f2543SmrgPermission to use, copy, modify, and distribute this 5706f2543Smrgsoftware and its documentation for any purpose and without 6706f2543Smrgfee is hereby granted, provided that the above copyright 7706f2543Smrgnotice appear in all copies and that both that copyright 8706f2543Smrgnotice and this permission notice appear in supporting 9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be 10706f2543Smrgused in advertising or publicity pertaining to distribution 11706f2543Smrgof the software without specific prior written permission. 12706f2543SmrgSilicon Graphics makes no representation about the suitability 13706f2543Smrgof this software for any purpose. It is provided "as is" 14706f2543Smrgwithout any express or implied warranty. 15706f2543Smrg 16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 24706f2543Smrg 25706f2543Smrg********************************************************/ 26706f2543Smrg 27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 28706f2543Smrg#include <dix-config.h> 29706f2543Smrg#elif defined(HAVE_CONFIG_H) 30706f2543Smrg#include <config.h> 31706f2543Smrg#endif 32706f2543Smrg 33706f2543Smrg#include <stdio.h> 34706f2543Smrg#include <X11/X.h> 35706f2543Smrg#include <X11/Xproto.h> 36706f2543Smrg#include "misc.h" 37706f2543Smrg#include "inputstr.h" 38706f2543Smrg#include <X11/keysym.h> 39706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS 40706f2543Smrg#include <xkbsrv.h> 41706f2543Smrg 42706f2543Smrg/***====================================================================***/ 43706f2543Smrg 44706f2543Smrg#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 45706f2543Smrg#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 46706f2543Smrg 47706f2543Smrgint 48706f2543SmrgXkbKeyTypesForCoreSymbols( XkbDescPtr xkb, 49706f2543Smrg int map_width, 50706f2543Smrg KeySym * core_syms, 51706f2543Smrg unsigned int protected, 52706f2543Smrg int * types_inout, 53706f2543Smrg KeySym * xkb_syms_rtrn) 54706f2543Smrg{ 55706f2543Smrgregister int i; 56706f2543Smrgunsigned int empty; 57706f2543Smrgint nSyms[XkbNumKbdGroups]; 58706f2543Smrgint nGroups,tmp,groupsWidth; 59706f2543SmrgBOOL replicated = FALSE; 60706f2543Smrg 61706f2543Smrg /* Section 12.2 of the protocol describes this process in more detail */ 62706f2543Smrg /* Step 1: find the # of symbols in the core mapping per group */ 63706f2543Smrg groupsWidth= 2; 64706f2543Smrg for (i=0;i<XkbNumKbdGroups;i++) { 65706f2543Smrg if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { 66706f2543Smrg nSyms[i]= xkb->map->types[types_inout[i]].num_levels; 67706f2543Smrg if (nSyms[i]>groupsWidth) 68706f2543Smrg groupsWidth= nSyms[i]; 69706f2543Smrg } 70706f2543Smrg else { 71706f2543Smrg types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ 72706f2543Smrg nSyms[i]= 2; 73706f2543Smrg } 74706f2543Smrg } 75706f2543Smrg if (nSyms[XkbGroup1Index]<2) 76706f2543Smrg nSyms[XkbGroup1Index]= 2; 77706f2543Smrg if (nSyms[XkbGroup2Index]<2) 78706f2543Smrg nSyms[XkbGroup2Index]= 2; 79706f2543Smrg /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 80706f2543Smrg /* symbols in the core are in the order: */ 81706f2543Smrg /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 82706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); 83706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); 84706f2543Smrg for (i=2;i<nSyms[XkbGroup1Index];i++) { 85706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); 86706f2543Smrg } 87706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); 88706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); 89706f2543Smrg tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ 90706f2543Smrg for (i=2;i<nSyms[XkbGroup2Index];i++) { 91706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); 92706f2543Smrg } 93706f2543Smrg 94706f2543Smrg /* Special case: if only the first group is explicit, and the symbols 95706f2543Smrg * replicate across all groups, then we have a Section 12.4 replication */ 96706f2543Smrg if ((protected & ~XkbExplicitKeyType1Mask) == 0) 97706f2543Smrg { 98706f2543Smrg int j, width = nSyms[XkbGroup1Index]; 99706f2543Smrg 100706f2543Smrg replicated = TRUE; 101706f2543Smrg 102706f2543Smrg /* Check ABAB in ABABCDECDEABCDE */ 103706f2543Smrg if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) || 104706f2543Smrg (width > 1 && CORE_SYM(1) != CORE_SYM(3))) 105706f2543Smrg replicated = FALSE; 106706f2543Smrg 107706f2543Smrg /* Check CDECDE in ABABCDECDEABCDE */ 108706f2543Smrg for (i = 2; i < width && replicated; i++) 109706f2543Smrg { 110706f2543Smrg if (CORE_SYM(2 + i) != CORE_SYM(i + width)) 111706f2543Smrg replicated = FALSE; 112706f2543Smrg } 113706f2543Smrg 114706f2543Smrg /* Check ABCDE in ABABCDECDEABCDE */ 115706f2543Smrg for (j = 2; replicated && 116706f2543Smrg j < XkbNumKbdGroups && 117706f2543Smrg map_width >= width * (j + 1); j++) 118706f2543Smrg { 119706f2543Smrg for (i = 0; i < width && replicated; i++) 120706f2543Smrg { 121706f2543Smrg if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j)) 122706f2543Smrg replicated = FALSE; 123706f2543Smrg } 124706f2543Smrg } 125706f2543Smrg } 126706f2543Smrg 127706f2543Smrg if (replicated) 128706f2543Smrg { 129706f2543Smrg nSyms[XkbGroup2Index]= 0; 130706f2543Smrg nSyms[XkbGroup3Index]= 0; 131706f2543Smrg nSyms[XkbGroup4Index]= 0; 132706f2543Smrg nGroups= 1; 133706f2543Smrg } else 134706f2543Smrg { 135706f2543Smrg tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; 136706f2543Smrg if ((tmp>=map_width)&& 137706f2543Smrg ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { 138706f2543Smrg nSyms[XkbGroup3Index]= 0; 139706f2543Smrg nSyms[XkbGroup4Index]= 0; 140706f2543Smrg nGroups= 2; 141706f2543Smrg } else 142706f2543Smrg { 143706f2543Smrg nGroups= 3; 144706f2543Smrg for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { 145706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); 146706f2543Smrg } 147706f2543Smrg if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { 148706f2543Smrg nGroups= 4; 149706f2543Smrg for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { 150706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); 151706f2543Smrg } 152706f2543Smrg } 153706f2543Smrg else { 154706f2543Smrg nSyms[XkbGroup4Index]= 0; 155706f2543Smrg } 156706f2543Smrg } 157706f2543Smrg } 158706f2543Smrg /* steps 3&4: alphanumeric expansion, assign canonical types */ 159706f2543Smrg empty= 0; 160706f2543Smrg for (i=0;i<nGroups;i++) { 161706f2543Smrg KeySym *syms; 162706f2543Smrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 163706f2543Smrg if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { 164706f2543Smrg KeySym upper,lower; 165706f2543Smrg XkbConvertCase(syms[0],&lower,&upper); 166706f2543Smrg if (upper!=lower) { 167706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; 168706f2543Smrg xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; 169706f2543Smrg if ((protected&(1<<i))==0) 170706f2543Smrg types_inout[i]= XkbAlphabeticIndex; 171706f2543Smrg } 172706f2543Smrg else if ((protected&(1<<i))==0) { 173706f2543Smrg types_inout[i]= XkbOneLevelIndex; 174706f2543Smrg /* nSyms[i]= 1;*/ 175706f2543Smrg } 176706f2543Smrg } 177706f2543Smrg if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { 178706f2543Smrg if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) 179706f2543Smrg types_inout[i]= XkbKeypadIndex; 180706f2543Smrg else { 181706f2543Smrg KeySym upper,lower; 182706f2543Smrg XkbConvertCase(syms[0],&lower,&upper); 183706f2543Smrg if ((syms[0]==lower)&&(syms[1]==upper)) 184706f2543Smrg types_inout[i]= XkbAlphabeticIndex; 185706f2543Smrg } 186706f2543Smrg } 187706f2543Smrg if (syms[0]==NoSymbol) { 188706f2543Smrg register int n; 189706f2543Smrg Bool found; 190706f2543Smrg for (n=1,found=FALSE;(!found)&&(n<nSyms[i]);n++) { 191706f2543Smrg found= (syms[n]!=NoSymbol); 192706f2543Smrg } 193706f2543Smrg if (!found) 194706f2543Smrg empty|= (1<<i); 195706f2543Smrg } 196706f2543Smrg } 197706f2543Smrg /* step 5: squoosh out empty groups */ 198706f2543Smrg if (empty) { 199706f2543Smrg for (i=nGroups-1;i>=0;i--) { 200706f2543Smrg if (((empty&(1<<i))==0)||(protected&(1<<i))) 201706f2543Smrg break; 202706f2543Smrg nGroups--; 203706f2543Smrg } 204706f2543Smrg } 205706f2543Smrg if (nGroups<1) 206706f2543Smrg return 0; 207706f2543Smrg 208706f2543Smrg /* step 6: replicate group 1 into group two, if necessary */ 209706f2543Smrg if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { 210706f2543Smrg if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { 211706f2543Smrg nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; 212706f2543Smrg types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; 213706f2543Smrg memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, 214706f2543Smrg 2*sizeof(KeySym)); 215706f2543Smrg } 216706f2543Smrg else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { 217706f2543Smrg memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], 218706f2543Smrg (char *)xkb_syms_rtrn, 219706f2543Smrg nSyms[XkbGroup1Index]*sizeof(KeySym)); 220706f2543Smrg } 221706f2543Smrg } 222706f2543Smrg 223706f2543Smrg /* step 7: check for all groups identical or all width 1 224706f2543Smrg * 225706f2543Smrg * Special feature: if group 1 has an explicit type and all other groups 226706f2543Smrg * have canonical types with same symbols, we assume it's info lost from 227706f2543Smrg * the core replication. 228706f2543Smrg */ 229706f2543Smrg if (nGroups>1) { 230706f2543Smrg Bool sameType,allOneLevel, canonical = TRUE; 231706f2543Smrg allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); 232706f2543Smrg for (i=1,sameType=TRUE;(allOneLevel||sameType)&&(i<nGroups);i++) { 233706f2543Smrg sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); 234706f2543Smrg if (allOneLevel) 235706f2543Smrg allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); 236706f2543Smrg if (types_inout[i] > XkbLastRequiredType) 237706f2543Smrg canonical = FALSE; 238706f2543Smrg } 239706f2543Smrg if (((sameType) || canonical)&& 240706f2543Smrg (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ 241706f2543Smrg register int s; 242706f2543Smrg Bool identical; 243706f2543Smrg for (i=1,identical=TRUE;identical&&(i<nGroups);i++) { 244706f2543Smrg KeySym *syms; 245706f2543Smrg if (nSyms[i] != nSyms[XkbGroup1Index]) 246706f2543Smrg identical = FALSE; 247706f2543Smrg syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 248706f2543Smrg for (s=0;identical&&(s<nSyms[i]);s++) { 249706f2543Smrg if (syms[s]!=xkb_syms_rtrn[s]) 250706f2543Smrg identical= FALSE; 251706f2543Smrg } 252706f2543Smrg } 253706f2543Smrg if (identical) 254706f2543Smrg nGroups= 1; 255706f2543Smrg } 256706f2543Smrg if (allOneLevel && (nGroups>1)) { 257706f2543Smrg KeySym *syms; 258706f2543Smrg syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 259706f2543Smrg nSyms[XkbGroup1Index]= 1; 260706f2543Smrg for (i=1;i<nGroups;i++) { 261706f2543Smrg xkb_syms_rtrn[i]= syms[0]; 262706f2543Smrg syms+= nSyms[i]; 263706f2543Smrg nSyms[i]= 1; 264706f2543Smrg } 265706f2543Smrg } 266706f2543Smrg } 267706f2543Smrg return nGroups; 268706f2543Smrg} 269706f2543Smrg 270706f2543Smrgstatic XkbSymInterpretPtr 271706f2543Smrg_XkbFindMatchingInterp( XkbDescPtr xkb, 272706f2543Smrg KeySym sym, 273706f2543Smrg unsigned int real_mods, 274706f2543Smrg unsigned int level) 275706f2543Smrg{ 276706f2543Smrgregister unsigned i; 277706f2543SmrgXkbSymInterpretPtr interp,rtrn; 278706f2543SmrgCARD8 mods; 279706f2543Smrg 280706f2543Smrg rtrn= NULL; 281706f2543Smrg interp= xkb->compat->sym_interpret; 282706f2543Smrg for (i=0;i<xkb->compat->num_si;i++,interp++) { 283706f2543Smrg if ((interp->sym==NoSymbol)||(sym==interp->sym)) { 284706f2543Smrg int match; 285706f2543Smrg if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) 286706f2543Smrg mods= real_mods; 287706f2543Smrg else mods= 0; 288706f2543Smrg switch (interp->match&XkbSI_OpMask) { 289706f2543Smrg case XkbSI_NoneOf: 290706f2543Smrg match= ((interp->mods&mods)==0); 291706f2543Smrg break; 292706f2543Smrg case XkbSI_AnyOfOrNone: 293706f2543Smrg match= ((mods==0)||((interp->mods&mods)!=0)); 294706f2543Smrg break; 295706f2543Smrg case XkbSI_AnyOf: 296706f2543Smrg match= ((interp->mods&mods)!=0); 297706f2543Smrg break; 298706f2543Smrg case XkbSI_AllOf: 299706f2543Smrg match= ((interp->mods&mods)==interp->mods); 300706f2543Smrg break; 301706f2543Smrg case XkbSI_Exactly: 302706f2543Smrg match= (interp->mods==mods); 303706f2543Smrg break; 304706f2543Smrg default: 305706f2543Smrg match= 0; 306706f2543Smrg break; 307706f2543Smrg } 308706f2543Smrg if (match) { 309706f2543Smrg if (interp->sym!=NoSymbol) { 310706f2543Smrg return interp; 311706f2543Smrg } 312706f2543Smrg else if (rtrn==NULL) { 313706f2543Smrg rtrn= interp; 314706f2543Smrg } 315706f2543Smrg } 316706f2543Smrg } 317706f2543Smrg } 318706f2543Smrg return rtrn; 319706f2543Smrg} 320706f2543Smrg 321706f2543Smrgstatic void 322706f2543Smrg_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) 323706f2543Smrg{ 324706f2543SmrgKeyCode last; 325706f2543Smrg 326706f2543Smrg last= (*pFirst)+(*pNum); 327706f2543Smrg if (newKey<*pFirst) { 328706f2543Smrg *pFirst= newKey; 329706f2543Smrg *pNum= (last-newKey)+1; 330706f2543Smrg } 331706f2543Smrg else if (newKey>last) { 332706f2543Smrg *pNum= (last-*pFirst)+1; 333706f2543Smrg } 334706f2543Smrg return; 335706f2543Smrg} 336706f2543Smrg 337706f2543Smrgstatic void 338706f2543Smrg_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 339706f2543Smrg{ 340706f2543Smrgunsigned tmp; 341706f2543Smrg 342706f2543Smrg switch (act->type) { 343706f2543Smrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 344706f2543Smrg if (act->mods.flags&XkbSA_UseModMapMods) 345706f2543Smrg act->mods.real_mods= act->mods.mask= mods; 346706f2543Smrg if ((tmp= XkbModActionVMods(&act->mods))!=0) { 347706f2543Smrg XkbVirtualModsToReal(xkb,tmp,&tmp); 348706f2543Smrg act->mods.mask|= tmp; 349706f2543Smrg } 350706f2543Smrg break; 351706f2543Smrg case XkbSA_ISOLock: 352706f2543Smrg if (act->iso.flags&XkbSA_UseModMapMods) 353706f2543Smrg act->iso.real_mods= act->iso.mask= mods; 354706f2543Smrg if ((tmp= XkbModActionVMods(&act->iso))!=0) { 355706f2543Smrg XkbVirtualModsToReal(xkb,tmp,&tmp); 356706f2543Smrg act->iso.mask|= tmp; 357706f2543Smrg } 358706f2543Smrg break; 359706f2543Smrg } 360706f2543Smrg return; 361706f2543Smrg} 362706f2543Smrg 363706f2543Smrg#define IBUF_SIZE 8 364706f2543Smrg 365706f2543SmrgBool 366706f2543SmrgXkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) 367706f2543Smrg{ 368706f2543SmrgKeySym * syms; 369706f2543Smrgunsigned char explicit,mods; 370706f2543SmrgXkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; 371706f2543Smrgint n,nSyms,found; 372706f2543Smrgunsigned changed,tmp; 373706f2543Smrg 374706f2543Smrg if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| 375706f2543Smrg (!xkb->compat)||(!xkb->compat->sym_interpret)|| 376706f2543Smrg (key<xkb->min_key_code)||(key>xkb->max_key_code)) { 377706f2543Smrg return FALSE; 378706f2543Smrg } 379706f2543Smrg if (((!xkb->server)||(!xkb->server->key_acts))&& 380706f2543Smrg (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { 381706f2543Smrg return FALSE; 382706f2543Smrg } 383706f2543Smrg changed= 0; /* keeps track of what has changed in _this_ call */ 384706f2543Smrg explicit= xkb->server->explicit[key]; 385706f2543Smrg if (explicit&XkbExplicitInterpretMask) /* nothing to do */ 386706f2543Smrg return TRUE; 387706f2543Smrg mods= (xkb->map->modmap?xkb->map->modmap[key]:0); 388706f2543Smrg nSyms= XkbKeyNumSyms(xkb,key); 389706f2543Smrg syms= XkbKeySymsPtr(xkb,key); 390706f2543Smrg if (nSyms>IBUF_SIZE) { 391706f2543Smrg interps= calloc(nSyms, sizeof(XkbSymInterpretPtr)); 392706f2543Smrg if (interps==NULL) { 393706f2543Smrg interps= ibuf; 394706f2543Smrg nSyms= IBUF_SIZE; 395706f2543Smrg } 396706f2543Smrg } 397706f2543Smrg else { 398706f2543Smrg interps= ibuf; 399706f2543Smrg } 400706f2543Smrg found= 0; 401706f2543Smrg for (n=0;n<nSyms;n++) { 402706f2543Smrg unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); 403706f2543Smrg interps[n]= NULL; 404706f2543Smrg if (syms[n]!=NoSymbol) { 405706f2543Smrg interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); 406706f2543Smrg if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) 407706f2543Smrg found++; 408706f2543Smrg else interps[n]= NULL; 409706f2543Smrg } 410706f2543Smrg } 411706f2543Smrg /* 1/28/96 (ef) -- XXX! WORKING HERE */ 412706f2543Smrg if (!found) { 413706f2543Smrg if (xkb->server->key_acts[key]!=0) { 414706f2543Smrg xkb->server->key_acts[key]= 0; 415706f2543Smrg changed|= XkbKeyActionsMask; 416706f2543Smrg } 417706f2543Smrg } 418706f2543Smrg else { 419706f2543Smrg XkbAction *pActs; 420706f2543Smrg unsigned int new_vmodmask; 421706f2543Smrg changed|= XkbKeyActionsMask; 422706f2543Smrg pActs= XkbResizeKeyActions(xkb,key,nSyms); 423706f2543Smrg if (!pActs) { 424706f2543Smrg if (nSyms > IBUF_SIZE) 425706f2543Smrg free(interps); 426706f2543Smrg return FALSE; 427706f2543Smrg } 428706f2543Smrg new_vmodmask= 0; 429706f2543Smrg for (n=0;n<nSyms;n++) { 430706f2543Smrg if (interps[n]) { 431706f2543Smrg unsigned effMods; 432706f2543Smrg 433706f2543Smrg pActs[n]= *((XkbAction *)&interps[n]->act); 434706f2543Smrg if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { 435706f2543Smrg effMods= mods; 436706f2543Smrg if (interps[n]->virtual_mod!=XkbNoModifier) 437706f2543Smrg new_vmodmask|= (1<<interps[n]->virtual_mod); 438706f2543Smrg } 439706f2543Smrg else effMods= 0; 440706f2543Smrg _XkbSetActionKeyMods(xkb,&pActs[n],effMods); 441706f2543Smrg } 442706f2543Smrg else pActs[n].type= XkbSA_NoAction; 443706f2543Smrg } 444706f2543Smrg if (((explicit&XkbExplicitVModMapMask)==0)&& 445706f2543Smrg (xkb->server->vmodmap[key]!=new_vmodmask)) { 446706f2543Smrg changed|= XkbVirtualModMapMask; 447706f2543Smrg xkb->server->vmodmap[key]= new_vmodmask; 448706f2543Smrg } 449706f2543Smrg if (interps[0]) { 450706f2543Smrg if ((interps[0]->flags&XkbSI_LockingKey)&& 451706f2543Smrg ((explicit&XkbExplicitBehaviorMask)==0)) { 452706f2543Smrg xkb->server->behaviors[key].type= XkbKB_Lock; 453706f2543Smrg changed|= XkbKeyBehaviorsMask; 454706f2543Smrg } 455706f2543Smrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 456706f2543Smrg CARD8 old; 457706f2543Smrg old= BitIsOn(xkb->ctrls->per_key_repeat, key); 458706f2543Smrg if (interps[0]->flags&XkbSI_AutoRepeat) 459706f2543Smrg SetBit(xkb->ctrls->per_key_repeat, key); 460706f2543Smrg else 461706f2543Smrg ClearBit(xkb->ctrls->per_key_repeat, key); 462706f2543Smrg if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key)) 463706f2543Smrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 464706f2543Smrg } 465706f2543Smrg } 466706f2543Smrg } 467706f2543Smrg if ((!found)||(interps[0]==NULL)) { 468706f2543Smrg if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 469706f2543Smrg CARD8 old; 470706f2543Smrg old = BitIsOn(xkb->ctrls->per_key_repeat, key); 471706f2543Smrg SetBit(xkb->ctrls->per_key_repeat, key); 472706f2543Smrg if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key))) 473706f2543Smrg changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 474706f2543Smrg } 475706f2543Smrg if (((explicit&XkbExplicitBehaviorMask)==0)&& 476706f2543Smrg (xkb->server->behaviors[key].type==XkbKB_Lock)) { 477706f2543Smrg xkb->server->behaviors[key].type= XkbKB_Default; 478706f2543Smrg changed|= XkbKeyBehaviorsMask; 479706f2543Smrg } 480706f2543Smrg } 481706f2543Smrg if (changes) { 482706f2543Smrg XkbMapChangesPtr mc; 483706f2543Smrg mc= &changes->map; 484706f2543Smrg tmp= (changed&mc->changed); 485706f2543Smrg if (tmp&XkbKeyActionsMask) 486706f2543Smrg _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); 487706f2543Smrg else if (changed&XkbKeyActionsMask) { 488706f2543Smrg mc->changed|= XkbKeyActionsMask; 489706f2543Smrg mc->first_key_act= key; 490706f2543Smrg mc->num_key_acts= 1; 491706f2543Smrg } 492706f2543Smrg if (tmp&XkbKeyBehaviorsMask) { 493706f2543Smrg _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, 494706f2543Smrg key); 495706f2543Smrg } 496706f2543Smrg else if (changed&XkbKeyBehaviorsMask) { 497706f2543Smrg mc->changed|= XkbKeyBehaviorsMask; 498706f2543Smrg mc->first_key_behavior= key; 499706f2543Smrg mc->num_key_behaviors= 1; 500706f2543Smrg } 501706f2543Smrg if (tmp&XkbVirtualModMapMask) 502706f2543Smrg _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); 503706f2543Smrg else if (changed&XkbVirtualModMapMask) { 504706f2543Smrg mc->changed|= XkbVirtualModMapMask; 505706f2543Smrg mc->first_vmodmap_key= key; 506706f2543Smrg mc->num_vmodmap_keys= 1; 507706f2543Smrg } 508706f2543Smrg mc->changed|= changed; 509706f2543Smrg } 510706f2543Smrg if (interps!=ibuf) 511706f2543Smrg free(interps); 512706f2543Smrg return TRUE; 513706f2543Smrg} 514706f2543Smrg 515706f2543SmrgStatus 516706f2543SmrgXkbChangeTypesOfKey( XkbDescPtr xkb, 517706f2543Smrg int key, 518706f2543Smrg int nGroups, 519706f2543Smrg unsigned groups, 520706f2543Smrg int * newTypesIn, 521706f2543Smrg XkbMapChangesPtr changes) 522706f2543Smrg{ 523706f2543SmrgXkbKeyTypePtr pOldType,pNewType; 524706f2543Smrgregister int i; 525706f2543Smrgint width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; 526706f2543Smrg 527706f2543Smrg if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || 528706f2543Smrg (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)|| 529706f2543Smrg (nGroups>XkbNumKbdGroups)) { 530706f2543Smrg return BadMatch; 531706f2543Smrg } 532706f2543Smrg if (nGroups==0) { 533706f2543Smrg for (i=0;i<XkbNumKbdGroups;i++) { 534706f2543Smrg xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; 535706f2543Smrg } 536706f2543Smrg i= xkb->map->key_sym_map[key].group_info; 537706f2543Smrg i= XkbSetNumGroups(i,0); 538706f2543Smrg xkb->map->key_sym_map[key].group_info= i; 539706f2543Smrg XkbResizeKeySyms(xkb,key,0); 540706f2543Smrg return Success; 541706f2543Smrg } 542706f2543Smrg 543706f2543Smrg nOldGroups= XkbKeyNumGroups(xkb,key); 544706f2543Smrg oldWidth= XkbKeyGroupsWidth(xkb,key); 545706f2543Smrg for (width=i=0;i<nGroups;i++) { 546706f2543Smrg if (groups&(1<<i)) 547706f2543Smrg newTypes[i]= newTypesIn[i]; 548706f2543Smrg else if (i<nOldGroups) 549706f2543Smrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); 550706f2543Smrg else if (nOldGroups>0) 551706f2543Smrg newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 552706f2543Smrg else newTypes[i]= XkbTwoLevelIndex; 553706f2543Smrg if (newTypes[i]>xkb->map->num_types) 554706f2543Smrg return BadMatch; 555706f2543Smrg pNewType= &xkb->map->types[newTypes[i]]; 556706f2543Smrg if (pNewType->num_levels>width) 557706f2543Smrg width= pNewType->num_levels; 558706f2543Smrg } 559706f2543Smrg if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) 560706f2543Smrg xkb->ctrls->num_groups= nGroups; 561706f2543Smrg if ((width!=oldWidth)||(nGroups!=nOldGroups)) { 562706f2543Smrg KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; 563706f2543Smrg int nCopy; 564706f2543Smrg 565706f2543Smrg if (nOldGroups==0) { 566706f2543Smrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 567706f2543Smrg if (pSyms!=NULL) { 568706f2543Smrg i= xkb->map->key_sym_map[key].group_info; 569706f2543Smrg i= XkbSetNumGroups(i,nGroups); 570706f2543Smrg xkb->map->key_sym_map[key].group_info= i; 571706f2543Smrg xkb->map->key_sym_map[key].width= width; 572706f2543Smrg for (i=0;i<nGroups;i++) { 573706f2543Smrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 574706f2543Smrg } 575706f2543Smrg return Success; 576706f2543Smrg } 577706f2543Smrg return BadAlloc; 578706f2543Smrg } 579706f2543Smrg pSyms= XkbKeySymsPtr(xkb,key); 580706f2543Smrg memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 581706f2543Smrg pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 582706f2543Smrg if (pSyms==NULL) 583706f2543Smrg return BadAlloc; 584706f2543Smrg memset(pSyms, 0, width*nGroups*sizeof(KeySym)); 585706f2543Smrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 586706f2543Smrg pOldType= XkbKeyKeyType(xkb,key,i); 587706f2543Smrg pNewType= &xkb->map->types[newTypes[i]]; 588706f2543Smrg if (pNewType->num_levels>pOldType->num_levels) 589706f2543Smrg nCopy= pOldType->num_levels; 590706f2543Smrg else nCopy= pNewType->num_levels; 591706f2543Smrg memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); 592706f2543Smrg } 593706f2543Smrg if (XkbKeyHasActions(xkb,key)) { 594706f2543Smrg XkbAction oldActs[XkbMaxSymsPerKey],*pActs; 595706f2543Smrg pActs= XkbKeyActionsPtr(xkb,key); 596706f2543Smrg memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); 597706f2543Smrg pActs= XkbResizeKeyActions(xkb,key,width*nGroups); 598706f2543Smrg if (pActs==NULL) 599706f2543Smrg return BadAlloc; 600706f2543Smrg memset(pActs, 0, width*nGroups*sizeof(XkbAction)); 601706f2543Smrg for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 602706f2543Smrg pOldType= XkbKeyKeyType(xkb,key,i); 603706f2543Smrg pNewType= &xkb->map->types[newTypes[i]]; 604706f2543Smrg if (pNewType->num_levels>pOldType->num_levels) 605706f2543Smrg nCopy= pOldType->num_levels; 606706f2543Smrg else nCopy= pNewType->num_levels; 607706f2543Smrg memcpy(&pActs[i*width],&oldActs[i*oldWidth], 608706f2543Smrg nCopy*sizeof(XkbAction)); 609706f2543Smrg } 610706f2543Smrg } 611706f2543Smrg i= xkb->map->key_sym_map[key].group_info; 612706f2543Smrg i= XkbSetNumGroups(i,nGroups); 613706f2543Smrg xkb->map->key_sym_map[key].group_info= i; 614706f2543Smrg xkb->map->key_sym_map[key].width= width; 615706f2543Smrg } 616706f2543Smrg width= 0; 617706f2543Smrg for (i=0;i<nGroups;i++) { 618706f2543Smrg xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 619706f2543Smrg if (xkb->map->types[newTypes[i]].num_levels>width) 620706f2543Smrg width= xkb->map->types[newTypes[i]].num_levels; 621706f2543Smrg } 622706f2543Smrg xkb->map->key_sym_map[key].width= width; 623706f2543Smrg if (changes!=NULL) { 624706f2543Smrg if (changes->changed&XkbKeySymsMask) { 625706f2543Smrg _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, 626706f2543Smrg key); 627706f2543Smrg } 628706f2543Smrg else { 629706f2543Smrg changes->changed|= XkbKeySymsMask; 630706f2543Smrg changes->first_key_sym= key; 631706f2543Smrg changes->num_key_syms= 1; 632706f2543Smrg } 633706f2543Smrg } 634706f2543Smrg return Success; 635706f2543Smrg} 636706f2543Smrg 637706f2543Smrg/***====================================================================***/ 638706f2543Smrg 639706f2543SmrgBool 640706f2543SmrgXkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) 641706f2543Smrg{ 642706f2543Smrgregister int i,bit; 643706f2543Smrgregister unsigned mask; 644706f2543Smrg 645706f2543Smrg if (xkb==NULL) 646706f2543Smrg return FALSE; 647706f2543Smrg if (virtual_mask==0) { 648706f2543Smrg *mask_rtrn= 0; 649706f2543Smrg return TRUE; 650706f2543Smrg } 651706f2543Smrg if (xkb->server==NULL) 652706f2543Smrg return FALSE; 653706f2543Smrg for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 654706f2543Smrg if (virtual_mask&bit) 655706f2543Smrg mask|= xkb->server->vmods[i]; 656706f2543Smrg } 657706f2543Smrg *mask_rtrn= mask; 658706f2543Smrg return TRUE; 659706f2543Smrg} 660706f2543Smrg 661706f2543Smrg/***====================================================================***/ 662706f2543Smrg 663706f2543Smrgstatic Bool 664706f2543SmrgXkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) 665706f2543Smrg{ 666706f2543Smrgunsigned int tmp; 667706f2543Smrg 668706f2543Smrg switch (act->type) { 669706f2543Smrg case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 670706f2543Smrg if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { 671706f2543Smrg XkbVirtualModsToReal(xkb,tmp,&tmp); 672706f2543Smrg act->mods.mask= act->mods.real_mods; 673706f2543Smrg act->mods.mask|= tmp; 674706f2543Smrg return TRUE; 675706f2543Smrg } 676706f2543Smrg break; 677706f2543Smrg case XkbSA_ISOLock: 678706f2543Smrg if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { 679706f2543Smrg XkbVirtualModsToReal(xkb,tmp,&tmp); 680706f2543Smrg act->iso.mask= act->iso.real_mods; 681706f2543Smrg act->iso.mask|= tmp; 682706f2543Smrg return TRUE; 683706f2543Smrg } 684706f2543Smrg break; 685706f2543Smrg } 686706f2543Smrg return FALSE; 687706f2543Smrg} 688706f2543Smrg 689706f2543Smrgstatic void 690706f2543SmrgXkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, 691706f2543Smrg XkbKeyTypePtr type, 692706f2543Smrg unsigned int changed, 693706f2543Smrg XkbChangesPtr changes) 694706f2543Smrg{ 695706f2543Smrgregister unsigned int i; 696706f2543Smrgunsigned int mask; 697706f2543Smrg 698706f2543Smrg XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); 699706f2543Smrg type->mods.mask= type->mods.real_mods|mask; 700706f2543Smrg if ((type->map_count>0)&&(type->mods.vmods!=0)) { 701706f2543Smrg XkbKTMapEntryPtr entry; 702706f2543Smrg for (i=0,entry=type->map;i<type->map_count;i++,entry++) { 703706f2543Smrg if (entry->mods.vmods!=0) { 704706f2543Smrg XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); 705706f2543Smrg entry->mods.mask=entry->mods.real_mods|mask; 706706f2543Smrg /* entry is active if vmods are bound*/ 707706f2543Smrg entry->active= (mask!=0); 708706f2543Smrg } 709706f2543Smrg else entry->active= 1; 710706f2543Smrg } 711706f2543Smrg } 712706f2543Smrg if (changes) { 713706f2543Smrg int type_ndx; 714706f2543Smrg type_ndx= type-xkb->map->types; 715706f2543Smrg if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) 716706f2543Smrg return; 717706f2543Smrg if (changes->map.changed&XkbKeyTypesMask) { 718706f2543Smrg int last; 719706f2543Smrg last= changes->map.first_type+changes->map.num_types-1; 720706f2543Smrg if (type_ndx<changes->map.first_type) { 721706f2543Smrg changes->map.first_type= type_ndx; 722706f2543Smrg changes->map.num_types= (last-type_ndx)+1; 723706f2543Smrg } 724706f2543Smrg else if (type_ndx>last) { 725706f2543Smrg changes->map.num_types= (type_ndx-changes->map.first_type)+1; 726706f2543Smrg } 727706f2543Smrg } 728706f2543Smrg else { 729706f2543Smrg changes->map.changed|= XkbKeyTypesMask; 730706f2543Smrg changes->map.first_type= type_ndx; 731706f2543Smrg changes->map.num_types= 1; 732706f2543Smrg } 733706f2543Smrg } 734706f2543Smrg return; 735706f2543Smrg} 736706f2543Smrg 737706f2543SmrgBool 738706f2543SmrgXkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) 739706f2543Smrg{ 740706f2543Smrgregister int i; 741706f2543Smrgunsigned int checkState = 0; 742706f2543Smrg 743706f2543Smrg if ((!xkb) || (!xkb->map) || (changed==0)) 744706f2543Smrg return FALSE; 745706f2543Smrg for (i=0;i<xkb->map->num_types;i++) { 746706f2543Smrg if (xkb->map->types[i].mods.vmods & changed) 747706f2543Smrg XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); 748706f2543Smrg } 749706f2543Smrg if (changed&xkb->ctrls->internal.vmods) { 750706f2543Smrg unsigned int newMask; 751706f2543Smrg XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); 752706f2543Smrg newMask|= xkb->ctrls->internal.real_mods; 753706f2543Smrg if (xkb->ctrls->internal.mask!=newMask) { 754706f2543Smrg xkb->ctrls->internal.mask= newMask; 755706f2543Smrg if (changes) { 756706f2543Smrg changes->ctrls.changed_ctrls|= XkbInternalModsMask; 757706f2543Smrg checkState= TRUE; 758706f2543Smrg } 759706f2543Smrg } 760706f2543Smrg } 761706f2543Smrg if (changed&xkb->ctrls->ignore_lock.vmods) { 762706f2543Smrg unsigned int newMask; 763706f2543Smrg XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); 764706f2543Smrg newMask|= xkb->ctrls->ignore_lock.real_mods; 765706f2543Smrg if (xkb->ctrls->ignore_lock.mask!=newMask) { 766706f2543Smrg xkb->ctrls->ignore_lock.mask= newMask; 767706f2543Smrg if (changes) { 768706f2543Smrg changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; 769706f2543Smrg checkState= TRUE; 770706f2543Smrg } 771706f2543Smrg } 772706f2543Smrg } 773706f2543Smrg if (xkb->indicators!=NULL) { 774706f2543Smrg XkbIndicatorMapPtr map; 775706f2543Smrg map= &xkb->indicators->maps[0]; 776706f2543Smrg for (i=0;i<XkbNumIndicators;i++,map++) { 777706f2543Smrg if (map->mods.vmods&changed) { 778706f2543Smrg unsigned int newMask; 779706f2543Smrg XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); 780706f2543Smrg newMask|= map->mods.real_mods; 781706f2543Smrg if (newMask!=map->mods.mask) { 782706f2543Smrg map->mods.mask= newMask; 783706f2543Smrg if (changes) { 784706f2543Smrg changes->indicators.map_changes|= (1<<i); 785706f2543Smrg checkState= TRUE; 786706f2543Smrg } 787706f2543Smrg } 788706f2543Smrg } 789706f2543Smrg } 790706f2543Smrg } 791706f2543Smrg if (xkb->compat!=NULL) { 792706f2543Smrg XkbCompatMapPtr compat; 793706f2543Smrg compat= xkb->compat; 794706f2543Smrg for (i=0;i<XkbNumKbdGroups;i++) { 795706f2543Smrg unsigned int newMask; 796706f2543Smrg XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); 797706f2543Smrg newMask|= compat->groups[i].real_mods; 798706f2543Smrg if (compat->groups[i].mask!=newMask) { 799706f2543Smrg compat->groups[i].mask= newMask; 800706f2543Smrg if (changes) { 801706f2543Smrg changes->compat.changed_groups|= (1<<i); 802706f2543Smrg checkState= TRUE; 803706f2543Smrg } 804706f2543Smrg } 805706f2543Smrg } 806706f2543Smrg } 807706f2543Smrg if (xkb->map && xkb->server) { 808706f2543Smrg int highChange = 0, lowChange = -1; 809706f2543Smrg for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 810706f2543Smrg if (XkbKeyHasActions(xkb,i)) { 811706f2543Smrg register XkbAction *pAct; 812706f2543Smrg register int n; 813706f2543Smrg 814706f2543Smrg pAct= XkbKeyActionsPtr(xkb,i); 815706f2543Smrg for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { 816706f2543Smrg if ((pAct->type!=XkbSA_NoAction)&& 817706f2543Smrg XkbUpdateActionVirtualMods(xkb,pAct,changed)) { 818706f2543Smrg if (lowChange<0) 819706f2543Smrg lowChange= i; 820706f2543Smrg highChange= i; 821706f2543Smrg } 822706f2543Smrg } 823706f2543Smrg } 824706f2543Smrg } 825706f2543Smrg if (changes && (lowChange>0)) { /* something changed */ 826706f2543Smrg if (changes->map.changed&XkbKeyActionsMask) { 827706f2543Smrg int last; 828706f2543Smrg if (changes->map.first_key_act<lowChange) 829706f2543Smrg lowChange= changes->map.first_key_act; 830706f2543Smrg last= changes->map.first_key_act+changes->map.num_key_acts-1; 831706f2543Smrg if (last>highChange) 832706f2543Smrg highChange= last; 833706f2543Smrg } 834706f2543Smrg changes->map.changed|= XkbKeyActionsMask; 835706f2543Smrg changes->map.first_key_act= lowChange; 836706f2543Smrg changes->map.num_key_acts= (highChange-lowChange)+1; 837706f2543Smrg } 838706f2543Smrg } 839706f2543Smrg return checkState; 840706f2543Smrg} 841