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 #endif
30
31 #include <stdio.h>
32 #include <X11/X.h>
33 #include <X11/Xproto.h>
34 #include "misc.h"
35 #include "inputstr.h"
36 #include <X11/keysym.h>
37 #define XKBSRV_NEED_FILE_FUNCS
38 #include <xkbsrv.h>
39
40 /***====================================================================***/
41
42 Status
XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)43 XkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes)
44 {
45 register int i;
46 XkbClientMapPtr map;
47
48 if ((xkb == NULL) ||
49 ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
50 return BadValue;
51 if ((which & XkbKeySymsMask) &&
52 ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
53 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
54 (xkb->max_key_code < xkb->min_key_code))) {
55 DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n",
56 xkb->min_key_code, xkb->max_key_code);
57 return BadValue;
58 }
59
60 if (xkb->map == NULL) {
61 map = calloc(1, sizeof(XkbClientMapRec));
62 if (map == NULL)
63 return BadAlloc;
64 xkb->map = map;
65 }
66 else
67 map = xkb->map;
68
69 if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
70 if (map->types == NULL) {
71 map->types = calloc(nTotalTypes, sizeof(XkbKeyTypeRec));
72 if (map->types == NULL)
73 return BadAlloc;
74 map->num_types = 0;
75 map->size_types = nTotalTypes;
76 }
77 else if (map->size_types < nTotalTypes) {
78 XkbKeyTypeRec *prev_types = map->types;
79
80 map->types =
81 reallocarray(map->types, nTotalTypes, sizeof(XkbKeyTypeRec));
82 if (map->types == NULL) {
83 free(prev_types);
84 map->num_types = map->size_types = 0;
85 return BadAlloc;
86 }
87 map->size_types = nTotalTypes;
88 memset(&map->types[map->num_types], 0,
89 ((map->size_types -
90 map->num_types) * sizeof(XkbKeyTypeRec)));
91 }
92 }
93 if (which & XkbKeySymsMask) {
94 int nKeys = XkbNumKeys(xkb);
95
96 if (map->syms == NULL) {
97 map->size_syms = (nKeys * 15) / 10;
98 map->syms = calloc(map->size_syms, sizeof(KeySym));
99 if (!map->syms) {
100 map->size_syms = 0;
101 return BadAlloc;
102 }
103 map->num_syms = 1;
104 map->syms[0] = NoSymbol;
105 }
106 if (map->key_sym_map == NULL) {
107 i = xkb->max_key_code + 1;
108 map->key_sym_map = calloc(i, sizeof(XkbSymMapRec));
109 if (map->key_sym_map == NULL)
110 return BadAlloc;
111 }
112 }
113 if (which & XkbModifierMapMask) {
114 if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
115 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
116 (xkb->max_key_code < xkb->min_key_code))
117 return BadMatch;
118 if (map->modmap == NULL) {
119 i = xkb->max_key_code + 1;
120 map->modmap = calloc(i, sizeof(unsigned char));
121 if (map->modmap == NULL)
122 return BadAlloc;
123 }
124 }
125 return Success;
126 }
127
128 Status
XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)129 XkbAllocServerMap(XkbDescPtr xkb, unsigned which, unsigned nNewActions)
130 {
131 register int i;
132 XkbServerMapPtr map;
133
134 if (xkb == NULL)
135 return BadMatch;
136 if (xkb->server == NULL) {
137 map = calloc(1, sizeof(XkbServerMapRec));
138 if (map == NULL)
139 return BadAlloc;
140 for (i = 0; i < XkbNumVirtualMods; i++) {
141 map->vmods[i] = XkbNoModifierMask;
142 }
143 xkb->server = map;
144 }
145 else
146 map = xkb->server;
147 if (which & XkbExplicitComponentsMask) {
148 if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
149 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
150 (xkb->max_key_code < xkb->min_key_code))
151 return BadMatch;
152 if (map->explicit == NULL) {
153 i = xkb->max_key_code + 1;
154 map->explicit = calloc(i, sizeof(unsigned char));
155 if (map->explicit == NULL)
156 return BadAlloc;
157 }
158 }
159 if (which & XkbKeyActionsMask) {
160 if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
161 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
162 (xkb->max_key_code < xkb->min_key_code))
163 return BadMatch;
164 if (nNewActions < 1)
165 nNewActions = 1;
166 if (map->acts == NULL) {
167 map->acts = calloc((nNewActions + 1), sizeof(XkbAction));
168 if (map->acts == NULL)
169 return BadAlloc;
170 map->num_acts = 1;
171 map->size_acts = nNewActions + 1;
172 }
173 else if ((map->size_acts - map->num_acts) < nNewActions) {
174 unsigned need;
175 XkbAction *prev_acts = map->acts;
176
177 need = map->num_acts + nNewActions;
178 map->acts = reallocarray(map->acts, need, sizeof(XkbAction));
179 if (map->acts == NULL) {
180 free(prev_acts);
181 map->num_acts = map->size_acts = 0;
182 return BadAlloc;
183 }
184 map->size_acts = need;
185 memset(&map->acts[map->num_acts], 0,
186 ((map->size_acts - map->num_acts) * sizeof(XkbAction)));
187 }
188 if (map->key_acts == NULL) {
189 i = xkb->max_key_code + 1;
190 map->key_acts = calloc(i, sizeof(unsigned short));
191 if (map->key_acts == NULL)
192 return BadAlloc;
193 }
194 }
195 if (which & XkbKeyBehaviorsMask) {
196 if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
197 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
198 (xkb->max_key_code < xkb->min_key_code))
199 return BadMatch;
200 if (map->behaviors == NULL) {
201 i = xkb->max_key_code + 1;
202 map->behaviors = calloc(i, sizeof(XkbBehavior));
203 if (map->behaviors == NULL)
204 return BadAlloc;
205 }
206 }
207 if (which & XkbVirtualModMapMask) {
208 if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
209 (!XkbIsLegalKeycode(xkb->max_key_code)) ||
210 (xkb->max_key_code < xkb->min_key_code))
211 return BadMatch;
212 if (map->vmodmap == NULL) {
213 i = xkb->max_key_code + 1;
214 map->vmodmap = calloc(i, sizeof(unsigned short));
215 if (map->vmodmap == NULL)
216 return BadAlloc;
217 }
218 }
219 return Success;
220 }
221
222 /***====================================================================***/
223
224 static Status
XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)225 XkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into)
226 {
227 if ((!from) || (!into))
228 return BadMatch;
229 free(into->map);
230 into->map = NULL;
231 free(into->preserve);
232 into->preserve = NULL;
233 free(into->level_names);
234 into->level_names = NULL;
235 *into = *from;
236 if ((from->map) && (into->map_count > 0)) {
237 into->map = calloc(into->map_count, sizeof(XkbKTMapEntryRec));
238 if (!into->map)
239 return BadAlloc;
240 memcpy(into->map, from->map,
241 into->map_count * sizeof(XkbKTMapEntryRec));
242 }
243 if ((from->preserve) && (into->map_count > 0)) {
244 into->preserve = calloc(into->map_count, sizeof(XkbModsRec));
245 if (!into->preserve)
246 return BadAlloc;
247 memcpy(into->preserve, from->preserve,
248 into->map_count * sizeof(XkbModsRec));
249 }
250 if ((from->level_names) && (into->num_levels > 0)) {
251 into->level_names = calloc(into->num_levels, sizeof(Atom));
252 if (!into->level_names)
253 return BadAlloc;
254 memcpy(into->level_names, from->level_names,
255 into->num_levels * sizeof(Atom));
256 }
257 return Success;
258 }
259
260 Status
XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)261 XkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types)
262 {
263 register int i, rtrn;
264
265 if ((!from) || (!into) || (num_types < 0))
266 return BadMatch;
267 for (i = 0; i < num_types; i++) {
268 if ((rtrn = XkbCopyKeyType(from++, into++)) != Success)
269 return rtrn;
270 }
271 return Success;
272 }
273
274 Status
XkbResizeKeyType(XkbDescPtr xkb,int type_ndx,int map_count,Bool want_preserve,int new_num_lvls)275 XkbResizeKeyType(XkbDescPtr xkb,
276 int type_ndx,
277 int map_count, Bool want_preserve, int new_num_lvls)
278 {
279 XkbKeyTypePtr type;
280 KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys;
281
282 if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0)
283 || (new_num_lvls < 1))
284 return BadValue;
285 switch (type_ndx) {
286 case XkbOneLevelIndex:
287 if (new_num_lvls != 1)
288 return BadMatch;
289 break;
290 case XkbTwoLevelIndex:
291 case XkbAlphabeticIndex:
292 case XkbKeypadIndex:
293 if (new_num_lvls != 2)
294 return BadMatch;
295 break;
296 }
297 type = &xkb->map->types[type_ndx];
298 if (map_count == 0) {
299 free(type->map);
300 type->map = NULL;
301 free(type->preserve);
302 type->preserve = NULL;
303 type->map_count = 0;
304 }
305 else {
306 XkbKTMapEntryRec *prev_map = type->map;
307
308 if ((map_count > type->map_count) || (type->map == NULL))
309 type->map =
310 reallocarray(type->map, map_count, sizeof(XkbKTMapEntryRec));
311 if (!type->map) {
312 free(prev_map);
313 return BadAlloc;
314 }
315 if (want_preserve) {
316 XkbModsRec *prev_preserve = type->preserve;
317
318 if ((map_count > type->map_count) || (type->preserve == NULL)) {
319 type->preserve = reallocarray(type->preserve,
320 map_count, sizeof(XkbModsRec));
321 }
322 if (!type->preserve) {
323 free(prev_preserve);
324 return BadAlloc;
325 }
326 }
327 else {
328 free(type->preserve);
329 type->preserve = NULL;
330 }
331 type->map_count = map_count;
332 }
333
334 if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) {
335 Atom *prev_level_names = type->level_names;
336
337 type->level_names = reallocarray(type->level_names,
338 new_num_lvls, sizeof(Atom));
339 if (!type->level_names) {
340 free(prev_level_names);
341 return BadAlloc;
342 }
343 }
344 /*
345 * Here's the theory:
346 * If the width of the type changed, we might have to resize the symbol
347 * maps for any keys that use the type for one or more groups. This is
348 * expensive, so we'll try to cull out any keys that are obviously okay:
349 * In any case:
350 * - keys that have a group width <= the old width are okay (because
351 * they could not possibly have been associated with the old type)
352 * If the key type increased in size:
353 * - keys that already have a group width >= to the new width are okay
354 * + keys that have a group width >= the old width but < the new width
355 * might have to be enlarged.
356 * If the key type decreased in size:
357 * - keys that have a group width > the old width don't have to be
358 * resized (because they must have some other wider type associated
359 * with some group).
360 * + keys that have a group width == the old width might have to be
361 * shrunk.
362 * The possibilities marked with '+' require us to examine the key types
363 * associated with each group for the key.
364 */
365 memset(matchingKeys, 0, XkbMaxKeyCount * sizeof(KeyCode));
366 nMatchingKeys = 0;
367 if (new_num_lvls > type->num_levels) {
368 int nTotal;
369 KeySym *newSyms;
370 int width, match, nResize;
371 register int i, g, nSyms;
372
373 nResize = 0;
374 for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
375 width = XkbKeyGroupsWidth(xkb, i);
376 if (width < type->num_levels || width >= new_num_lvls) {
377 nTotal += XkbKeyNumSyms(xkb,i);
378 continue;
379 }
380 for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
381 (g >= 0) && (!match); g--) {
382 if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
383 matchingKeys[nMatchingKeys++] = i;
384 match = 1;
385 }
386 }
387 if (!match)
388 nTotal += XkbKeyNumSyms(xkb, i);
389 else {
390 nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
391 nResize++;
392 }
393 }
394 if (nResize > 0) {
395 int nextMatch;
396
397 xkb->map->size_syms = (nTotal * 15) / 10;
398 newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
399 if (newSyms == NULL)
400 return BadAlloc;
401 nextMatch = 0;
402 nSyms = 1;
403 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
404 if (matchingKeys[nextMatch] == i) {
405 KeySym *pOld;
406
407 nextMatch++;
408 width = XkbKeyGroupsWidth(xkb, i);
409 pOld = XkbKeySymsPtr(xkb, i);
410 for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
411 memcpy(&newSyms[nSyms + (new_num_lvls * g)],
412 &pOld[width * g], width * sizeof(KeySym));
413 }
414 xkb->map->key_sym_map[i].offset = nSyms;
415 nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
416 }
417 else {
418 memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
419 XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
420 xkb->map->key_sym_map[i].offset = nSyms;
421 nSyms += XkbKeyNumSyms(xkb, i);
422 }
423 }
424 type->num_levels = new_num_lvls;
425 free(xkb->map->syms);
426 xkb->map->syms = newSyms;
427 xkb->map->num_syms = nSyms;
428 return Success;
429 }
430 }
431 else if (new_num_lvls < type->num_levels) {
432 int width, match;
433 register int g, i;
434
435 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
436 width = XkbKeyGroupsWidth(xkb, i);
437 if (width < type->num_levels)
438 continue;
439 for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
440 (g >= 0) && (!match); g--) {
441 if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
442 matchingKeys[nMatchingKeys++] = i;
443 match = 1;
444 }
445 }
446 }
447 }
448 if (nMatchingKeys > 0) {
449 int key, firstClear;
450 register int i, g;
451
452 if (new_num_lvls > type->num_levels)
453 firstClear = type->num_levels;
454 else
455 firstClear = new_num_lvls;
456 for (i = 0; i < nMatchingKeys; i++) {
457 KeySym *pSyms;
458 int width, nClear;
459
460 key = matchingKeys[i];
461 width = XkbKeyGroupsWidth(xkb, key);
462 nClear = width - firstClear;
463 pSyms = XkbKeySymsPtr(xkb, key);
464 for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
465 if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
466 if (nClear > 0)
467 memset(&pSyms[g * width + firstClear], 0,
468 nClear * sizeof(KeySym));
469 }
470 }
471 }
472 }
473 type->num_levels = new_num_lvls;
474 return Success;
475 }
476
477 KeySym *
XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)478 XkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
479 {
480 register int i, nSyms, nKeySyms;
481 unsigned nOldSyms;
482 KeySym *newSyms;
483
484 if (needed == 0) {
485 xkb->map->key_sym_map[key].offset = 0;
486 return xkb->map->syms;
487 }
488 nOldSyms = XkbKeyNumSyms(xkb, key);
489 if (nOldSyms >= (unsigned) needed) {
490 return XkbKeySymsPtr(xkb, key);
491 }
492 if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
493 if (nOldSyms > 0) {
494 memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
495 nOldSyms * sizeof(KeySym));
496 }
497 if ((needed - nOldSyms) > 0) {
498 memset(&xkb->map->
499 syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)], 0,
500 (needed - nOldSyms) * sizeof(KeySym));
501 }
502 xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
503 xkb->map->num_syms += needed;
504 return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
505 }
506 xkb->map->size_syms += (needed > 32 ? needed : 32);
507 newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
508 if (newSyms == NULL)
509 return NULL;
510 newSyms[0] = NoSymbol;
511 nSyms = 1;
512 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
513 int nCopy;
514
515 nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
516 if ((nKeySyms == 0) && (i != key))
517 continue;
518 if (i == key)
519 nKeySyms = needed;
520 if (nCopy != 0)
521 memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
522 nCopy * sizeof(KeySym));
523 if (nKeySyms > nCopy)
524 memset(&newSyms[nSyms + nCopy], 0,
525 (nKeySyms - nCopy) * sizeof(KeySym));
526 xkb->map->key_sym_map[i].offset = nSyms;
527 nSyms += nKeySyms;
528 }
529 free(xkb->map->syms);
530 xkb->map->syms = newSyms;
531 xkb->map->num_syms = nSyms;
532 return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
533 }
534
535 static unsigned
_ExtendRange(unsigned int old_flags,unsigned int flag,KeyCode newKC,KeyCode * old_min,unsigned char * old_num)536 _ExtendRange(unsigned int old_flags,
537 unsigned int flag,
538 KeyCode newKC, KeyCode *old_min, unsigned char *old_num)
539 {
540 if ((old_flags & flag) == 0) {
541 old_flags |= flag;
542 *old_min = newKC;
543 *old_num = 1;
544 }
545 else {
546 int last = (*old_min) + (*old_num) - 1;
547
548 if (newKC < *old_min) {
549 *old_min = newKC;
550 *old_num = (last - newKC) + 1;
551 }
552 else if (newKC > last) {
553 *old_num = (newKC - (*old_min)) + 1;
554 }
555 }
556 return old_flags;
557 }
558
559 Status
XkbChangeKeycodeRange(XkbDescPtr xkb,int minKC,int maxKC,XkbChangesPtr changes)560 XkbChangeKeycodeRange(XkbDescPtr xkb,
561 int minKC, int maxKC, XkbChangesPtr changes)
562 {
563 int tmp;
564
565 if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
566 return BadValue;
567 if (minKC > maxKC)
568 return BadMatch;
569 if (minKC < xkb->min_key_code) {
570 if (changes)
571 changes->map.min_key_code = minKC;
572 tmp = xkb->min_key_code - minKC;
573 if (xkb->map) {
574 if (xkb->map->key_sym_map) {
575 memset((char *) &xkb->map->key_sym_map[minKC], 0,
576 tmp * sizeof(XkbSymMapRec));
577 if (changes) {
578 changes->map.changed = _ExtendRange(changes->map.changed,
579 XkbKeySymsMask, minKC,
580 &changes->map.
581 first_key_sym,
582 &changes->map.
583 num_key_syms);
584 }
585 }
586 if (xkb->map->modmap) {
587 memset((char *) &xkb->map->modmap[minKC], 0, tmp);
588 if (changes) {
589 changes->map.changed = _ExtendRange(changes->map.changed,
590 XkbModifierMapMask,
591 minKC,
592 &changes->map.
593 first_modmap_key,
594 &changes->map.
595 num_modmap_keys);
596 }
597 }
598 }
599 if (xkb->server) {
600 if (xkb->server->behaviors) {
601 memset((char *) &xkb->server->behaviors[minKC], 0,
602 tmp * sizeof(XkbBehavior));
603 if (changes) {
604 changes->map.changed = _ExtendRange(changes->map.changed,
605 XkbKeyBehaviorsMask,
606 minKC,
607 &changes->map.
608 first_key_behavior,
609 &changes->map.
610 num_key_behaviors);
611 }
612 }
613 if (xkb->server->key_acts) {
614 memset((char *) &xkb->server->key_acts[minKC], 0,
615 tmp * sizeof(unsigned short));
616 if (changes) {
617 changes->map.changed = _ExtendRange(changes->map.changed,
618 XkbKeyActionsMask,
619 minKC,
620 &changes->map.
621 first_key_act,
622 &changes->map.
623 num_key_acts);
624 }
625 }
626 if (xkb->server->vmodmap) {
627 memset((char *) &xkb->server->vmodmap[minKC], 0,
628 tmp * sizeof(unsigned short));
629 if (changes) {
630 changes->map.changed = _ExtendRange(changes->map.changed,
631 XkbVirtualModMapMask,
632 minKC,
633 &changes->map.
634 first_modmap_key,
635 &changes->map.
636 num_vmodmap_keys);
637 }
638 }
639 }
640 if ((xkb->names) && (xkb->names->keys)) {
641 memset((char *) &xkb->names->keys[minKC], 0,
642 tmp * sizeof(XkbKeyNameRec));
643 if (changes) {
644 changes->names.changed = _ExtendRange(changes->names.changed,
645 XkbKeyNamesMask, minKC,
646 &changes->names.first_key,
647 &changes->names.num_keys);
648 }
649 }
650 xkb->min_key_code = minKC;
651 }
652 if (maxKC > xkb->max_key_code) {
653 if (changes)
654 changes->map.max_key_code = maxKC;
655 tmp = maxKC - xkb->max_key_code;
656 if (xkb->map) {
657 if (xkb->map->key_sym_map) {
658 XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
659
660 xkb->map->key_sym_map = reallocarray(xkb->map->key_sym_map,
661 maxKC + 1,
662 sizeof(XkbSymMapRec));
663 if (!xkb->map->key_sym_map) {
664 free(prev_key_sym_map);
665 return BadAlloc;
666 }
667 memset((char *) &xkb->map->key_sym_map[xkb->max_key_code], 0,
668 tmp * sizeof(XkbSymMapRec));
669 if (changes) {
670 changes->map.changed = _ExtendRange(changes->map.changed,
671 XkbKeySymsMask, maxKC,
672 &changes->map.
673 first_key_sym,
674 &changes->map.
675 num_key_syms);
676 }
677 }
678 if (xkb->map->modmap) {
679 unsigned char *prev_modmap = xkb->map->modmap;
680
681 xkb->map->modmap = reallocarray(xkb->map->modmap,
682 maxKC + 1,
683 sizeof(unsigned char));
684 if (!xkb->map->modmap) {
685 free(prev_modmap);
686 return BadAlloc;
687 }
688 memset((char *) &xkb->map->modmap[xkb->max_key_code], 0, tmp);
689 if (changes) {
690 changes->map.changed = _ExtendRange(changes->map.changed,
691 XkbModifierMapMask,
692 maxKC,
693 &changes->map.
694 first_modmap_key,
695 &changes->map.
696 num_modmap_keys);
697 }
698 }
699 }
700 if (xkb->server) {
701 if (xkb->server->behaviors) {
702 XkbBehavior *prev_behaviors = xkb->server->behaviors;
703
704 xkb->server->behaviors = reallocarray(xkb->server->behaviors,
705 maxKC + 1,
706 sizeof(XkbBehavior));
707 if (!xkb->server->behaviors) {
708 free(prev_behaviors);
709 return BadAlloc;
710 }
711 memset((char *) &xkb->server->behaviors[xkb->max_key_code], 0,
712 tmp * sizeof(XkbBehavior));
713 if (changes) {
714 changes->map.changed = _ExtendRange(changes->map.changed,
715 XkbKeyBehaviorsMask,
716 maxKC,
717 &changes->map.
718 first_key_behavior,
719 &changes->map.
720 num_key_behaviors);
721 }
722 }
723 if (xkb->server->key_acts) {
724 unsigned short *prev_key_acts = xkb->server->key_acts;
725
726 xkb->server->key_acts = reallocarray(xkb->server->key_acts,
727 maxKC + 1,
728 sizeof(unsigned short));
729 if (!xkb->server->key_acts) {
730 free(prev_key_acts);
731 return BadAlloc;
732 }
733 memset((char *) &xkb->server->key_acts[xkb->max_key_code], 0,
734 tmp * sizeof(unsigned short));
735 if (changes) {
736 changes->map.changed = _ExtendRange(changes->map.changed,
737 XkbKeyActionsMask,
738 maxKC,
739 &changes->map.
740 first_key_act,
741 &changes->map.
742 num_key_acts);
743 }
744 }
745 if (xkb->server->vmodmap) {
746 unsigned short *prev_vmodmap = xkb->server->vmodmap;
747
748 xkb->server->vmodmap = reallocarray(xkb->server->vmodmap,
749 maxKC + 1,
750 sizeof(unsigned short));
751 if (!xkb->server->vmodmap) {
752 free(prev_vmodmap);
753 return BadAlloc;
754 }
755 memset((char *) &xkb->server->vmodmap[xkb->max_key_code], 0,
756 tmp * sizeof(unsigned short));
757 if (changes) {
758 changes->map.changed = _ExtendRange(changes->map.changed,
759 XkbVirtualModMapMask,
760 maxKC,
761 &changes->map.
762 first_modmap_key,
763 &changes->map.
764 num_vmodmap_keys);
765 }
766 }
767 }
768 if ((xkb->names) && (xkb->names->keys)) {
769 XkbKeyNameRec *prev_keys = xkb->names->keys;
770
771 xkb->names->keys = reallocarray(xkb->names->keys,
772 maxKC + 1, sizeof(XkbKeyNameRec));
773 if (!xkb->names->keys) {
774 free(prev_keys);
775 return BadAlloc;
776 }
777 memset((char *) &xkb->names->keys[xkb->max_key_code], 0,
778 tmp * sizeof(XkbKeyNameRec));
779 if (changes) {
780 changes->names.changed = _ExtendRange(changes->names.changed,
781 XkbKeyNamesMask, maxKC,
782 &changes->names.first_key,
783 &changes->names.num_keys);
784 }
785 }
786 xkb->max_key_code = maxKC;
787 }
788 return Success;
789 }
790
791 XkbAction *
XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)792 XkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
793 {
794 register int i, nActs;
795 XkbAction *newActs;
796
797 if (needed == 0) {
798 xkb->server->key_acts[key] = 0;
799 return NULL;
800 }
801 if (XkbKeyHasActions(xkb, key) &&
802 (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
803 return XkbKeyActionsPtr(xkb, key);
804 if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
805 xkb->server->key_acts[key] = xkb->server->num_acts;
806 xkb->server->num_acts += needed;
807 return &xkb->server->acts[xkb->server->key_acts[key]];
808 }
809 xkb->server->size_acts = xkb->server->num_acts + needed + 8;
810 newActs = calloc(xkb->server->size_acts, sizeof(XkbAction));
811 if (newActs == NULL)
812 return NULL;
813 newActs[0].type = XkbSA_NoAction;
814 nActs = 1;
815 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
816 int nKeyActs, nCopy;
817
818 if ((xkb->server->key_acts[i] == 0) && (i != key))
819 continue;
820
821 nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
822 if (i == key) {
823 nKeyActs = needed;
824 if (needed < nCopy)
825 nCopy = needed;
826 }
827
828 if (nCopy > 0)
829 memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
830 nCopy * sizeof(XkbAction));
831 if (nCopy < nKeyActs)
832 memset(&newActs[nActs + nCopy], 0,
833 (nKeyActs - nCopy) * sizeof(XkbAction));
834 xkb->server->key_acts[i] = nActs;
835 nActs += nKeyActs;
836 }
837 free(xkb->server->acts);
838 xkb->server->acts = newActs;
839 xkb->server->num_acts = nActs;
840 return &xkb->server->acts[xkb->server->key_acts[key]];
841 }
842
843 void
XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)844 XkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
845 {
846 XkbClientMapPtr map;
847
848 if ((xkb == NULL) || (xkb->map == NULL))
849 return;
850 if (freeMap)
851 what = XkbAllClientInfoMask;
852 map = xkb->map;
853 if (what & XkbKeyTypesMask) {
854 if (map->types != NULL) {
855 if (map->num_types > 0) {
856 register int i;
857 XkbKeyTypePtr type;
858
859 for (i = 0, type = map->types; i < map->num_types; i++, type++) {
860 free(type->map);
861 type->map = NULL;
862 free(type->preserve);
863 type->preserve = NULL;
864 type->map_count = 0;
865 free(type->level_names);
866 type->level_names = NULL;
867 }
868 }
869 free(map->types);
870 map->num_types = map->size_types = 0;
871 map->types = NULL;
872 }
873 }
874 if (what & XkbKeySymsMask) {
875 free(map->key_sym_map);
876 map->key_sym_map = NULL;
877 if (map->syms != NULL) {
878 free(map->syms);
879 map->size_syms = map->num_syms = 0;
880 map->syms = NULL;
881 }
882 }
883 if ((what & XkbModifierMapMask) && (map->modmap != NULL)) {
884 free(map->modmap);
885 map->modmap = NULL;
886 }
887 if (freeMap) {
888 free(xkb->map);
889 xkb->map = NULL;
890 }
891 return;
892 }
893
894 void
XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)895 XkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
896 {
897 XkbServerMapPtr map;
898
899 if ((xkb == NULL) || (xkb->server == NULL))
900 return;
901 if (freeMap)
902 what = XkbAllServerInfoMask;
903 map = xkb->server;
904 if ((what & XkbExplicitComponentsMask) && (map->explicit != NULL)) {
905 free(map->explicit);
906 map->explicit = NULL;
907 }
908 if (what & XkbKeyActionsMask) {
909 free(map->key_acts);
910 map->key_acts = NULL;
911 if (map->acts != NULL) {
912 free(map->acts);
913 map->num_acts = map->size_acts = 0;
914 map->acts = NULL;
915 }
916 }
917 if ((what & XkbKeyBehaviorsMask) && (map->behaviors != NULL)) {
918 free(map->behaviors);
919 map->behaviors = NULL;
920 }
921 if ((what & XkbVirtualModMapMask) && (map->vmodmap != NULL)) {
922 free(map->vmodmap);
923 map->vmodmap = NULL;
924 }
925
926 if (freeMap) {
927 free(xkb->server);
928 xkb->server = NULL;
929 }
930 return;
931 }
932