Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / XKBMisc.c
CommitLineData
a09e091a
JB
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, 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
279static 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
330static 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
346static 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
376Bool
377XkbApplyCompatMapToKey(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
535Status
536XkbChangeTypesOfKey(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
662Bool
663XkbVirtualModsToReal(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
686static Bool
687XkbUpdateActionVirtualMods(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
714static void
715XkbUpdateKeyTypeVirtualMods(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
766Bool
767XkbApplyVirtualModChanges(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}