XKBMAlloc.c revision 818534a1
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31
32#include <stdio.h>
33#include "Xlibint.h"
34#include <X11/extensions/XKBproto.h>
35#include <X11/keysym.h>
36#include "XKBlibint.h"
37
38
39/***====================================================================***/
40
41Status
42XkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes)
43{
44    register int i;
45    XkbClientMapPtr map;
46
47    if ((xkb == NULL) ||
48        ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
49        return BadValue;
50    if ((which & XkbKeySymsMask) &&
51        ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
52         (!XkbIsLegalKeycode(xkb->max_key_code)) ||
53         (xkb->max_key_code < xkb->min_key_code))) {
54#ifdef DEBUG
55        fprintf(stderr, "bad keycode (%d,%d) in XkbAllocClientMap\n",
56                xkb->min_key_code, xkb->max_key_code);
57#endif
58        return BadValue;
59    }
60
61    if (xkb->map == NULL) {
62        map = _XkbTypedCalloc(1, XkbClientMapRec);
63        if (map == NULL)
64            return BadAlloc;
65        xkb->map = map;
66    }
67    else
68        map = xkb->map;
69
70    if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
71        if (map->types == NULL) {
72            map->types = _XkbTypedCalloc(nTotalTypes, XkbKeyTypeRec);
73            if (map->types == NULL)
74                return BadAlloc;
75            map->num_types = 0;
76            map->size_types = nTotalTypes;
77        }
78        else if (map->size_types < nTotalTypes) {
79            XkbKeyTypeRec *prev_types = map->types;
80
81            map->types =
82                _XkbTypedRealloc(map->types, nTotalTypes, XkbKeyTypeRec);
83            if (map->types == NULL) {
84                _XkbFree(prev_types);
85                map->num_types = map->size_types = 0;
86                return BadAlloc;
87            }
88            map->size_types = nTotalTypes;
89            bzero(&map->types[map->num_types],
90                  ((map->size_types - 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 = _XkbTypedCalloc(map->size_syms, 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 = _XkbTypedCalloc(i, 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 = _XkbTypedCalloc(i, unsigned char);
121            if (map->modmap == NULL)
122                return BadAlloc;
123        }
124    }
125    return Success;
126}
127
128Status
129XkbAllocServerMap(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 = _XkbTypedCalloc(1, 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 = _XkbTypedCalloc(i, 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 = _XkbTypedCalloc((nNewActions + 1), 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 = _XkbTypedRealloc(map->acts, need, XkbAction);
179            if (map->acts == NULL) {
180                _XkbFree(prev_acts);
181                map->num_acts = map->size_acts = 0;
182                return BadAlloc;
183            }
184            map->size_acts = need;
185            bzero(&map->acts[map->num_acts],
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 = _XkbTypedCalloc(i, 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 = _XkbTypedCalloc(i, 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 = _XkbTypedCalloc(i, unsigned short);
215            if (map->vmodmap == NULL)
216                return BadAlloc;
217        }
218    }
219    return Success;
220}
221
222/***====================================================================***/
223
224Status
225XkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into)
226{
227    if ((!from) || (!into))
228        return BadMatch;
229    if (into->map) {
230        _XkbFree(into->map);
231        into->map = NULL;
232    }
233    if (into->preserve) {
234        _XkbFree(into->preserve);
235        into->preserve = NULL;
236    }
237    if (into->level_names) {
238        _XkbFree(into->level_names);
239        into->level_names = NULL;
240    }
241    *into = *from;
242    if ((from->map) && (into->map_count > 0)) {
243        into->map = _XkbTypedCalloc(into->map_count, XkbKTMapEntryRec);
244        if (!into->map)
245            return BadAlloc;
246        memcpy(into->map, from->map,
247               into->map_count * sizeof(XkbKTMapEntryRec));
248    }
249    if ((from->preserve) && (into->map_count > 0)) {
250        into->preserve = _XkbTypedCalloc(into->map_count, XkbModsRec);
251        if (!into->preserve)
252            return BadAlloc;
253        memcpy(into->preserve, from->preserve,
254               into->map_count * sizeof(XkbModsRec));
255    }
256    if ((from->level_names) && (into->num_levels > 0)) {
257        into->level_names = _XkbTypedCalloc(into->num_levels, Atom);
258        if (!into->level_names)
259            return BadAlloc;
260        memcpy(into->level_names, from->level_names,
261               into->num_levels * sizeof(Atom));
262    }
263    return Success;
264}
265
266Status
267XkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types)
268{
269    register int i, rtrn;
270
271    if ((!from) || (!into) || (num_types < 0))
272        return BadMatch;
273    for (i = 0; i < num_types; i++) {
274        if ((rtrn = XkbCopyKeyType(from++, into++)) != Success)
275            return rtrn;
276    }
277    return Success;
278}
279
280XkbKeyTypePtr
281XkbAddKeyType(XkbDescPtr xkb,
282              Atom name,
283              int map_count,
284              Bool want_preserve,
285              int num_lvls)
286{
287    register int i;
288    unsigned tmp;
289    XkbKeyTypePtr type;
290    XkbClientMapPtr map;
291
292    if ((!xkb) || (num_lvls < 1))
293        return NULL;
294    map = xkb->map;
295    if ((map) && (map->types)) {
296        for (i = 0; i < map->num_types; i++) {
297            if (map->types[i].name == name) {
298                Status status =
299                    XkbResizeKeyType(xkb, i, map_count, want_preserve,
300                                     num_lvls);
301                return (status == Success ? &map->types[i] : NULL);
302            }
303        }
304    }
305    if ((!map) || (!map->types) || (!map->num_types < XkbNumRequiredTypes)) {
306        tmp = XkbNumRequiredTypes + 1;
307        if (XkbAllocClientMap(xkb, XkbKeyTypesMask, tmp) != Success)
308            return NULL;
309        if (!map)
310            map = xkb->map;
311        tmp = 0;
312        if (map->num_types <= XkbKeypadIndex)
313            tmp |= XkbKeypadMask;
314        if (map->num_types <= XkbAlphabeticIndex)
315            tmp |= XkbAlphabeticMask;
316        if (map->num_types <= XkbTwoLevelIndex)
317            tmp |= XkbTwoLevelMask;
318        if (map->num_types <= XkbOneLevelIndex)
319            tmp |= XkbOneLevelMask;
320        if (XkbInitCanonicalKeyTypes(xkb, tmp, XkbNoModifier) == Success) {
321            for (i = 0; i < map->num_types; i++) {
322                Status status;
323
324                if (map->types[i].name != name)
325                    continue;
326                status = XkbResizeKeyType(xkb, i, map_count, want_preserve,
327                                          num_lvls);
328                return (status == Success ? &map->types[i] : NULL);
329            }
330        }
331    }
332    if ((map->num_types <= map->size_types) &&
333        (XkbAllocClientMap(xkb, XkbKeyTypesMask, map->num_types + 1) !=
334         Success)) {
335        return NULL;
336    }
337    type = &map->types[map->num_types];
338    map->num_types++;
339    bzero((char *) type, sizeof(XkbKeyTypeRec));
340    type->num_levels = num_lvls;
341    type->map_count = map_count;
342    type->name = name;
343    if (map_count > 0) {
344        type->map = _XkbTypedCalloc(map_count, XkbKTMapEntryRec);
345        if (!type->map) {
346            map->num_types--;
347            return NULL;
348        }
349        if (want_preserve) {
350            type->preserve = _XkbTypedCalloc(map_count, XkbModsRec);
351            if (!type->preserve) {
352                _XkbFree(type->map);
353                map->num_types--;
354                return NULL;
355            }
356        }
357    }
358    return type;
359}
360
361Status
362XkbResizeKeyType(XkbDescPtr xkb,
363                 int type_ndx,
364                 int map_count,
365                 Bool want_preserve,
366                 int new_num_lvls)
367{
368    XkbKeyTypePtr type;
369    KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys;
370
371    if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0)
372        || (new_num_lvls < 1))
373        return BadValue;
374    switch (type_ndx) {
375    case XkbOneLevelIndex:
376        if (new_num_lvls != 1)
377            return BadMatch;
378        break;
379    case XkbTwoLevelIndex:
380    case XkbAlphabeticIndex:
381    case XkbKeypadIndex:
382        if (new_num_lvls != 2)
383            return BadMatch;
384        break;
385    }
386    type = &xkb->map->types[type_ndx];
387    if (map_count == 0) {
388        if (type->map != NULL)
389            _XkbFree(type->map);
390        type->map = NULL;
391        if (type->preserve != NULL)
392            _XkbFree(type->preserve);
393        type->preserve = NULL;
394        type->map_count = 0;
395    }
396    else {
397        XkbKTMapEntryRec *prev_map = type->map;
398
399        if ((map_count > type->map_count) || (type->map == NULL))
400            type->map =
401                _XkbTypedRealloc(type->map, map_count, XkbKTMapEntryRec);
402        if (!type->map) {
403            if (prev_map)
404                _XkbFree(prev_map);
405            return BadAlloc;
406        }
407        if (want_preserve) {
408            XkbModsRec *prev_preserve = type->preserve;
409
410            if ((map_count > type->map_count) || (type->preserve == NULL)) {
411                type->preserve = _XkbTypedRealloc(type->preserve, map_count,
412                                                  XkbModsRec);
413            }
414            if (!type->preserve) {
415                if (prev_preserve)
416                    _XkbFree(prev_preserve);
417                return BadAlloc;
418            }
419        }
420        else if (type->preserve != NULL) {
421            _XkbFree(type->preserve);
422            type->preserve = NULL;
423        }
424        type->map_count = map_count;
425    }
426
427    if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) {
428        Atom *prev_level_names = type->level_names;
429
430        type->level_names =
431            _XkbTypedRealloc(type->level_names, new_num_lvls, Atom);
432        if (!type->level_names) {
433            if (prev_level_names)
434                _XkbFree(prev_level_names);
435            return BadAlloc;
436        }
437    }
438    /*
439     * Here's the theory:
440     *    If the width of the type changed, we might have to resize the symbol
441     * maps for any keys that use the type for one or more groups.  This is
442     * expensive, so we'll try to cull out any keys that are obviously okay:
443     * In any case:
444     *    - keys that have a group width <= the old width are okay (because
445     *      they could not possibly have been associated with the old type)
446     * If the key type increased in size:
447     *    - keys that already have a group width >= to the new width are okay
448     *    + keys that have a group width >= the old width but < the new width
449     *      might have to be enlarged.
450     * If the key type decreased in size:
451     *    - keys that have a group width > the old width don't have to be
452     *      resized (because they must have some other wider type associated
453     *      with some group).
454     *    + keys that have a group width == the old width might have to be
455     *      shrunk.
456     * The possibilities marked with '+' require us to examine the key types
457     * associated with each group for the key.
458     */
459    bzero(matchingKeys, XkbMaxKeyCount * sizeof(KeyCode));
460    nMatchingKeys = 0;
461    if (new_num_lvls > type->num_levels) {
462        int nTotal;
463        KeySym *newSyms;
464        int width, match, nResize;
465        register int i, g, nSyms;
466
467        nResize = 0;
468        for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
469            width = XkbKeyGroupsWidth(xkb, i);
470            if (width < type->num_levels)
471                continue;
472            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
473                 (g >= 0) && (!match); g--) {
474                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
475                    matchingKeys[nMatchingKeys++] = i;
476                    match = 1;
477                }
478            }
479            if ((!match) || (width >= new_num_lvls))
480                nTotal += XkbKeyNumSyms(xkb, i);
481            else {
482                nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
483                nResize++;
484            }
485        }
486        if (nResize > 0) {
487            int nextMatch;
488
489            xkb->map->size_syms = (nTotal * 12) / 10;
490            newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
491            if (newSyms == NULL)
492                return BadAlloc;
493            nextMatch = 0;
494            nSyms = 1;
495            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
496                if (matchingKeys[nextMatch] == i) {
497                    KeySym *pOld;
498
499                    nextMatch++;
500                    width = XkbKeyGroupsWidth(xkb, i);
501                    pOld = XkbKeySymsPtr(xkb, i);
502                    for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
503                        memcpy(&newSyms[nSyms + (new_num_lvls * g)],
504                               &pOld[width * g], width * sizeof(KeySym));
505                    }
506                    xkb->map->key_sym_map[i].offset = nSyms;
507                    nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
508                }
509                else {
510                    memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
511                           XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
512                    xkb->map->key_sym_map[i].offset = nSyms;
513                    nSyms += XkbKeyNumSyms(xkb, i);
514                }
515            }
516            type->num_levels = new_num_lvls;
517            _XkbFree(xkb->map->syms);
518            xkb->map->syms = newSyms;
519            xkb->map->num_syms = nSyms;
520            return Success;
521        }
522    }
523    else if (new_num_lvls < type->num_levels) {
524        int width, match;
525        register int g, i;
526
527        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
528            width = XkbKeyGroupsWidth(xkb, i);
529            if (width < type->num_levels)
530                continue;
531            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
532                 (g >= 0) && (!match); g--) {
533                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
534                    matchingKeys[nMatchingKeys++] = i;
535                    match = 1;
536                }
537            }
538        }
539    }
540    if (nMatchingKeys > 0) {
541        int key, firstClear;
542        register int i, g;
543
544        if (new_num_lvls > type->num_levels)
545            firstClear = type->num_levels;
546        else
547            firstClear = new_num_lvls;
548        for (i = 0; i < nMatchingKeys; i++) {
549            KeySym *pSyms;
550            int width, nClear;
551
552            key = matchingKeys[i];
553            width = XkbKeyGroupsWidth(xkb, key);
554            nClear = width - firstClear;
555            pSyms = XkbKeySymsPtr(xkb, key);
556            for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
557                if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
558                    if (nClear > 0)
559                        bzero(&pSyms[g * width + firstClear],
560                              nClear * sizeof(KeySym));
561                }
562            }
563        }
564    }
565    type->num_levels = new_num_lvls;
566    return Success;
567}
568
569KeySym *
570XkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
571{
572    register int i, nSyms, nKeySyms;
573    unsigned nOldSyms;
574    KeySym *newSyms;
575
576    if (needed == 0) {
577        xkb->map->key_sym_map[key].offset = 0;
578        return xkb->map->syms;
579    }
580    nOldSyms = XkbKeyNumSyms(xkb, key);
581    if (nOldSyms >= (unsigned) needed) {
582        return XkbKeySymsPtr(xkb, key);
583    }
584    if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
585        if (nOldSyms > 0) {
586            memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
587                   nOldSyms * sizeof(KeySym));
588        }
589        if ((needed - nOldSyms) > 0) {
590            bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)],
591                  (needed - nOldSyms) * sizeof(KeySym));
592        }
593        xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
594        xkb->map->num_syms += needed;
595        return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
596    }
597    xkb->map->size_syms += (needed > 32 ? needed : 32);
598    newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
599    if (newSyms == NULL)
600        return NULL;
601    newSyms[0] = NoSymbol;
602    nSyms = 1;
603    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
604        int nCopy;
605
606        nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
607        if ((nKeySyms == 0) && (i != key))
608            continue;
609        if (i == key)
610            nKeySyms = needed;
611        if (nCopy != 0)
612            memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
613                   nCopy * sizeof(KeySym));
614        if (nKeySyms > nCopy)
615            bzero(&newSyms[nSyms + nCopy], (nKeySyms - nCopy) * sizeof(KeySym));
616        xkb->map->key_sym_map[i].offset = nSyms;
617        nSyms += nKeySyms;
618    }
619    _XkbFree(xkb->map->syms);
620    xkb->map->syms = newSyms;
621    xkb->map->num_syms = nSyms;
622    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
623}
624
625static unsigned
626_ExtendRange(unsigned int old_flags,
627             unsigned int flag,
628             KeyCode newKC,
629             KeyCode *old_min,
630             unsigned char *old_num)
631{
632    if ((old_flags & flag) == 0) {
633        old_flags |= flag;
634        *old_min = newKC;
635        *old_num = 1;
636    }
637    else {
638        int last = (*old_min) + (*old_num) - 1;
639
640        if (newKC < *old_min) {
641            *old_min = newKC;
642            *old_num = (last - newKC) + 1;
643        }
644        else if (newKC > last) {
645            *old_num = (newKC - (*old_min)) + 1;
646        }
647    }
648    return old_flags;
649}
650
651Status
652XkbChangeKeycodeRange(XkbDescPtr xkb,
653                      int minKC,
654                      int maxKC,
655                      XkbChangesPtr changes)
656{
657    int tmp;
658
659    if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
660        return BadValue;
661    if (minKC > maxKC)
662        return BadMatch;
663    if (minKC < xkb->min_key_code) {
664        if (changes)
665            changes->map.min_key_code = minKC;
666        tmp = xkb->min_key_code - minKC;
667        if (xkb->map) {
668            if (xkb->map->key_sym_map) {
669                bzero((char *) &xkb->map->key_sym_map[minKC],
670                      tmp * sizeof(XkbSymMapRec));
671                if (changes) {
672                    changes->map.changed = _ExtendRange(changes->map.changed,
673                                                XkbKeySymsMask, minKC,
674                                                &changes->map.first_key_sym,
675                                                &changes->map.num_key_syms);
676                }
677            }
678            if (xkb->map->modmap) {
679                bzero((char *) &xkb->map->modmap[minKC], tmp);
680                if (changes) {
681                    changes->map.changed = _ExtendRange(changes->map.changed,
682                                                XkbModifierMapMask, minKC,
683                                                &changes->map.first_modmap_key,
684                                                &changes->map.num_modmap_keys);
685                }
686            }
687        }
688        if (xkb->server) {
689            if (xkb->server->behaviors) {
690                bzero((char *) &xkb->server->behaviors[minKC],
691                      tmp * sizeof(XkbBehavior));
692                if (changes) {
693                    changes->map.changed = _ExtendRange(changes->map.changed,
694                                              XkbKeyBehaviorsMask, minKC,
695                                              &changes->map.first_key_behavior,
696                                              &changes->map.num_key_behaviors);
697                }
698            }
699            if (xkb->server->key_acts) {
700                bzero((char *) &xkb->server->key_acts[minKC],
701                      tmp * sizeof(unsigned short));
702                if (changes) {
703                    changes->map.changed = _ExtendRange(changes->map.changed,
704                                                XkbKeyActionsMask, minKC,
705                                                &changes->map.first_key_act,
706                                                &changes->map.num_key_acts);
707                }
708            }
709            if (xkb->server->vmodmap) {
710                bzero((char *) &xkb->server->vmodmap[minKC],
711                      tmp * sizeof(unsigned short));
712                if (changes) {
713                    changes->map.changed = _ExtendRange(changes->map.changed,
714                                                XkbVirtualModMapMask, minKC,
715                                                &changes->map.first_modmap_key,
716                                                &changes->map.num_vmodmap_keys);
717                }
718            }
719        }
720        if ((xkb->names) && (xkb->names->keys)) {
721            bzero((char *) &xkb->names->keys[minKC],
722                  tmp * sizeof(XkbKeyNameRec));
723            if (changes) {
724                changes->names.changed = _ExtendRange(changes->names.changed,
725                                                      XkbKeyNamesMask, minKC,
726                                                      &changes->names.first_key,
727                                                      &changes->names.num_keys);
728            }
729        }
730        xkb->min_key_code = minKC;
731    }
732    if (maxKC > xkb->max_key_code) {
733        if (changes)
734            changes->map.max_key_code = maxKC;
735        tmp = maxKC - xkb->max_key_code;
736        if (xkb->map) {
737            if (xkb->map->key_sym_map) {
738                XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
739
740                xkb->map->key_sym_map = _XkbTypedRealloc(xkb->map->key_sym_map,
741                                                    (maxKC + 1), XkbSymMapRec);
742                if (!xkb->map->key_sym_map) {
743                    _XkbFree(prev_key_sym_map);
744                    return BadAlloc;
745                }
746                bzero((char *) &xkb->map->key_sym_map[xkb->max_key_code],
747                      tmp * sizeof(XkbSymMapRec));
748                if (changes) {
749                    changes->map.changed = _ExtendRange(changes->map.changed,
750                                                XkbKeySymsMask, maxKC,
751                                                &changes->map.first_key_sym,
752                                                &changes->map.num_key_syms);
753                }
754            }
755            if (xkb->map->modmap) {
756                unsigned char *prev_modmap = xkb->map->modmap;
757
758                xkb->map->modmap = _XkbTypedRealloc(xkb->map->modmap,
759                                                    (maxKC + 1), unsigned char);
760                if (!xkb->map->modmap) {
761                    _XkbFree(prev_modmap);
762                    return BadAlloc;
763                }
764                bzero((char *) &xkb->map->modmap[xkb->max_key_code], tmp);
765                if (changes) {
766                    changes->map.changed = _ExtendRange(changes->map.changed,
767                                                XkbModifierMapMask, maxKC,
768                                                &changes->map.first_modmap_key,
769                                                &changes->map.num_modmap_keys);
770                }
771            }
772        }
773        if (xkb->server) {
774            if (xkb->server->behaviors) {
775                XkbBehavior *prev_behaviors = xkb->server->behaviors;
776
777                xkb->server->behaviors =
778                    _XkbTypedRealloc(xkb->server->behaviors, (maxKC + 1),
779                                     XkbBehavior);
780                if (!xkb->server->behaviors) {
781                    _XkbFree(prev_behaviors);
782                    return BadAlloc;
783                }
784                bzero((char *) &xkb->server->behaviors[xkb->max_key_code],
785                      tmp * sizeof(XkbBehavior));
786                if (changes) {
787                    changes->map.changed = _ExtendRange(changes->map.changed,
788                                                XkbKeyBehaviorsMask, maxKC,
789                                                &changes->map.first_key_behavior,
790                                                &changes->map.num_key_behaviors);
791                }
792            }
793            if (xkb->server->key_acts) {
794                unsigned short *prev_key_acts = xkb->server->key_acts;
795
796                xkb->server->key_acts = _XkbTypedRealloc(xkb->server->key_acts,
797                                                (maxKC + 1), unsigned short);
798                if (!xkb->server->key_acts) {
799                    _XkbFree(prev_key_acts);
800                    return BadAlloc;
801                }
802                bzero((char *) &xkb->server->key_acts[xkb->max_key_code],
803                      tmp * sizeof(unsigned short));
804                if (changes) {
805                    changes->map.changed = _ExtendRange(changes->map.changed,
806                                                XkbKeyActionsMask, maxKC,
807                                                &changes->map.first_key_act,
808                                                &changes->map.num_key_acts);
809                }
810            }
811            if (xkb->server->vmodmap) {
812                unsigned short *prev_vmodmap = xkb->server->vmodmap;
813
814                xkb->server->vmodmap = _XkbTypedRealloc(xkb->server->vmodmap,
815                                                (maxKC + 1), unsigned short);
816                if (!xkb->server->vmodmap) {
817                    _XkbFree(prev_vmodmap);
818                    return BadAlloc;
819                }
820                bzero((char *) &xkb->server->vmodmap[xkb->max_key_code],
821                      tmp * sizeof(unsigned short));
822                if (changes) {
823                    changes->map.changed = _ExtendRange(changes->map.changed,
824                                                XkbVirtualModMapMask, maxKC,
825                                                &changes->map.first_modmap_key,
826                                                &changes->map.num_vmodmap_keys);
827                }
828            }
829        }
830        if ((xkb->names) && (xkb->names->keys)) {
831            XkbKeyNameRec *prev_keys = xkb->names->keys;
832
833            xkb->names->keys = _XkbTypedRealloc(xkb->names->keys,
834                                                (maxKC + 1), XkbKeyNameRec);
835            if (!xkb->names->keys) {
836                _XkbFree(prev_keys);
837                return BadAlloc;
838            }
839            bzero((char *) &xkb->names->keys[xkb->max_key_code],
840                  tmp * sizeof(XkbKeyNameRec));
841            if (changes) {
842                changes->names.changed = _ExtendRange(changes->names.changed,
843                                                      XkbKeyNamesMask, maxKC,
844                                                      &changes->names.first_key,
845                                                      &changes->names.num_keys);
846            }
847        }
848        xkb->max_key_code = maxKC;
849    }
850    return Success;
851}
852
853XkbAction *
854XkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
855{
856    register int i, nActs;
857    XkbAction *newActs;
858
859    if (needed == 0) {
860        xkb->server->key_acts[key] = 0;
861        return NULL;
862    }
863    if (XkbKeyHasActions(xkb, key) &&
864        (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
865        return XkbKeyActionsPtr(xkb, key);
866    if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
867        xkb->server->key_acts[key] = xkb->server->num_acts;
868        xkb->server->num_acts += needed;
869        return &xkb->server->acts[xkb->server->key_acts[key]];
870    }
871    xkb->server->size_acts = xkb->server->num_acts + needed + 8;
872    newActs = _XkbTypedCalloc(xkb->server->size_acts, XkbAction);
873    if (newActs == NULL)
874        return NULL;
875    newActs[0].type = XkbSA_NoAction;
876    nActs = 1;
877    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
878        int nKeyActs, nCopy;
879
880        if ((xkb->server->key_acts[i] == 0) && (i != key))
881            continue;
882
883        nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
884        if (i == key) {
885            nKeyActs = needed;
886            if (needed < nCopy)
887                nCopy = needed;
888        }
889
890        if (nCopy > 0)
891            memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
892                   nCopy * sizeof(XkbAction));
893        if (nCopy < nKeyActs)
894            bzero(&newActs[nActs + nCopy],
895                  (nKeyActs - nCopy) * sizeof(XkbAction));
896        xkb->server->key_acts[i] = nActs;
897        nActs += nKeyActs;
898    }
899    _XkbFree(xkb->server->acts);
900    xkb->server->acts = newActs;
901    xkb->server->num_acts = nActs;
902    return &xkb->server->acts[xkb->server->key_acts[key]];
903}
904
905void
906XkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
907{
908    XkbClientMapPtr map;
909
910    if ((xkb == NULL) || (xkb->map == NULL))
911        return;
912    if (freeMap)
913        what = XkbAllClientInfoMask;
914    map = xkb->map;
915    if (what & XkbKeyTypesMask) {
916        if (map->types != NULL) {
917            if (map->num_types > 0) {
918                register int i;
919                XkbKeyTypePtr type;
920
921                for (i = 0, type = map->types; i < map->num_types; i++, type++) {
922                    if (type->map != NULL) {
923                        _XkbFree(type->map);
924                        type->map = NULL;
925                    }
926                    if (type->preserve != NULL) {
927                        _XkbFree(type->preserve);
928                        type->preserve = NULL;
929                    }
930                    type->map_count = 0;
931                    if (type->level_names != NULL) {
932                        _XkbFree(type->level_names);
933                        type->level_names = NULL;
934                    }
935                }
936            }
937            _XkbFree(map->types);
938            map->num_types = map->size_types = 0;
939            map->types = NULL;
940        }
941    }
942    if (what & XkbKeySymsMask) {
943        if (map->key_sym_map != NULL) {
944            _XkbFree(map->key_sym_map);
945            map->key_sym_map = NULL;
946        }
947        if (map->syms != NULL) {
948            _XkbFree(map->syms);
949            map->size_syms = map->num_syms = 0;
950            map->syms = NULL;
951        }
952    }
953    if ((what & XkbModifierMapMask) && (map->modmap != NULL)) {
954        _XkbFree(map->modmap);
955        map->modmap = NULL;
956    }
957    if (freeMap) {
958        _XkbFree(xkb->map);
959        xkb->map = NULL;
960    }
961    return;
962}
963
964void
965XkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
966{
967    XkbServerMapPtr map;
968
969    if ((xkb == NULL) || (xkb->server == NULL))
970        return;
971    if (freeMap)
972        what = XkbAllServerInfoMask;
973    map = xkb->server;
974    if ((what & XkbExplicitComponentsMask) && (map->explicit != NULL)) {
975        _XkbFree(map->explicit);
976        map->explicit = NULL;
977    }
978    if (what & XkbKeyActionsMask) {
979        if (map->key_acts != NULL) {
980            _XkbFree(map->key_acts);
981            map->key_acts = NULL;
982        }
983        if (map->acts != NULL) {
984            _XkbFree(map->acts);
985            map->num_acts = map->size_acts = 0;
986            map->acts = NULL;
987        }
988    }
989    if ((what & XkbKeyBehaviorsMask) && (map->behaviors != NULL)) {
990        _XkbFree(map->behaviors);
991        map->behaviors = NULL;
992    }
993    if ((what & XkbVirtualModMapMask) && (map->vmodmap != NULL)) {
994        _XkbFree(map->vmodmap);
995        map->vmodmap = NULL;
996    }
997
998    if (freeMap) {
999        _XkbFree(xkb->server);
1000        xkb->server = NULL;
1001    }
1002    return;
1003}
1004