105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
935c4bbdfSmrgdocumentation, and that the name of Silicon Graphics not be
1035c4bbdfSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1235c4bbdfSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1635c4bbdfSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1735c4bbdfSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1935c4bbdfSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2035c4bbdfSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2135c4bbdfSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <X11/X.h>
3305b261ecSmrg#include <X11/Xproto.h>
3405b261ecSmrg#include "misc.h"
3505b261ecSmrg#include "inputstr.h"
3605b261ecSmrg#include <X11/keysym.h>
3705b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
3805b261ecSmrg#include <xkbsrv.h>
3905b261ecSmrg
4005b261ecSmrg/***====================================================================***/
4105b261ecSmrg
4205b261ecSmrgStatus
4335c4bbdfSmrgXkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes)
4405b261ecSmrg{
4535c4bbdfSmrg    XkbClientMapPtr map;
4635c4bbdfSmrg
4735c4bbdfSmrg    if ((xkb == NULL) ||
4835c4bbdfSmrg        ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
4935c4bbdfSmrg        return BadValue;
5035c4bbdfSmrg    if ((which & XkbKeySymsMask) &&
5135c4bbdfSmrg        ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
5235c4bbdfSmrg         (!XkbIsLegalKeycode(xkb->max_key_code)) ||
5335c4bbdfSmrg         (xkb->max_key_code < xkb->min_key_code))) {
544642e01fSmrg        DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n",
5535c4bbdfSmrg               xkb->min_key_code, xkb->max_key_code);
5635c4bbdfSmrg        return BadValue;
5735c4bbdfSmrg    }
5835c4bbdfSmrg
5935c4bbdfSmrg    if (xkb->map == NULL) {
6035c4bbdfSmrg        map = calloc(1, sizeof(XkbClientMapRec));
6135c4bbdfSmrg        if (map == NULL)
6235c4bbdfSmrg            return BadAlloc;
6335c4bbdfSmrg        xkb->map = map;
6435c4bbdfSmrg    }
6535c4bbdfSmrg    else
6635c4bbdfSmrg        map = xkb->map;
6735c4bbdfSmrg
6835c4bbdfSmrg    if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
6935c4bbdfSmrg        if (map->types == NULL) {
7035c4bbdfSmrg            map->types = calloc(nTotalTypes, sizeof(XkbKeyTypeRec));
7135c4bbdfSmrg            if (map->types == NULL)
7235c4bbdfSmrg                return BadAlloc;
7335c4bbdfSmrg            map->num_types = 0;
7435c4bbdfSmrg            map->size_types = nTotalTypes;
7535c4bbdfSmrg        }
7635c4bbdfSmrg        else if (map->size_types < nTotalTypes) {
7735c4bbdfSmrg            XkbKeyTypeRec *prev_types = map->types;
7835c4bbdfSmrg
7935c4bbdfSmrg            map->types =
8035c4bbdfSmrg                reallocarray(map->types, nTotalTypes, sizeof(XkbKeyTypeRec));
8135c4bbdfSmrg            if (map->types == NULL) {
8235c4bbdfSmrg                free(prev_types);
8335c4bbdfSmrg                map->num_types = map->size_types = 0;
8435c4bbdfSmrg                return BadAlloc;
8535c4bbdfSmrg            }
8635c4bbdfSmrg            map->size_types = nTotalTypes;
8735c4bbdfSmrg            memset(&map->types[map->num_types], 0,
8835c4bbdfSmrg                   ((map->size_types -
8935c4bbdfSmrg                     map->num_types) * sizeof(XkbKeyTypeRec)));
9035c4bbdfSmrg        }
9135c4bbdfSmrg    }
9235c4bbdfSmrg    if (which & XkbKeySymsMask) {
9335c4bbdfSmrg        int nKeys = XkbNumKeys(xkb);
9435c4bbdfSmrg
9535c4bbdfSmrg        if (map->syms == NULL) {
9635c4bbdfSmrg            map->size_syms = (nKeys * 15) / 10;
9735c4bbdfSmrg            map->syms = calloc(map->size_syms, sizeof(KeySym));
9835c4bbdfSmrg            if (!map->syms) {
9935c4bbdfSmrg                map->size_syms = 0;
10035c4bbdfSmrg                return BadAlloc;
10135c4bbdfSmrg            }
10235c4bbdfSmrg            map->num_syms = 1;
10335c4bbdfSmrg            map->syms[0] = NoSymbol;
10435c4bbdfSmrg        }
10535c4bbdfSmrg        if (map->key_sym_map == NULL) {
106f2346221Smrg            map->key_sym_map = calloc(MAP_LENGTH, sizeof(XkbSymMapRec));
10735c4bbdfSmrg            if (map->key_sym_map == NULL)
10835c4bbdfSmrg                return BadAlloc;
10935c4bbdfSmrg        }
11035c4bbdfSmrg    }
11135c4bbdfSmrg    if (which & XkbModifierMapMask) {
11235c4bbdfSmrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
11335c4bbdfSmrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
11435c4bbdfSmrg            (xkb->max_key_code < xkb->min_key_code))
11535c4bbdfSmrg            return BadMatch;
11635c4bbdfSmrg        if (map->modmap == NULL) {
117f2346221Smrg            map->modmap = calloc(MAP_LENGTH, sizeof(unsigned char));
11835c4bbdfSmrg            if (map->modmap == NULL)
11935c4bbdfSmrg                return BadAlloc;
12035c4bbdfSmrg        }
12105b261ecSmrg    }
12205b261ecSmrg    return Success;
12305b261ecSmrg}
12405b261ecSmrg
12505b261ecSmrgStatus
12635c4bbdfSmrgXkbAllocServerMap(XkbDescPtr xkb, unsigned which, unsigned nNewActions)
12705b261ecSmrg{
12835c4bbdfSmrg    register int i;
12935c4bbdfSmrg    XkbServerMapPtr map;
13035c4bbdfSmrg
13135c4bbdfSmrg    if (xkb == NULL)
13235c4bbdfSmrg        return BadMatch;
13335c4bbdfSmrg    if (xkb->server == NULL) {
13435c4bbdfSmrg        map = calloc(1, sizeof(XkbServerMapRec));
13535c4bbdfSmrg        if (map == NULL)
13635c4bbdfSmrg            return BadAlloc;
13735c4bbdfSmrg        for (i = 0; i < XkbNumVirtualMods; i++) {
13835c4bbdfSmrg            map->vmods[i] = XkbNoModifierMask;
13935c4bbdfSmrg        }
14035c4bbdfSmrg        xkb->server = map;
14135c4bbdfSmrg    }
14235c4bbdfSmrg    else
14335c4bbdfSmrg        map = xkb->server;
14435c4bbdfSmrg    if (which & XkbExplicitComponentsMask) {
14535c4bbdfSmrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
14635c4bbdfSmrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
14735c4bbdfSmrg            (xkb->max_key_code < xkb->min_key_code))
14835c4bbdfSmrg            return BadMatch;
14935c4bbdfSmrg        if (map->explicit == NULL) {
150f2346221Smrg            map->explicit = calloc(MAP_LENGTH, sizeof(unsigned char));
15135c4bbdfSmrg            if (map->explicit == NULL)
15235c4bbdfSmrg                return BadAlloc;
15335c4bbdfSmrg        }
15435c4bbdfSmrg    }
15535c4bbdfSmrg    if (which & XkbKeyActionsMask) {
15635c4bbdfSmrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
15735c4bbdfSmrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
15835c4bbdfSmrg            (xkb->max_key_code < xkb->min_key_code))
15935c4bbdfSmrg            return BadMatch;
16035c4bbdfSmrg        if (nNewActions < 1)
16135c4bbdfSmrg            nNewActions = 1;
16235c4bbdfSmrg        if (map->acts == NULL) {
16335c4bbdfSmrg            map->acts = calloc((nNewActions + 1), sizeof(XkbAction));
16435c4bbdfSmrg            if (map->acts == NULL)
16535c4bbdfSmrg                return BadAlloc;
16635c4bbdfSmrg            map->num_acts = 1;
16735c4bbdfSmrg            map->size_acts = nNewActions + 1;
16835c4bbdfSmrg        }
16935c4bbdfSmrg        else if ((map->size_acts - map->num_acts) < nNewActions) {
17035c4bbdfSmrg            unsigned need;
17135c4bbdfSmrg            XkbAction *prev_acts = map->acts;
17235c4bbdfSmrg
17335c4bbdfSmrg            need = map->num_acts + nNewActions;
17435c4bbdfSmrg            map->acts = reallocarray(map->acts, need, sizeof(XkbAction));
17535c4bbdfSmrg            if (map->acts == NULL) {
17635c4bbdfSmrg                free(prev_acts);
17735c4bbdfSmrg                map->num_acts = map->size_acts = 0;
17835c4bbdfSmrg                return BadAlloc;
17935c4bbdfSmrg            }
18035c4bbdfSmrg            map->size_acts = need;
18135c4bbdfSmrg            memset(&map->acts[map->num_acts], 0,
18235c4bbdfSmrg                   ((map->size_acts - map->num_acts) * sizeof(XkbAction)));
18335c4bbdfSmrg        }
18435c4bbdfSmrg        if (map->key_acts == NULL) {
185f2346221Smrg            map->key_acts = calloc(MAP_LENGTH, sizeof(unsigned short));
18635c4bbdfSmrg            if (map->key_acts == NULL)
18735c4bbdfSmrg                return BadAlloc;
18835c4bbdfSmrg        }
18935c4bbdfSmrg    }
19035c4bbdfSmrg    if (which & XkbKeyBehaviorsMask) {
19135c4bbdfSmrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
19235c4bbdfSmrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
19335c4bbdfSmrg            (xkb->max_key_code < xkb->min_key_code))
19435c4bbdfSmrg            return BadMatch;
19535c4bbdfSmrg        if (map->behaviors == NULL) {
196f2346221Smrg            map->behaviors = calloc(MAP_LENGTH, sizeof(XkbBehavior));
19735c4bbdfSmrg            if (map->behaviors == NULL)
19835c4bbdfSmrg                return BadAlloc;
19935c4bbdfSmrg        }
20035c4bbdfSmrg    }
20135c4bbdfSmrg    if (which & XkbVirtualModMapMask) {
20235c4bbdfSmrg        if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
20335c4bbdfSmrg            (!XkbIsLegalKeycode(xkb->max_key_code)) ||
20435c4bbdfSmrg            (xkb->max_key_code < xkb->min_key_code))
20535c4bbdfSmrg            return BadMatch;
20635c4bbdfSmrg        if (map->vmodmap == NULL) {
207f2346221Smrg            map->vmodmap = calloc(MAP_LENGTH, sizeof(unsigned short));
20835c4bbdfSmrg            if (map->vmodmap == NULL)
20935c4bbdfSmrg                return BadAlloc;
21035c4bbdfSmrg        }
21105b261ecSmrg    }
21205b261ecSmrg    return Success;
21305b261ecSmrg}
21405b261ecSmrg
21505b261ecSmrg/***====================================================================***/
21605b261ecSmrg
21705b261ecSmrgstatic Status
21835c4bbdfSmrgXkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into)
21905b261ecSmrg{
22035c4bbdfSmrg    if ((!from) || (!into))
22135c4bbdfSmrg        return BadMatch;
2226747b715Smrg    free(into->map);
2236747b715Smrg    into->map = NULL;
2246747b715Smrg    free(into->preserve);
2256747b715Smrg    into->preserve = NULL;
2266747b715Smrg    free(into->level_names);
2276747b715Smrg    into->level_names = NULL;
22835c4bbdfSmrg    *into = *from;
22935c4bbdfSmrg    if ((from->map) && (into->map_count > 0)) {
23035c4bbdfSmrg        into->map = calloc(into->map_count, sizeof(XkbKTMapEntryRec));
23135c4bbdfSmrg        if (!into->map)
23235c4bbdfSmrg            return BadAlloc;
23335c4bbdfSmrg        memcpy(into->map, from->map,
23435c4bbdfSmrg               into->map_count * sizeof(XkbKTMapEntryRec));
23535c4bbdfSmrg    }
23635c4bbdfSmrg    if ((from->preserve) && (into->map_count > 0)) {
23735c4bbdfSmrg        into->preserve = calloc(into->map_count, sizeof(XkbModsRec));
23835c4bbdfSmrg        if (!into->preserve)
23935c4bbdfSmrg            return BadAlloc;
24035c4bbdfSmrg        memcpy(into->preserve, from->preserve,
24135c4bbdfSmrg               into->map_count * sizeof(XkbModsRec));
24235c4bbdfSmrg    }
24335c4bbdfSmrg    if ((from->level_names) && (into->num_levels > 0)) {
24435c4bbdfSmrg        into->level_names = calloc(into->num_levels, sizeof(Atom));
24535c4bbdfSmrg        if (!into->level_names)
24635c4bbdfSmrg            return BadAlloc;
24735c4bbdfSmrg        memcpy(into->level_names, from->level_names,
24835c4bbdfSmrg               into->num_levels * sizeof(Atom));
24905b261ecSmrg    }
25005b261ecSmrg    return Success;
25105b261ecSmrg}
25205b261ecSmrg
25305b261ecSmrgStatus
25435c4bbdfSmrgXkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types)
25505b261ecSmrg{
25635c4bbdfSmrg    register int i, rtrn;
25705b261ecSmrg
25835c4bbdfSmrg    if ((!from) || (!into) || (num_types < 0))
25935c4bbdfSmrg        return BadMatch;
26035c4bbdfSmrg    for (i = 0; i < num_types; i++) {
26135c4bbdfSmrg        if ((rtrn = XkbCopyKeyType(from++, into++)) != Success)
26235c4bbdfSmrg            return rtrn;
26305b261ecSmrg    }
26405b261ecSmrg    return Success;
26505b261ecSmrg}
26605b261ecSmrg
26705b261ecSmrgStatus
26835c4bbdfSmrgXkbResizeKeyType(XkbDescPtr xkb,
26935c4bbdfSmrg                 int type_ndx,
27035c4bbdfSmrg                 int map_count, Bool want_preserve, int new_num_lvls)
27105b261ecSmrg{
27235c4bbdfSmrg    XkbKeyTypePtr type;
27335c4bbdfSmrg    KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys;
27405b261ecSmrg
27535c4bbdfSmrg    if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0)
27635c4bbdfSmrg        || (new_num_lvls < 1))
27735c4bbdfSmrg        return BadValue;
27805b261ecSmrg    switch (type_ndx) {
27935c4bbdfSmrg    case XkbOneLevelIndex:
28035c4bbdfSmrg        if (new_num_lvls != 1)
28135c4bbdfSmrg            return BadMatch;
28235c4bbdfSmrg        break;
28335c4bbdfSmrg    case XkbTwoLevelIndex:
28435c4bbdfSmrg    case XkbAlphabeticIndex:
28535c4bbdfSmrg    case XkbKeypadIndex:
28635c4bbdfSmrg        if (new_num_lvls != 2)
28735c4bbdfSmrg            return BadMatch;
28835c4bbdfSmrg        break;
28935c4bbdfSmrg    }
29035c4bbdfSmrg    type = &xkb->map->types[type_ndx];
29135c4bbdfSmrg    if (map_count == 0) {
29235c4bbdfSmrg        free(type->map);
29335c4bbdfSmrg        type->map = NULL;
29435c4bbdfSmrg        free(type->preserve);
29535c4bbdfSmrg        type->preserve = NULL;
29635c4bbdfSmrg        type->map_count = 0;
29705b261ecSmrg    }
29805b261ecSmrg    else {
29935c4bbdfSmrg        XkbKTMapEntryRec *prev_map = type->map;
30035c4bbdfSmrg
30135c4bbdfSmrg        if ((map_count > type->map_count) || (type->map == NULL))
30235c4bbdfSmrg            type->map =
30335c4bbdfSmrg                reallocarray(type->map, map_count, sizeof(XkbKTMapEntryRec));
30435c4bbdfSmrg        if (!type->map) {
30535c4bbdfSmrg            free(prev_map);
30635c4bbdfSmrg            return BadAlloc;
30735c4bbdfSmrg        }
30835c4bbdfSmrg        if (want_preserve) {
30935c4bbdfSmrg            XkbModsRec *prev_preserve = type->preserve;
31035c4bbdfSmrg
31135c4bbdfSmrg            if ((map_count > type->map_count) || (type->preserve == NULL)) {
31235c4bbdfSmrg                type->preserve = reallocarray(type->preserve,
31335c4bbdfSmrg                                              map_count, sizeof(XkbModsRec));
31435c4bbdfSmrg            }
31535c4bbdfSmrg            if (!type->preserve) {
31635c4bbdfSmrg                free(prev_preserve);
31735c4bbdfSmrg                return BadAlloc;
31835c4bbdfSmrg            }
31935c4bbdfSmrg        }
32035c4bbdfSmrg        else {
32135c4bbdfSmrg            free(type->preserve);
32235c4bbdfSmrg            type->preserve = NULL;
32335c4bbdfSmrg        }
32435c4bbdfSmrg        type->map_count = map_count;
32535c4bbdfSmrg    }
32635c4bbdfSmrg
32735c4bbdfSmrg    if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) {
32835c4bbdfSmrg        Atom *prev_level_names = type->level_names;
32935c4bbdfSmrg
33035c4bbdfSmrg        type->level_names = reallocarray(type->level_names,
33135c4bbdfSmrg                                         new_num_lvls, sizeof(Atom));
33235c4bbdfSmrg        if (!type->level_names) {
33335c4bbdfSmrg            free(prev_level_names);
33435c4bbdfSmrg            return BadAlloc;
33535c4bbdfSmrg        }
33605b261ecSmrg    }
33705b261ecSmrg    /*
33805b261ecSmrg     * Here's the theory:
33905b261ecSmrg     *    If the width of the type changed, we might have to resize the symbol
34005b261ecSmrg     * maps for any keys that use the type for one or more groups.  This is
34105b261ecSmrg     * expensive, so we'll try to cull out any keys that are obviously okay:
34205b261ecSmrg     * In any case:
34305b261ecSmrg     *    - keys that have a group width <= the old width are okay (because
34405b261ecSmrg     *      they could not possibly have been associated with the old type)
34505b261ecSmrg     * If the key type increased in size:
34605b261ecSmrg     *    - keys that already have a group width >= to the new width are okay
34705b261ecSmrg     *    + keys that have a group width >= the old width but < the new width
34805b261ecSmrg     *      might have to be enlarged.
34905b261ecSmrg     * If the key type decreased in size:
35005b261ecSmrg     *    - keys that have a group width > the old width don't have to be
35135c4bbdfSmrg     *      resized (because they must have some other wider type associated
35205b261ecSmrg     *      with some group).
35305b261ecSmrg     *    + keys that have a group width == the old width might have to be
35405b261ecSmrg     *      shrunk.
35505b261ecSmrg     * The possibilities marked with '+' require us to examine the key types
35605b261ecSmrg     * associated with each group for the key.
35705b261ecSmrg     */
35835c4bbdfSmrg    memset(matchingKeys, 0, XkbMaxKeyCount * sizeof(KeyCode));
35935c4bbdfSmrg    nMatchingKeys = 0;
36035c4bbdfSmrg    if (new_num_lvls > type->num_levels) {
36135c4bbdfSmrg        int nTotal;
36235c4bbdfSmrg        KeySym *newSyms;
36335c4bbdfSmrg        int width, match, nResize;
36435c4bbdfSmrg        register int i, g, nSyms;
36535c4bbdfSmrg
36635c4bbdfSmrg        nResize = 0;
36735c4bbdfSmrg        for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
36835c4bbdfSmrg            width = XkbKeyGroupsWidth(xkb, i);
36935c4bbdfSmrg            if (width < type->num_levels || width >= new_num_lvls) {
37035c4bbdfSmrg                nTotal += XkbKeyNumSyms(xkb,i);
37135c4bbdfSmrg                continue;
37235c4bbdfSmrg            }
37335c4bbdfSmrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
37435c4bbdfSmrg                 (g >= 0) && (!match); g--) {
37535c4bbdfSmrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
37635c4bbdfSmrg                    matchingKeys[nMatchingKeys++] = i;
37735c4bbdfSmrg                    match = 1;
37835c4bbdfSmrg                }
37935c4bbdfSmrg            }
38035c4bbdfSmrg            if (!match)
38135c4bbdfSmrg                nTotal += XkbKeyNumSyms(xkb, i);
38235c4bbdfSmrg            else {
38335c4bbdfSmrg                nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
38435c4bbdfSmrg                nResize++;
38535c4bbdfSmrg            }
38635c4bbdfSmrg        }
38735c4bbdfSmrg        if (nResize > 0) {
38835c4bbdfSmrg            int nextMatch;
38935c4bbdfSmrg
39035c4bbdfSmrg            xkb->map->size_syms = (nTotal * 15) / 10;
39135c4bbdfSmrg            newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
39235c4bbdfSmrg            if (newSyms == NULL)
39335c4bbdfSmrg                return BadAlloc;
39435c4bbdfSmrg            nextMatch = 0;
39535c4bbdfSmrg            nSyms = 1;
39635c4bbdfSmrg            for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
39735c4bbdfSmrg                if (matchingKeys[nextMatch] == i) {
39835c4bbdfSmrg                    KeySym *pOld;
39935c4bbdfSmrg
40035c4bbdfSmrg                    nextMatch++;
40135c4bbdfSmrg                    width = XkbKeyGroupsWidth(xkb, i);
40235c4bbdfSmrg                    pOld = XkbKeySymsPtr(xkb, i);
40335c4bbdfSmrg                    for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
40435c4bbdfSmrg                        memcpy(&newSyms[nSyms + (new_num_lvls * g)],
40535c4bbdfSmrg                               &pOld[width * g], width * sizeof(KeySym));
40635c4bbdfSmrg                    }
40735c4bbdfSmrg                    xkb->map->key_sym_map[i].offset = nSyms;
40835c4bbdfSmrg                    nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
40935c4bbdfSmrg                }
41035c4bbdfSmrg                else {
41135c4bbdfSmrg                    memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
41235c4bbdfSmrg                           XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
41335c4bbdfSmrg                    xkb->map->key_sym_map[i].offset = nSyms;
41435c4bbdfSmrg                    nSyms += XkbKeyNumSyms(xkb, i);
41535c4bbdfSmrg                }
41635c4bbdfSmrg            }
41735c4bbdfSmrg            type->num_levels = new_num_lvls;
41835c4bbdfSmrg            free(xkb->map->syms);
41935c4bbdfSmrg            xkb->map->syms = newSyms;
42035c4bbdfSmrg            xkb->map->num_syms = nSyms;
42135c4bbdfSmrg            return Success;
42235c4bbdfSmrg        }
42335c4bbdfSmrg    }
42435c4bbdfSmrg    else if (new_num_lvls < type->num_levels) {
42535c4bbdfSmrg        int width, match;
42635c4bbdfSmrg        register int g, i;
42735c4bbdfSmrg
42835c4bbdfSmrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
42935c4bbdfSmrg            width = XkbKeyGroupsWidth(xkb, i);
43035c4bbdfSmrg            if (width < type->num_levels)
43135c4bbdfSmrg                continue;
43235c4bbdfSmrg            for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
43335c4bbdfSmrg                 (g >= 0) && (!match); g--) {
43435c4bbdfSmrg                if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
43535c4bbdfSmrg                    matchingKeys[nMatchingKeys++] = i;
43635c4bbdfSmrg                    match = 1;
43735c4bbdfSmrg                }
43835c4bbdfSmrg            }
43935c4bbdfSmrg        }
44035c4bbdfSmrg    }
44135c4bbdfSmrg    if (nMatchingKeys > 0) {
44235c4bbdfSmrg        int key, firstClear;
44335c4bbdfSmrg        register int i, g;
44435c4bbdfSmrg
44535c4bbdfSmrg        if (new_num_lvls > type->num_levels)
44635c4bbdfSmrg            firstClear = type->num_levels;
44735c4bbdfSmrg        else
44835c4bbdfSmrg            firstClear = new_num_lvls;
44935c4bbdfSmrg        for (i = 0; i < nMatchingKeys; i++) {
45035c4bbdfSmrg            KeySym *pSyms;
45135c4bbdfSmrg            int width, nClear;
45235c4bbdfSmrg
45335c4bbdfSmrg            key = matchingKeys[i];
45435c4bbdfSmrg            width = XkbKeyGroupsWidth(xkb, key);
45535c4bbdfSmrg            nClear = width - firstClear;
45635c4bbdfSmrg            pSyms = XkbKeySymsPtr(xkb, key);
45735c4bbdfSmrg            for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
45835c4bbdfSmrg                if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
45935c4bbdfSmrg                    if (nClear > 0)
46035c4bbdfSmrg                        memset(&pSyms[g * width + firstClear], 0,
46135c4bbdfSmrg                               nClear * sizeof(KeySym));
46235c4bbdfSmrg                }
46335c4bbdfSmrg            }
46435c4bbdfSmrg        }
46535c4bbdfSmrg    }
46635c4bbdfSmrg    type->num_levels = new_num_lvls;
46705b261ecSmrg    return Success;
46805b261ecSmrg}
46905b261ecSmrg
47005b261ecSmrgKeySym *
47135c4bbdfSmrgXkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
47205b261ecSmrg{
47335c4bbdfSmrg    register int i, nSyms, nKeySyms;
47435c4bbdfSmrg    unsigned nOldSyms;
47535c4bbdfSmrg    KeySym *newSyms;
47635c4bbdfSmrg
47735c4bbdfSmrg    if (needed == 0) {
47835c4bbdfSmrg        xkb->map->key_sym_map[key].offset = 0;
47935c4bbdfSmrg        return xkb->map->syms;
48035c4bbdfSmrg    }
48135c4bbdfSmrg    nOldSyms = XkbKeyNumSyms(xkb, key);
48235c4bbdfSmrg    if (nOldSyms >= (unsigned) needed) {
48335c4bbdfSmrg        return XkbKeySymsPtr(xkb, key);
48435c4bbdfSmrg    }
48535c4bbdfSmrg    if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
48635c4bbdfSmrg        if (nOldSyms > 0) {
48735c4bbdfSmrg            memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
48835c4bbdfSmrg                   nOldSyms * sizeof(KeySym));
48935c4bbdfSmrg        }
49035c4bbdfSmrg        if ((needed - nOldSyms) > 0) {
49135c4bbdfSmrg            memset(&xkb->map->
49235c4bbdfSmrg                   syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)], 0,
49335c4bbdfSmrg                   (needed - nOldSyms) * sizeof(KeySym));
49435c4bbdfSmrg        }
49535c4bbdfSmrg        xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
49635c4bbdfSmrg        xkb->map->num_syms += needed;
49735c4bbdfSmrg        return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
49835c4bbdfSmrg    }
49935c4bbdfSmrg    xkb->map->size_syms += (needed > 32 ? needed : 32);
5006747b715Smrg    newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
50135c4bbdfSmrg    if (newSyms == NULL)
50235c4bbdfSmrg        return NULL;
50335c4bbdfSmrg    newSyms[0] = NoSymbol;
50405b261ecSmrg    nSyms = 1;
50535c4bbdfSmrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
50635c4bbdfSmrg        int nCopy;
50735c4bbdfSmrg
50835c4bbdfSmrg        nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
50935c4bbdfSmrg        if ((nKeySyms == 0) && (i != key))
51035c4bbdfSmrg            continue;
51135c4bbdfSmrg        if (i == key)
51235c4bbdfSmrg            nKeySyms = needed;
51335c4bbdfSmrg        if (nCopy != 0)
51435c4bbdfSmrg            memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
51535c4bbdfSmrg                   nCopy * sizeof(KeySym));
51635c4bbdfSmrg        if (nKeySyms > nCopy)
51735c4bbdfSmrg            memset(&newSyms[nSyms + nCopy], 0,
51835c4bbdfSmrg                   (nKeySyms - nCopy) * sizeof(KeySym));
51935c4bbdfSmrg        xkb->map->key_sym_map[i].offset = nSyms;
52035c4bbdfSmrg        nSyms += nKeySyms;
52105b261ecSmrg    }
5226747b715Smrg    free(xkb->map->syms);
52305b261ecSmrg    xkb->map->syms = newSyms;
52405b261ecSmrg    xkb->map->num_syms = nSyms;
52505b261ecSmrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
52605b261ecSmrg}
52705b261ecSmrg
52805b261ecSmrgstatic unsigned
52935c4bbdfSmrg_ExtendRange(unsigned int old_flags,
53035c4bbdfSmrg             unsigned int flag,
53135c4bbdfSmrg             KeyCode newKC, KeyCode *old_min, unsigned char *old_num)
53205b261ecSmrg{
53335c4bbdfSmrg    if ((old_flags & flag) == 0) {
53435c4bbdfSmrg        old_flags |= flag;
53535c4bbdfSmrg        *old_min = newKC;
53635c4bbdfSmrg        *old_num = 1;
53705b261ecSmrg    }
53805b261ecSmrg    else {
53935c4bbdfSmrg        int last = (*old_min) + (*old_num) - 1;
54035c4bbdfSmrg
54135c4bbdfSmrg        if (newKC < *old_min) {
54235c4bbdfSmrg            *old_min = newKC;
54335c4bbdfSmrg            *old_num = (last - newKC) + 1;
54435c4bbdfSmrg        }
54535c4bbdfSmrg        else if (newKC > last) {
54635c4bbdfSmrg            *old_num = (newKC - (*old_min)) + 1;
54735c4bbdfSmrg        }
54805b261ecSmrg    }
54905b261ecSmrg    return old_flags;
55005b261ecSmrg}
55105b261ecSmrg
55205b261ecSmrgStatus
55335c4bbdfSmrgXkbChangeKeycodeRange(XkbDescPtr xkb,
55435c4bbdfSmrg                      int minKC, int maxKC, XkbChangesPtr changes)
55505b261ecSmrg{
55635c4bbdfSmrg    int tmp;
55735c4bbdfSmrg
55835c4bbdfSmrg    if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
55935c4bbdfSmrg        return BadValue;
56035c4bbdfSmrg    if (minKC > maxKC)
56135c4bbdfSmrg        return BadMatch;
56235c4bbdfSmrg    if (minKC < xkb->min_key_code) {
56335c4bbdfSmrg        if (changes)
56435c4bbdfSmrg            changes->map.min_key_code = minKC;
56535c4bbdfSmrg        tmp = xkb->min_key_code - minKC;
56635c4bbdfSmrg        if (xkb->map) {
56735c4bbdfSmrg            if (xkb->map->key_sym_map) {
56835c4bbdfSmrg                memset((char *) &xkb->map->key_sym_map[minKC], 0,
56935c4bbdfSmrg                       tmp * sizeof(XkbSymMapRec));
57035c4bbdfSmrg                if (changes) {
57135c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
57235c4bbdfSmrg                                                        XkbKeySymsMask, minKC,
57335c4bbdfSmrg                                                        &changes->map.
57435c4bbdfSmrg                                                        first_key_sym,
57535c4bbdfSmrg                                                        &changes->map.
57635c4bbdfSmrg                                                        num_key_syms);
57735c4bbdfSmrg                }
57835c4bbdfSmrg            }
57935c4bbdfSmrg            if (xkb->map->modmap) {
58035c4bbdfSmrg                memset((char *) &xkb->map->modmap[minKC], 0, tmp);
58135c4bbdfSmrg                if (changes) {
58235c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
58335c4bbdfSmrg                                                        XkbModifierMapMask,
58435c4bbdfSmrg                                                        minKC,
58535c4bbdfSmrg                                                        &changes->map.
58635c4bbdfSmrg                                                        first_modmap_key,
58735c4bbdfSmrg                                                        &changes->map.
58835c4bbdfSmrg                                                        num_modmap_keys);
58935c4bbdfSmrg                }
59035c4bbdfSmrg            }
59135c4bbdfSmrg        }
59235c4bbdfSmrg        if (xkb->server) {
59335c4bbdfSmrg            if (xkb->server->behaviors) {
59435c4bbdfSmrg                memset((char *) &xkb->server->behaviors[minKC], 0,
59535c4bbdfSmrg                       tmp * sizeof(XkbBehavior));
59635c4bbdfSmrg                if (changes) {
59735c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
59835c4bbdfSmrg                                                        XkbKeyBehaviorsMask,
59935c4bbdfSmrg                                                        minKC,
60035c4bbdfSmrg                                                        &changes->map.
60135c4bbdfSmrg                                                        first_key_behavior,
60235c4bbdfSmrg                                                        &changes->map.
60335c4bbdfSmrg                                                        num_key_behaviors);
60435c4bbdfSmrg                }
60535c4bbdfSmrg            }
60635c4bbdfSmrg            if (xkb->server->key_acts) {
60735c4bbdfSmrg                memset((char *) &xkb->server->key_acts[minKC], 0,
60835c4bbdfSmrg                       tmp * sizeof(unsigned short));
60935c4bbdfSmrg                if (changes) {
61035c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
61135c4bbdfSmrg                                                        XkbKeyActionsMask,
61235c4bbdfSmrg                                                        minKC,
61335c4bbdfSmrg                                                        &changes->map.
61435c4bbdfSmrg                                                        first_key_act,
61535c4bbdfSmrg                                                        &changes->map.
61635c4bbdfSmrg                                                        num_key_acts);
61735c4bbdfSmrg                }
61835c4bbdfSmrg            }
61935c4bbdfSmrg            if (xkb->server->vmodmap) {
62035c4bbdfSmrg                memset((char *) &xkb->server->vmodmap[minKC], 0,
62135c4bbdfSmrg                       tmp * sizeof(unsigned short));
62235c4bbdfSmrg                if (changes) {
62335c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
62435c4bbdfSmrg                                                        XkbVirtualModMapMask,
62535c4bbdfSmrg                                                        minKC,
62635c4bbdfSmrg                                                        &changes->map.
62735c4bbdfSmrg                                                        first_modmap_key,
62835c4bbdfSmrg                                                        &changes->map.
62935c4bbdfSmrg                                                        num_vmodmap_keys);
63035c4bbdfSmrg                }
63135c4bbdfSmrg            }
63235c4bbdfSmrg        }
63335c4bbdfSmrg        if ((xkb->names) && (xkb->names->keys)) {
63435c4bbdfSmrg            memset((char *) &xkb->names->keys[minKC], 0,
63535c4bbdfSmrg                   tmp * sizeof(XkbKeyNameRec));
63635c4bbdfSmrg            if (changes) {
63735c4bbdfSmrg                changes->names.changed = _ExtendRange(changes->names.changed,
63835c4bbdfSmrg                                                      XkbKeyNamesMask, minKC,
63935c4bbdfSmrg                                                      &changes->names.first_key,
64035c4bbdfSmrg                                                      &changes->names.num_keys);
64135c4bbdfSmrg            }
64235c4bbdfSmrg        }
64335c4bbdfSmrg        xkb->min_key_code = minKC;
64435c4bbdfSmrg    }
64535c4bbdfSmrg    if (maxKC > xkb->max_key_code) {
64635c4bbdfSmrg        if (changes)
64735c4bbdfSmrg            changes->map.max_key_code = maxKC;
648f2346221Smrg        tmp = MAP_LENGTH - xkb->max_key_code;
64935c4bbdfSmrg        if (xkb->map) {
65035c4bbdfSmrg            if (xkb->map->key_sym_map) {
65135c4bbdfSmrg                memset((char *) &xkb->map->key_sym_map[xkb->max_key_code], 0,
65235c4bbdfSmrg                       tmp * sizeof(XkbSymMapRec));
65335c4bbdfSmrg                if (changes) {
65435c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
65535c4bbdfSmrg                                                        XkbKeySymsMask, maxKC,
65635c4bbdfSmrg                                                        &changes->map.
65735c4bbdfSmrg                                                        first_key_sym,
65835c4bbdfSmrg                                                        &changes->map.
65935c4bbdfSmrg                                                        num_key_syms);
66035c4bbdfSmrg                }
66135c4bbdfSmrg            }
66235c4bbdfSmrg            if (xkb->map->modmap) {
66335c4bbdfSmrg                memset((char *) &xkb->map->modmap[xkb->max_key_code], 0, tmp);
66435c4bbdfSmrg                if (changes) {
66535c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
66635c4bbdfSmrg                                                        XkbModifierMapMask,
66735c4bbdfSmrg                                                        maxKC,
66835c4bbdfSmrg                                                        &changes->map.
66935c4bbdfSmrg                                                        first_modmap_key,
67035c4bbdfSmrg                                                        &changes->map.
67135c4bbdfSmrg                                                        num_modmap_keys);
67235c4bbdfSmrg                }
67335c4bbdfSmrg            }
67435c4bbdfSmrg        }
67535c4bbdfSmrg        if (xkb->server) {
67635c4bbdfSmrg            if (xkb->server->behaviors) {
67735c4bbdfSmrg                memset((char *) &xkb->server->behaviors[xkb->max_key_code], 0,
67835c4bbdfSmrg                       tmp * sizeof(XkbBehavior));
67935c4bbdfSmrg                if (changes) {
68035c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
68135c4bbdfSmrg                                                        XkbKeyBehaviorsMask,
68235c4bbdfSmrg                                                        maxKC,
68335c4bbdfSmrg                                                        &changes->map.
68435c4bbdfSmrg                                                        first_key_behavior,
68535c4bbdfSmrg                                                        &changes->map.
68635c4bbdfSmrg                                                        num_key_behaviors);
68735c4bbdfSmrg                }
68835c4bbdfSmrg            }
68935c4bbdfSmrg            if (xkb->server->key_acts) {
69035c4bbdfSmrg                memset((char *) &xkb->server->key_acts[xkb->max_key_code], 0,
69135c4bbdfSmrg                       tmp * sizeof(unsigned short));
69235c4bbdfSmrg                if (changes) {
69335c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
69435c4bbdfSmrg                                                        XkbKeyActionsMask,
69535c4bbdfSmrg                                                        maxKC,
69635c4bbdfSmrg                                                        &changes->map.
69735c4bbdfSmrg                                                        first_key_act,
69835c4bbdfSmrg                                                        &changes->map.
69935c4bbdfSmrg                                                        num_key_acts);
70035c4bbdfSmrg                }
70135c4bbdfSmrg            }
70235c4bbdfSmrg            if (xkb->server->vmodmap) {
70335c4bbdfSmrg                memset((char *) &xkb->server->vmodmap[xkb->max_key_code], 0,
70435c4bbdfSmrg                       tmp * sizeof(unsigned short));
70535c4bbdfSmrg                if (changes) {
70635c4bbdfSmrg                    changes->map.changed = _ExtendRange(changes->map.changed,
70735c4bbdfSmrg                                                        XkbVirtualModMapMask,
70835c4bbdfSmrg                                                        maxKC,
70935c4bbdfSmrg                                                        &changes->map.
71035c4bbdfSmrg                                                        first_modmap_key,
71135c4bbdfSmrg                                                        &changes->map.
71235c4bbdfSmrg                                                        num_vmodmap_keys);
71335c4bbdfSmrg                }
71435c4bbdfSmrg            }
71535c4bbdfSmrg        }
71635c4bbdfSmrg        if ((xkb->names) && (xkb->names->keys)) {
71735c4bbdfSmrg            memset((char *) &xkb->names->keys[xkb->max_key_code], 0,
71835c4bbdfSmrg                   tmp * sizeof(XkbKeyNameRec));
71935c4bbdfSmrg            if (changes) {
72035c4bbdfSmrg                changes->names.changed = _ExtendRange(changes->names.changed,
72135c4bbdfSmrg                                                      XkbKeyNamesMask, maxKC,
72235c4bbdfSmrg                                                      &changes->names.first_key,
72335c4bbdfSmrg                                                      &changes->names.num_keys);
72435c4bbdfSmrg            }
72535c4bbdfSmrg        }
72635c4bbdfSmrg        xkb->max_key_code = maxKC;
72705b261ecSmrg    }
72805b261ecSmrg    return Success;
72905b261ecSmrg}
73005b261ecSmrg
73105b261ecSmrgXkbAction *
73235c4bbdfSmrgXkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
73305b261ecSmrg{
73435c4bbdfSmrg    register int i, nActs;
73535c4bbdfSmrg    XkbAction *newActs;
73635c4bbdfSmrg
73754b5899cSmrg    if (needed <= 0) {
73835c4bbdfSmrg        xkb->server->key_acts[key] = 0;
73935c4bbdfSmrg        return NULL;
74035c4bbdfSmrg    }
74135c4bbdfSmrg    if (XkbKeyHasActions(xkb, key) &&
74235c4bbdfSmrg        (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
74335c4bbdfSmrg        return XkbKeyActionsPtr(xkb, key);
74435c4bbdfSmrg    if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
74535c4bbdfSmrg        xkb->server->key_acts[key] = xkb->server->num_acts;
74635c4bbdfSmrg        xkb->server->num_acts += needed;
74735c4bbdfSmrg        return &xkb->server->acts[xkb->server->key_acts[key]];
74835c4bbdfSmrg    }
74935c4bbdfSmrg    xkb->server->size_acts = xkb->server->num_acts + needed + 8;
7506747b715Smrg    newActs = calloc(xkb->server->size_acts, sizeof(XkbAction));
75135c4bbdfSmrg    if (newActs == NULL)
75235c4bbdfSmrg        return NULL;
75305b261ecSmrg    newActs[0].type = XkbSA_NoAction;
75405b261ecSmrg    nActs = 1;
75535c4bbdfSmrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
75635c4bbdfSmrg        int nKeyActs, nCopy;
75735c4bbdfSmrg
75835c4bbdfSmrg        if ((xkb->server->key_acts[i] == 0) && (i != key))
75935c4bbdfSmrg            continue;
76035c4bbdfSmrg
76135c4bbdfSmrg        nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
76235c4bbdfSmrg        if (i == key) {
76335c4bbdfSmrg            nKeyActs = needed;
76435c4bbdfSmrg            if (needed < nCopy)
76535c4bbdfSmrg                nCopy = needed;
76635c4bbdfSmrg        }
76735c4bbdfSmrg
76835c4bbdfSmrg        if (nCopy > 0)
76935c4bbdfSmrg            memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
77035c4bbdfSmrg                   nCopy * sizeof(XkbAction));
77135c4bbdfSmrg        if (nCopy < nKeyActs)
77235c4bbdfSmrg            memset(&newActs[nActs + nCopy], 0,
77335c4bbdfSmrg                   (nKeyActs - nCopy) * sizeof(XkbAction));
77435c4bbdfSmrg        xkb->server->key_acts[i] = nActs;
77535c4bbdfSmrg        nActs += nKeyActs;
77605b261ecSmrg    }
7776747b715Smrg    free(xkb->server->acts);
77805b261ecSmrg    xkb->server->acts = newActs;
77935c4bbdfSmrg    xkb->server->num_acts = nActs;
78005b261ecSmrg    return &xkb->server->acts[xkb->server->key_acts[key]];
78105b261ecSmrg}
78205b261ecSmrg
78305b261ecSmrgvoid
78435c4bbdfSmrgXkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
78505b261ecSmrg{
78635c4bbdfSmrg    XkbClientMapPtr map;
78705b261ecSmrg
78835c4bbdfSmrg    if ((xkb == NULL) || (xkb->map == NULL))
78935c4bbdfSmrg        return;
79005b261ecSmrg    if (freeMap)
79135c4bbdfSmrg        what = XkbAllClientInfoMask;
79235c4bbdfSmrg    map = xkb->map;
79335c4bbdfSmrg    if (what & XkbKeyTypesMask) {
79435c4bbdfSmrg        if (map->types != NULL) {
79535c4bbdfSmrg            if (map->num_types > 0) {
79635c4bbdfSmrg                register int i;
79735c4bbdfSmrg                XkbKeyTypePtr type;
79835c4bbdfSmrg
79935c4bbdfSmrg                for (i = 0, type = map->types; i < map->num_types; i++, type++) {
80035c4bbdfSmrg                    free(type->map);
80135c4bbdfSmrg                    type->map = NULL;
80235c4bbdfSmrg                    free(type->preserve);
80335c4bbdfSmrg                    type->preserve = NULL;
80435c4bbdfSmrg                    type->map_count = 0;
80535c4bbdfSmrg                    free(type->level_names);
80635c4bbdfSmrg                    type->level_names = NULL;
80735c4bbdfSmrg                }
80835c4bbdfSmrg            }
80935c4bbdfSmrg            free(map->types);
81035c4bbdfSmrg            map->num_types = map->size_types = 0;
81135c4bbdfSmrg            map->types = NULL;
81235c4bbdfSmrg        }
81335c4bbdfSmrg    }
81435c4bbdfSmrg    if (what & XkbKeySymsMask) {
81535c4bbdfSmrg        free(map->key_sym_map);
81635c4bbdfSmrg        map->key_sym_map = NULL;
81735c4bbdfSmrg        if (map->syms != NULL) {
81835c4bbdfSmrg            free(map->syms);
81935c4bbdfSmrg            map->size_syms = map->num_syms = 0;
82035c4bbdfSmrg            map->syms = NULL;
82135c4bbdfSmrg        }
82235c4bbdfSmrg    }
82335c4bbdfSmrg    if ((what & XkbModifierMapMask) && (map->modmap != NULL)) {
82435c4bbdfSmrg        free(map->modmap);
82535c4bbdfSmrg        map->modmap = NULL;
82605b261ecSmrg    }
82705b261ecSmrg    if (freeMap) {
82835c4bbdfSmrg        free(xkb->map);
82935c4bbdfSmrg        xkb->map = NULL;
83005b261ecSmrg    }
83105b261ecSmrg    return;
83205b261ecSmrg}
83305b261ecSmrg
83405b261ecSmrgvoid
83535c4bbdfSmrgXkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
83605b261ecSmrg{
83735c4bbdfSmrg    XkbServerMapPtr map;
83805b261ecSmrg
83935c4bbdfSmrg    if ((xkb == NULL) || (xkb->server == NULL))
84035c4bbdfSmrg        return;
84105b261ecSmrg    if (freeMap)
84235c4bbdfSmrg        what = XkbAllServerInfoMask;
84335c4bbdfSmrg    map = xkb->server;
84435c4bbdfSmrg    if ((what & XkbExplicitComponentsMask) && (map->explicit != NULL)) {
84535c4bbdfSmrg        free(map->explicit);
84635c4bbdfSmrg        map->explicit = NULL;
84735c4bbdfSmrg    }
84835c4bbdfSmrg    if (what & XkbKeyActionsMask) {
84935c4bbdfSmrg        free(map->key_acts);
85035c4bbdfSmrg        map->key_acts = NULL;
85135c4bbdfSmrg        if (map->acts != NULL) {
85235c4bbdfSmrg            free(map->acts);
85335c4bbdfSmrg            map->num_acts = map->size_acts = 0;
85435c4bbdfSmrg            map->acts = NULL;
85535c4bbdfSmrg        }
85635c4bbdfSmrg    }
85735c4bbdfSmrg    if ((what & XkbKeyBehaviorsMask) && (map->behaviors != NULL)) {
85835c4bbdfSmrg        free(map->behaviors);
85935c4bbdfSmrg        map->behaviors = NULL;
86035c4bbdfSmrg    }
86135c4bbdfSmrg    if ((what & XkbVirtualModMapMask) && (map->vmodmap != NULL)) {
86235c4bbdfSmrg        free(map->vmodmap);
86335c4bbdfSmrg        map->vmodmap = NULL;
86405b261ecSmrg    }
86505b261ecSmrg
86605b261ecSmrg    if (freeMap) {
86735c4bbdfSmrg        free(xkb->server);
86835c4bbdfSmrg        xkb->server = NULL;
86905b261ecSmrg    }
87005b261ecSmrg    return;
87105b261ecSmrg}
872