XKBMisc.c revision 4642e01f
1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#elif defined(HAVE_CONFIG_H) 30#include <config.h> 31#endif 32 33#include <stdio.h> 34#include <X11/X.h> 35#define NEED_EVENTS 36#define NEED_REPLIES 37#include <X11/Xproto.h> 38#include "misc.h" 39#include "inputstr.h" 40#include <X11/keysym.h> 41#define XKBSRV_NEED_FILE_FUNCS 42#include <xkbsrv.h> 43 44/***====================================================================***/ 45 46#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol) 47#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l)) 48 49int 50XkbKeyTypesForCoreSymbols( XkbDescPtr xkb, 51 int map_width, 52 KeySym * core_syms, 53 unsigned int protected, 54 int * types_inout, 55 KeySym * xkb_syms_rtrn) 56{ 57register int i; 58unsigned int empty; 59int nSyms[XkbNumKbdGroups]; 60int nGroups,tmp,groupsWidth; 61 62 /* Section 12.2 of the protocol describes this process in more detail */ 63 /* Step 1: find the # of symbols in the core mapping per group */ 64 groupsWidth= 2; 65 for (i=0;i<XkbNumKbdGroups;i++) { 66 if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) { 67 nSyms[i]= xkb->map->types[types_inout[i]].num_levels; 68 if (nSyms[i]>groupsWidth) 69 groupsWidth= nSyms[i]; 70 } 71 else { 72 types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */ 73 nSyms[i]= 2; 74 } 75 } 76 if (nSyms[XkbGroup1Index]<2) 77 nSyms[XkbGroup1Index]= 2; 78 if (nSyms[XkbGroup2Index]<2) 79 nSyms[XkbGroup2Index]= 2; 80 /* Step 2: Copy the symbols from the core ordering to XKB ordering */ 81 /* symbols in the core are in the order: */ 82 /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */ 83 xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0); 84 xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1); 85 for (i=2;i<nSyms[XkbGroup1Index];i++) { 86 xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i); 87 } 88 xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2); 89 xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3); 90 tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */ 91 for (i=2;i<nSyms[XkbGroup2Index];i++) { 92 xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i); 93 } 94 tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index]; 95 if ((tmp>=map_width)&& 96 ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) { 97 nSyms[XkbGroup3Index]= 0; 98 nSyms[XkbGroup4Index]= 0; 99 nGroups= 2; 100 } 101 else { 102 nGroups= 3; 103 for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) { 104 xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp); 105 } 106 if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) { 107 nGroups= 4; 108 for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) { 109 xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp); 110 } 111 } 112 else { 113 nSyms[XkbGroup4Index]= 0; 114 } 115 } 116 /* steps 3&4: alphanumeric expansion, assign canonical types */ 117 empty= 0; 118 for (i=0;i<nGroups;i++) { 119 KeySym *syms; 120 syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 121 if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) { 122 KeySym upper,lower; 123 XConvertCase(syms[0],&lower,&upper); 124 if (upper!=lower) { 125 xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower; 126 xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper; 127 if ((protected&(1<<i))==0) 128 types_inout[i]= XkbAlphabeticIndex; 129 } 130 else if ((protected&(1<<i))==0) { 131 types_inout[i]= XkbOneLevelIndex; 132 /* nSyms[i]= 1;*/ 133 } 134 } 135 if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) { 136 if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1])) 137 types_inout[i]= XkbKeypadIndex; 138 else { 139 KeySym upper,lower; 140 XConvertCase(syms[0],&lower,&upper); 141 if ((syms[0]==lower)&&(syms[1]==upper)) 142 types_inout[i]= XkbAlphabeticIndex; 143 } 144 } 145 if (syms[0]==NoSymbol) { 146 register int n; 147 Bool found; 148 for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) { 149 found= (syms[n]!=NoSymbol); 150 } 151 if (!found) 152 empty|= (1<<i); 153 } 154 } 155 /* step 5: squoosh out empty groups */ 156 if (empty) { 157 for (i=nGroups-1;i>=0;i--) { 158 if (((empty&(1<<i))==0)||(protected&(1<<i))) 159 break; 160 nGroups--; 161 } 162 } 163 if (nGroups<1) 164 return 0; 165 166 /* step 6: replicate group 1 into group two, if necessary */ 167 if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) { 168 if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) { 169 nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index]; 170 types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index]; 171 memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn, 172 2*sizeof(KeySym)); 173 } 174 else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) { 175 memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]], 176 (char *)xkb_syms_rtrn, 177 nSyms[XkbGroup1Index]*sizeof(KeySym)); 178 } 179 } 180 181 /* step 7: check for all groups identical or all width 1 182 * 183 * Special feature: if group 1 has an explicit type and all other groups 184 * have canonical types with same symbols, we assume it's info lost from 185 * the core replication. 186 */ 187 if (nGroups>1) { 188 Bool sameType,allOneLevel, canonical = True; 189 allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1); 190 for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) { 191 sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index])); 192 if (allOneLevel) 193 allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1); 194 if (types_inout[i] > XkbLastRequiredType) 195 canonical = False; 196 } 197 if (((sameType) || canonical)&& 198 (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){ 199 register int s; 200 Bool identical; 201 for (i=1,identical=True;identical&&(i<nGroups);i++) { 202 KeySym *syms; 203 syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)]; 204 for (s=0;identical&&(s<nSyms[i]);s++) { 205 if (syms[s]!=xkb_syms_rtrn[s]) 206 identical= False; 207 } 208 } 209 if (identical) 210 nGroups= 1; 211 } 212 if (allOneLevel && (nGroups>1)) { 213 KeySym *syms; 214 syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]]; 215 nSyms[XkbGroup1Index]= 1; 216 for (i=1;i<nGroups;i++) { 217 xkb_syms_rtrn[i]= syms[0]; 218 syms+= nSyms[i]; 219 nSyms[i]= 1; 220 } 221 } 222 } 223 return nGroups; 224} 225 226static XkbSymInterpretPtr 227_XkbFindMatchingInterp( XkbDescPtr xkb, 228 KeySym sym, 229 unsigned int real_mods, 230 unsigned int level) 231{ 232register unsigned i; 233XkbSymInterpretPtr interp,rtrn; 234CARD8 mods; 235 236 rtrn= NULL; 237 interp= xkb->compat->sym_interpret; 238 for (i=0;i<xkb->compat->num_si;i++,interp++) { 239 if ((interp->sym==NoSymbol)||(sym==interp->sym)) { 240 int match; 241 if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0)) 242 mods= real_mods; 243 else mods= 0; 244 switch (interp->match&XkbSI_OpMask) { 245 case XkbSI_NoneOf: 246 match= ((interp->mods&mods)==0); 247 break; 248 case XkbSI_AnyOfOrNone: 249 match= ((mods==0)||((interp->mods&mods)!=0)); 250 break; 251 case XkbSI_AnyOf: 252 match= ((interp->mods&mods)!=0); 253 break; 254 case XkbSI_AllOf: 255 match= ((interp->mods&mods)==interp->mods); 256 break; 257 case XkbSI_Exactly: 258 match= (interp->mods==mods); 259 break; 260 default: 261 match= 0; 262 break; 263 } 264 if (match) { 265 if (interp->sym!=NoSymbol) { 266 return interp; 267 } 268 else if (rtrn==NULL) { 269 rtrn= interp; 270 } 271 } 272 } 273 } 274 return rtrn; 275} 276 277static void 278_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey) 279{ 280KeyCode last; 281 282 last= (*pFirst)+(*pNum); 283 if (newKey<*pFirst) { 284 *pFirst= newKey; 285 *pNum= (last-newKey)+1; 286 } 287 else if (newKey>last) { 288 *pNum= (last-*pFirst)+1; 289 } 290 return; 291} 292 293static void 294_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods) 295{ 296unsigned tmp; 297 298 switch (act->type) { 299 case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 300 if (act->mods.flags&XkbSA_UseModMapMods) 301 act->mods.real_mods= act->mods.mask= mods; 302 if ((tmp= XkbModActionVMods(&act->mods))!=0) { 303 XkbVirtualModsToReal(xkb,tmp,&tmp); 304 act->mods.mask|= tmp; 305 } 306 break; 307 case XkbSA_ISOLock: 308 if (act->iso.flags&XkbSA_UseModMapMods) 309 act->iso.real_mods= act->iso.mask= mods; 310 if ((tmp= XkbModActionVMods(&act->iso))!=0) { 311 XkbVirtualModsToReal(xkb,tmp,&tmp); 312 act->iso.mask|= tmp; 313 } 314 break; 315 } 316 return; 317} 318 319#define IBUF_SIZE 8 320 321Bool 322XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes) 323{ 324KeySym * syms; 325unsigned char explicit,mods; 326XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE]; 327int n,nSyms,found; 328unsigned changed,tmp; 329 330 if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)|| 331 (!xkb->compat)||(!xkb->compat->sym_interpret)|| 332 (key<xkb->min_key_code)||(key>xkb->max_key_code)) { 333 return False; 334 } 335 if (((!xkb->server)||(!xkb->server->key_acts))&& 336 (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) { 337 return False; 338 } 339 changed= 0; /* keeps track of what has changed in _this_ call */ 340 explicit= xkb->server->explicit[key]; 341 if (explicit&XkbExplicitInterpretMask) /* nothing to do */ 342 return True; 343 mods= (xkb->map->modmap?xkb->map->modmap[key]:0); 344 nSyms= XkbKeyNumSyms(xkb,key); 345 syms= XkbKeySymsPtr(xkb,key); 346 if (nSyms>IBUF_SIZE) { 347 interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr); 348 if (interps==NULL) { 349 interps= ibuf; 350 nSyms= IBUF_SIZE; 351 } 352 } 353 else { 354 interps= ibuf; 355 } 356 found= 0; 357 for (n=0;n<nSyms;n++) { 358 unsigned level= (n%XkbKeyGroupsWidth(xkb,key)); 359 interps[n]= NULL; 360 if (syms[n]!=NoSymbol) { 361 interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level); 362 if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction) 363 found++; 364 else interps[n]= NULL; 365 } 366 } 367 /* 1/28/96 (ef) -- XXX! WORKING HERE */ 368 if (!found) { 369 if (xkb->server->key_acts[key]!=0) { 370 xkb->server->key_acts[key]= 0; 371 changed|= XkbKeyActionsMask; 372 } 373 } 374 else { 375 XkbAction *pActs; 376 unsigned int new_vmodmask; 377 changed|= XkbKeyActionsMask; 378 pActs= XkbResizeKeyActions(xkb,key,nSyms); 379 if (!pActs) { 380 if (nSyms > IBUF_SIZE) 381 xfree(interps); 382 return False; 383 } 384 new_vmodmask= 0; 385 for (n=0;n<nSyms;n++) { 386 if (interps[n]) { 387 unsigned effMods; 388 389 pActs[n]= *((XkbAction *)&interps[n]->act); 390 if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) { 391 effMods= mods; 392 if (interps[n]->virtual_mod!=XkbNoModifier) 393 new_vmodmask|= (1<<interps[n]->virtual_mod); 394 } 395 else effMods= 0; 396 _XkbSetActionKeyMods(xkb,&pActs[n],effMods); 397 } 398 else pActs[n].type= XkbSA_NoAction; 399 } 400 if (((explicit&XkbExplicitVModMapMask)==0)&& 401 (xkb->server->vmodmap[key]!=new_vmodmask)) { 402 changed|= XkbVirtualModMapMask; 403 xkb->server->vmodmap[key]= new_vmodmask; 404 } 405 if (interps[0]) { 406 if ((interps[0]->flags&XkbSI_LockingKey)&& 407 ((explicit&XkbExplicitBehaviorMask)==0)) { 408 xkb->server->behaviors[key].type= XkbKB_Lock; 409 changed|= XkbKeyBehaviorsMask; 410 } 411 if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 412 CARD8 old; 413 old= xkb->ctrls->per_key_repeat[key/8]; 414 if (interps[0]->flags&XkbSI_AutoRepeat) 415 xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 416 else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); 417 if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 418 changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 419 } 420 } 421 } 422 if ((!found)||(interps[0]==NULL)) { 423 if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { 424 CARD8 old; 425 old= xkb->ctrls->per_key_repeat[key/8]; 426 xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); 427 if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) 428 changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; 429 } 430 if (((explicit&XkbExplicitBehaviorMask)==0)&& 431 (xkb->server->behaviors[key].type==XkbKB_Lock)) { 432 xkb->server->behaviors[key].type= XkbKB_Default; 433 changed|= XkbKeyBehaviorsMask; 434 } 435 } 436 if (changes) { 437 XkbMapChangesPtr mc; 438 mc= &changes->map; 439 tmp= (changed&mc->changed); 440 if (tmp&XkbKeyActionsMask) 441 _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key); 442 else if (changed&XkbKeyActionsMask) { 443 mc->changed|= XkbKeyActionsMask; 444 mc->first_key_act= key; 445 mc->num_key_acts= 1; 446 } 447 if (tmp&XkbKeyBehaviorsMask) { 448 _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors, 449 key); 450 } 451 else if (changed&XkbKeyBehaviorsMask) { 452 mc->changed|= XkbKeyBehaviorsMask; 453 mc->first_key_behavior= key; 454 mc->num_key_behaviors= 1; 455 } 456 if (tmp&XkbVirtualModMapMask) 457 _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key); 458 else if (changed&XkbVirtualModMapMask) { 459 mc->changed|= XkbVirtualModMapMask; 460 mc->first_vmodmap_key= key; 461 mc->num_vmodmap_keys= 1; 462 } 463 mc->changed|= changed; 464 } 465 if (interps!=ibuf) 466 _XkbFree(interps); 467 return True; 468} 469 470Status 471XkbChangeTypesOfKey( XkbDescPtr xkb, 472 int key, 473 int nGroups, 474 unsigned groups, 475 int * newTypesIn, 476 XkbMapChangesPtr changes) 477{ 478XkbKeyTypePtr pOldType,pNewType; 479register int i; 480int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups]; 481 482 if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) || 483 (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)|| 484 (nGroups>XkbNumKbdGroups)) { 485 return BadMatch; 486 } 487 if (nGroups==0) { 488 for (i=0;i<XkbNumKbdGroups;i++) { 489 xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex; 490 } 491 i= xkb->map->key_sym_map[key].group_info; 492 i= XkbSetNumGroups(i,0); 493 xkb->map->key_sym_map[key].group_info= i; 494 XkbResizeKeySyms(xkb,key,0); 495 return Success; 496 } 497 498 nOldGroups= XkbKeyNumGroups(xkb,key); 499 oldWidth= XkbKeyGroupsWidth(xkb,key); 500 for (width=i=0;i<nGroups;i++) { 501 if (groups&(1<<i)) 502 newTypes[i]= newTypesIn[i]; 503 else if (i<nOldGroups) 504 newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i); 505 else if (nOldGroups>0) 506 newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index); 507 else newTypes[i]= XkbTwoLevelIndex; 508 if (newTypes[i]>xkb->map->num_types) 509 return BadMatch; 510 pNewType= &xkb->map->types[newTypes[i]]; 511 if (pNewType->num_levels>width) 512 width= pNewType->num_levels; 513 } 514 if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups)) 515 xkb->ctrls->num_groups= nGroups; 516 if ((width!=oldWidth)||(nGroups!=nOldGroups)) { 517 KeySym oldSyms[XkbMaxSymsPerKey],*pSyms; 518 int nCopy; 519 520 if (nOldGroups==0) { 521 pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 522 if (pSyms!=NULL) { 523 i= xkb->map->key_sym_map[key].group_info; 524 i= XkbSetNumGroups(i,nGroups); 525 xkb->map->key_sym_map[key].group_info= i; 526 xkb->map->key_sym_map[key].width= width; 527 for (i=0;i<nGroups;i++) { 528 xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 529 } 530 return Success; 531 } 532 return BadAlloc; 533 } 534 pSyms= XkbKeySymsPtr(xkb,key); 535 memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym)); 536 pSyms= XkbResizeKeySyms(xkb,key,width*nGroups); 537 if (pSyms==NULL) 538 return BadAlloc; 539 bzero(pSyms,width*nGroups*sizeof(KeySym)); 540 for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 541 pOldType= XkbKeyKeyType(xkb,key,i); 542 pNewType= &xkb->map->types[newTypes[i]]; 543 if (pNewType->num_levels>pOldType->num_levels) 544 nCopy= pOldType->num_levels; 545 else nCopy= pNewType->num_levels; 546 memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym)); 547 } 548 if (XkbKeyHasActions(xkb,key)) { 549 XkbAction oldActs[XkbMaxSymsPerKey],*pActs; 550 pActs= XkbKeyActionsPtr(xkb,key); 551 memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction)); 552 pActs= XkbResizeKeyActions(xkb,key,width*nGroups); 553 if (pActs==NULL) 554 return BadAlloc; 555 bzero(pActs,width*nGroups*sizeof(XkbAction)); 556 for (i=0;(i<nGroups)&&(i<nOldGroups);i++) { 557 pOldType= XkbKeyKeyType(xkb,key,i); 558 pNewType= &xkb->map->types[newTypes[i]]; 559 if (pNewType->num_levels>pOldType->num_levels) 560 nCopy= pOldType->num_levels; 561 else nCopy= pNewType->num_levels; 562 memcpy(&pActs[i*width],&oldActs[i*oldWidth], 563 nCopy*sizeof(XkbAction)); 564 } 565 } 566 i= xkb->map->key_sym_map[key].group_info; 567 i= XkbSetNumGroups(i,nGroups); 568 xkb->map->key_sym_map[key].group_info= i; 569 xkb->map->key_sym_map[key].width= width; 570 } 571 width= 0; 572 for (i=0;i<nGroups;i++) { 573 xkb->map->key_sym_map[key].kt_index[i]= newTypes[i]; 574 if (xkb->map->types[newTypes[i]].num_levels>width) 575 width= xkb->map->types[newTypes[i]].num_levels; 576 } 577 xkb->map->key_sym_map[key].width= width; 578 if (changes!=NULL) { 579 if (changes->changed&XkbKeySymsMask) { 580 _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms, 581 key); 582 } 583 else { 584 changes->changed|= XkbKeySymsMask; 585 changes->first_key_sym= key; 586 changes->num_key_syms= 1; 587 } 588 } 589 return Success; 590} 591 592/***====================================================================***/ 593 594Bool 595XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn) 596{ 597register int i,bit; 598register unsigned mask; 599 600 if (xkb==NULL) 601 return False; 602 if (virtual_mask==0) { 603 *mask_rtrn= 0; 604 return True; 605 } 606 if (xkb->server==NULL) 607 return False; 608 for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 609 if (virtual_mask&bit) 610 mask|= xkb->server->vmods[i]; 611 } 612 *mask_rtrn= mask; 613 return True; 614} 615 616/***====================================================================***/ 617 618static Bool 619XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed) 620{ 621unsigned int tmp; 622 623 switch (act->type) { 624 case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods: 625 if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) { 626 XkbVirtualModsToReal(xkb,tmp,&tmp); 627 act->mods.mask= act->mods.real_mods; 628 act->mods.mask|= tmp; 629 return True; 630 } 631 break; 632 case XkbSA_ISOLock: 633 if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) { 634 XkbVirtualModsToReal(xkb,tmp,&tmp); 635 act->iso.mask= act->iso.real_mods; 636 act->iso.mask|= tmp; 637 return True; 638 } 639 break; 640 } 641 return False; 642} 643 644static void 645XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb, 646 XkbKeyTypePtr type, 647 unsigned int changed, 648 XkbChangesPtr changes) 649{ 650register unsigned int i; 651unsigned int mask; 652 653 XkbVirtualModsToReal(xkb,type->mods.vmods,&mask); 654 type->mods.mask= type->mods.real_mods|mask; 655 if ((type->map_count>0)&&(type->mods.vmods!=0)) { 656 XkbKTMapEntryPtr entry; 657 for (i=0,entry=type->map;i<type->map_count;i++,entry++) { 658 if (entry->mods.vmods!=0) { 659 XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask); 660 entry->mods.mask=entry->mods.real_mods|mask; 661 /* entry is active if vmods are bound*/ 662 entry->active= (mask!=0); 663 } 664 else entry->active= 1; 665 } 666 } 667 if (changes) { 668 int type_ndx; 669 type_ndx= type-xkb->map->types; 670 if ((type_ndx<0)||(type_ndx>xkb->map->num_types)) 671 return; 672 if (changes->map.changed&XkbKeyTypesMask) { 673 int last; 674 last= changes->map.first_type+changes->map.num_types-1; 675 if (type_ndx<changes->map.first_type) { 676 changes->map.first_type= type_ndx; 677 changes->map.num_types= (last-type_ndx)+1; 678 } 679 else if (type_ndx>last) { 680 changes->map.num_types= (type_ndx-changes->map.first_type)+1; 681 } 682 } 683 else { 684 changes->map.changed|= XkbKeyTypesMask; 685 changes->map.first_type= type_ndx; 686 changes->map.num_types= 1; 687 } 688 } 689 return; 690} 691 692Bool 693XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes) 694{ 695register int i; 696unsigned int checkState = 0; 697 698 if ((!xkb) || (!xkb->map) || (changed==0)) 699 return False; 700 for (i=0;i<xkb->map->num_types;i++) { 701 if (xkb->map->types[i].mods.vmods & changed) 702 XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes); 703 } 704 if (changed&xkb->ctrls->internal.vmods) { 705 unsigned int newMask; 706 XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask); 707 newMask|= xkb->ctrls->internal.real_mods; 708 if (xkb->ctrls->internal.mask!=newMask) { 709 xkb->ctrls->internal.mask= newMask; 710 if (changes) { 711 changes->ctrls.changed_ctrls|= XkbInternalModsMask; 712 checkState= True; 713 } 714 } 715 } 716 if (changed&xkb->ctrls->ignore_lock.vmods) { 717 unsigned int newMask; 718 XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask); 719 newMask|= xkb->ctrls->ignore_lock.real_mods; 720 if (xkb->ctrls->ignore_lock.mask!=newMask) { 721 xkb->ctrls->ignore_lock.mask= newMask; 722 if (changes) { 723 changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask; 724 checkState= True; 725 } 726 } 727 } 728 if (xkb->indicators!=NULL) { 729 XkbIndicatorMapPtr map; 730 map= &xkb->indicators->maps[0]; 731 for (i=0;i<XkbNumIndicators;i++,map++) { 732 if (map->mods.vmods&changed) { 733 unsigned int newMask; 734 XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask); 735 newMask|= map->mods.real_mods; 736 if (newMask!=map->mods.mask) { 737 map->mods.mask= newMask; 738 if (changes) { 739 changes->indicators.map_changes|= (1<<i); 740 checkState= True; 741 } 742 } 743 } 744 } 745 } 746 if (xkb->compat!=NULL) { 747 XkbCompatMapPtr compat; 748 compat= xkb->compat; 749 for (i=0;i<XkbNumKbdGroups;i++) { 750 unsigned int newMask; 751 XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask); 752 newMask|= compat->groups[i].real_mods; 753 if (compat->groups[i].mask!=newMask) { 754 compat->groups[i].mask= newMask; 755 if (changes) { 756 changes->compat.changed_groups|= (1<<i); 757 checkState= True; 758 } 759 } 760 } 761 } 762 if (xkb->map && xkb->server) { 763 int highChange = 0, lowChange = -1; 764 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 765 if (XkbKeyHasActions(xkb,i)) { 766 register XkbAction *pAct; 767 register int n; 768 769 pAct= XkbKeyActionsPtr(xkb,i); 770 for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) { 771 if ((pAct->type!=XkbSA_NoAction)&& 772 XkbUpdateActionVirtualMods(xkb,pAct,changed)) { 773 if (lowChange<0) 774 lowChange= i; 775 highChange= i; 776 } 777 } 778 } 779 } 780 if (changes && (lowChange>0)) { /* something changed */ 781 if (changes->map.changed&XkbKeyActionsMask) { 782 int last; 783 if (changes->map.first_key_act<lowChange) 784 lowChange= changes->map.first_key_act; 785 last= changes->map.first_key_act+changes->map.num_key_acts-1; 786 if (last>highChange) 787 highChange= last; 788 } 789 changes->map.changed|= XkbKeyActionsMask; 790 changes->map.first_key_act= lowChange; 791 changes->map.num_key_acts= (highChange-lowChange)+1; 792 } 793 } 794 return checkState; 795} 796