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