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