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