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