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