XKBMAlloc.c revision 6747b715
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
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon 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
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA 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#elif defined(HAVE_CONFIG_H)
3005b261ecSmrg#include <config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <stdio.h>
3405b261ecSmrg#include <X11/X.h>
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg#include <X11/keysym.h>
3905b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg
4205b261ecSmrg/***====================================================================***/
4305b261ecSmrg
4405b261ecSmrgStatus
4505b261ecSmrgXkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)
4605b261ecSmrg{
4705b261ecSmrgregister int	i;
4805b261ecSmrgXkbClientMapPtr map;
4905b261ecSmrg
5005b261ecSmrg    if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
5105b261ecSmrg	return BadValue;
5205b261ecSmrg    if ((which&XkbKeySymsMask)&&
5305b261ecSmrg	((!XkbIsLegalKeycode(xkb->min_key_code))||
5405b261ecSmrg	 (!XkbIsLegalKeycode(xkb->max_key_code))||
5505b261ecSmrg	 (xkb->max_key_code<xkb->min_key_code))) {
564642e01fSmrg        DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n",
5705b261ecSmrg				xkb->min_key_code,xkb->max_key_code);
5805b261ecSmrg	return BadValue;
5905b261ecSmrg    }
6005b261ecSmrg
6105b261ecSmrg    if (xkb->map==NULL) {
626747b715Smrg	map= calloc(1, sizeof(XkbClientMapRec));
6305b261ecSmrg	if (map==NULL)
6405b261ecSmrg	    return BadAlloc;
6505b261ecSmrg	xkb->map= map;
6605b261ecSmrg    }
6705b261ecSmrg    else map= xkb->map;
6805b261ecSmrg
6905b261ecSmrg    if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
7005b261ecSmrg	if (map->types==NULL) {
716747b715Smrg	    map->types= calloc(nTotalTypes, sizeof(XkbKeyTypeRec));
7205b261ecSmrg	    if (map->types==NULL)
7305b261ecSmrg		return BadAlloc;
7405b261ecSmrg	    map->num_types= 0;
7505b261ecSmrg	    map->size_types= nTotalTypes;
7605b261ecSmrg	}
7705b261ecSmrg	else if (map->size_types<nTotalTypes) {
7805b261ecSmrg	    XkbKeyTypeRec *prev_types = map->types;
7905b261ecSmrg
806747b715Smrg	    map->types= realloc(map->types,nTotalTypes * sizeof(XkbKeyTypeRec));
8105b261ecSmrg	    if (map->types==NULL) {
826747b715Smrg		free(prev_types);
8305b261ecSmrg		map->num_types= map->size_types= 0;
8405b261ecSmrg		return BadAlloc;
8505b261ecSmrg	    }
8605b261ecSmrg	    map->size_types= nTotalTypes;
876747b715Smrg	    memset(&map->types[map->num_types], 0,
8805b261ecSmrg		  ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
8905b261ecSmrg	}
9005b261ecSmrg    }
9105b261ecSmrg    if (which&XkbKeySymsMask) {
9205b261ecSmrg	int nKeys= XkbNumKeys(xkb);
9305b261ecSmrg	if (map->syms==NULL) {
9405b261ecSmrg	    map->size_syms= (nKeys*15)/10;
956747b715Smrg	    map->syms= calloc(map->size_syms, sizeof(KeySym));
9605b261ecSmrg	    if (!map->syms) {
9705b261ecSmrg		map->size_syms= 0;
9805b261ecSmrg		return BadAlloc;
9905b261ecSmrg	    }
10005b261ecSmrg	    map->num_syms= 1;
10105b261ecSmrg	    map->syms[0]= NoSymbol;
10205b261ecSmrg	}
10305b261ecSmrg	if (map->key_sym_map==NULL) {
10405b261ecSmrg	    i= xkb->max_key_code+1;
1056747b715Smrg	    map->key_sym_map= calloc(i, sizeof(XkbSymMapRec));
10605b261ecSmrg	    if (map->key_sym_map==NULL)
10705b261ecSmrg		return BadAlloc;
10805b261ecSmrg	}
10905b261ecSmrg    }
11005b261ecSmrg    if (which&XkbModifierMapMask) {
11105b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
11205b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
11305b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
11405b261ecSmrg	    return BadMatch;
11505b261ecSmrg	if (map->modmap==NULL) {
11605b261ecSmrg	    i= xkb->max_key_code+1;
1176747b715Smrg	    map->modmap= calloc(i, sizeof(unsigned char));
11805b261ecSmrg	    if (map->modmap==NULL)
11905b261ecSmrg		return BadAlloc;
12005b261ecSmrg	}
12105b261ecSmrg    }
12205b261ecSmrg    return Success;
12305b261ecSmrg}
12405b261ecSmrg
12505b261ecSmrgStatus
12605b261ecSmrgXkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)
12705b261ecSmrg{
12805b261ecSmrgregister int	i;
12905b261ecSmrgXkbServerMapPtr map;
13005b261ecSmrg
13105b261ecSmrg    if (xkb==NULL)
13205b261ecSmrg	return BadMatch;
13305b261ecSmrg    if (xkb->server==NULL) {
1346747b715Smrg	map= calloc(1, sizeof(XkbServerMapRec));
13505b261ecSmrg	if (map==NULL)
13605b261ecSmrg	    return BadAlloc;
13705b261ecSmrg	for (i=0;i<XkbNumVirtualMods;i++) {
13805b261ecSmrg	    map->vmods[i]= XkbNoModifierMask;
13905b261ecSmrg	}
14005b261ecSmrg	xkb->server= map;
14105b261ecSmrg    }
14205b261ecSmrg    else map= xkb->server;
14305b261ecSmrg    if (which&XkbExplicitComponentsMask) {
14405b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
14505b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
14605b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
14705b261ecSmrg	    return BadMatch;
14805b261ecSmrg	if (map->explicit==NULL) {
14905b261ecSmrg	    i= xkb->max_key_code+1;
1506747b715Smrg	    map->explicit= calloc(i, sizeof(unsigned char));
15105b261ecSmrg	    if (map->explicit==NULL)
15205b261ecSmrg		return BadAlloc;
15305b261ecSmrg	}
15405b261ecSmrg    }
15505b261ecSmrg    if (which&XkbKeyActionsMask) {
15605b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
15705b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
15805b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
15905b261ecSmrg	    return BadMatch;
16005b261ecSmrg        if (nNewActions<1)
16105b261ecSmrg	    nNewActions= 1;
16205b261ecSmrg	if (map->acts==NULL) {
1636747b715Smrg	    map->acts= calloc((nNewActions+1), sizeof(XkbAction));
16405b261ecSmrg	    if (map->acts==NULL)
16505b261ecSmrg		return BadAlloc;
16605b261ecSmrg	    map->num_acts= 1;
16705b261ecSmrg	    map->size_acts= nNewActions+1;
16805b261ecSmrg	}
16905b261ecSmrg	else if ((map->size_acts-map->num_acts)<nNewActions) {
17005b261ecSmrg	    unsigned need;
17105b261ecSmrg	    XkbAction *prev_acts = map->acts;
17205b261ecSmrg	    need= map->num_acts+nNewActions;
1736747b715Smrg	    map->acts= realloc(map->acts,need * sizeof(XkbAction));
17405b261ecSmrg	    if (map->acts==NULL) {
1756747b715Smrg		free(prev_acts);
17605b261ecSmrg	        map->num_acts= map->size_acts= 0;
17705b261ecSmrg	        return BadAlloc;
17805b261ecSmrg	    }
17905b261ecSmrg	    map->size_acts= need;
1806747b715Smrg	    memset(&map->acts[map->num_acts], 0,
18105b261ecSmrg		    ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
18205b261ecSmrg	}
18305b261ecSmrg	if (map->key_acts==NULL) {
18405b261ecSmrg	    i= xkb->max_key_code+1;
1856747b715Smrg	    map->key_acts= calloc(i, sizeof(unsigned short));
18605b261ecSmrg	    if (map->key_acts==NULL)
18705b261ecSmrg		return BadAlloc;
18805b261ecSmrg	}
18905b261ecSmrg    }
19005b261ecSmrg    if (which&XkbKeyBehaviorsMask) {
19105b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
19205b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
19305b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
19405b261ecSmrg	    return BadMatch;
19505b261ecSmrg	if (map->behaviors==NULL) {
19605b261ecSmrg	    i= xkb->max_key_code+1;
1976747b715Smrg	    map->behaviors= calloc(i, sizeof(XkbBehavior));
19805b261ecSmrg	    if (map->behaviors==NULL)
19905b261ecSmrg		return BadAlloc;
20005b261ecSmrg	}
20105b261ecSmrg    }
20205b261ecSmrg    if (which&XkbVirtualModMapMask) {
20305b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
20405b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
20505b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
20605b261ecSmrg	    return BadMatch;
20705b261ecSmrg	if (map->vmodmap==NULL) {
20805b261ecSmrg	    i= xkb->max_key_code+1;
2096747b715Smrg	    map->vmodmap= calloc(i, sizeof(unsigned short));
21005b261ecSmrg	    if (map->vmodmap==NULL)
21105b261ecSmrg		return BadAlloc;
21205b261ecSmrg	}
21305b261ecSmrg    }
21405b261ecSmrg    return Success;
21505b261ecSmrg}
21605b261ecSmrg
21705b261ecSmrg/***====================================================================***/
21805b261ecSmrg
21905b261ecSmrgstatic Status
22005b261ecSmrgXkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)
22105b261ecSmrg{
22205b261ecSmrg    if ((!from)||(!into))
22305b261ecSmrg	return BadMatch;
2246747b715Smrg    free(into->map);
2256747b715Smrg    into->map = NULL;
2266747b715Smrg    free(into->preserve);
2276747b715Smrg    into->preserve = NULL;
2286747b715Smrg    free(into->level_names);
2296747b715Smrg    into->level_names = NULL;
23005b261ecSmrg    *into= *from;
23105b261ecSmrg    if ((from->map)&&(into->map_count>0)) {
2326747b715Smrg	into->map= calloc(into->map_count, sizeof(XkbKTMapEntryRec));
23305b261ecSmrg	if (!into->map)
23405b261ecSmrg	    return BadAlloc;
23505b261ecSmrg	memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec));
23605b261ecSmrg    }
23705b261ecSmrg    if ((from->preserve)&&(into->map_count>0)) {
2386747b715Smrg	into->preserve= calloc(into->map_count, sizeof(XkbModsRec));
23905b261ecSmrg	if (!into->preserve)
24005b261ecSmrg	    return BadAlloc;
24105b261ecSmrg	memcpy(into->preserve,from->preserve,
24205b261ecSmrg				into->map_count*sizeof(XkbModsRec));
24305b261ecSmrg    }
24405b261ecSmrg    if ((from->level_names)&&(into->num_levels>0)) {
2456747b715Smrg	into->level_names= calloc(into->num_levels, sizeof(Atom));
24605b261ecSmrg	if (!into->level_names)
24705b261ecSmrg	    return BadAlloc;
24805b261ecSmrg	memcpy(into->level_names,from->level_names,
24905b261ecSmrg				 into->num_levels*sizeof(Atom));
25005b261ecSmrg    }
25105b261ecSmrg    return Success;
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrgStatus
25505b261ecSmrgXkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)
25605b261ecSmrg{
25705b261ecSmrgregister int i,rtrn;
25805b261ecSmrg
25905b261ecSmrg    if ((!from)||(!into)||(num_types<0))
26005b261ecSmrg	return BadMatch;
26105b261ecSmrg    for (i=0;i<num_types;i++) {
26205b261ecSmrg	if ((rtrn= XkbCopyKeyType(from++,into++))!=Success)
26305b261ecSmrg	    return rtrn;
26405b261ecSmrg    }
26505b261ecSmrg    return Success;
26605b261ecSmrg}
26705b261ecSmrg
26805b261ecSmrgStatus
26905b261ecSmrgXkbResizeKeyType(	XkbDescPtr	xkb,
27005b261ecSmrg			int		type_ndx,
27105b261ecSmrg			int		map_count,
27205b261ecSmrg			Bool		want_preserve,
27305b261ecSmrg			int		new_num_lvls)
27405b261ecSmrg{
27505b261ecSmrgXkbKeyTypePtr	type;
27605b261ecSmrgKeyCode		matchingKeys[XkbMaxKeyCount],nMatchingKeys;
27705b261ecSmrg
27805b261ecSmrg    if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)||
27905b261ecSmrg    							(new_num_lvls<1))
28005b261ecSmrg	return BadValue;
28105b261ecSmrg    switch (type_ndx) {
28205b261ecSmrg	case XkbOneLevelIndex:
28305b261ecSmrg	    if (new_num_lvls!=1)
28405b261ecSmrg		return BadMatch;
28505b261ecSmrg	    break;
28605b261ecSmrg	case XkbTwoLevelIndex:
28705b261ecSmrg	case XkbAlphabeticIndex:
28805b261ecSmrg	case XkbKeypadIndex:
28905b261ecSmrg	    if (new_num_lvls!=2)
29005b261ecSmrg		return BadMatch;
29105b261ecSmrg	    break;
29205b261ecSmrg    }
29305b261ecSmrg    type= &xkb->map->types[type_ndx];
29405b261ecSmrg    if (map_count==0) {
29505b261ecSmrg	if (type->map!=NULL)
2966747b715Smrg	    free(type->map);
29705b261ecSmrg	type->map= NULL;
29805b261ecSmrg	if (type->preserve!=NULL)
2996747b715Smrg	    free(type->preserve);
30005b261ecSmrg	type->preserve= NULL;
30105b261ecSmrg	type->map_count= 0;
30205b261ecSmrg    }
30305b261ecSmrg    else {
30405b261ecSmrg	XkbKTMapEntryRec *prev_map = type->map;
30505b261ecSmrg
30605b261ecSmrg	if ((map_count>type->map_count)||(type->map==NULL))
3076747b715Smrg	    type->map = realloc(type->map,map_count * sizeof(XkbKTMapEntryRec));
30805b261ecSmrg	if (!type->map) {
3096747b715Smrg	    free(prev_map);
31005b261ecSmrg	    return BadAlloc;
31105b261ecSmrg	}
31205b261ecSmrg	if (want_preserve) {
31305b261ecSmrg	    XkbModsRec *prev_preserve = type->preserve;
31405b261ecSmrg
31505b261ecSmrg	    if ((map_count>type->map_count)||(type->preserve==NULL)) {
3166747b715Smrg		type->preserve = realloc(type->preserve,
3176747b715Smrg					  map_count * sizeof(XkbModsRec));
31805b261ecSmrg	    }
31905b261ecSmrg	    if (!type->preserve) {
3206747b715Smrg		free(prev_preserve);
32105b261ecSmrg		return BadAlloc;
32205b261ecSmrg	    }
32305b261ecSmrg	}
32405b261ecSmrg	else if (type->preserve!=NULL) {
3256747b715Smrg	    free(type->preserve);
32605b261ecSmrg	    type->preserve= NULL;
32705b261ecSmrg	}
32805b261ecSmrg	type->map_count= map_count;
32905b261ecSmrg    }
33005b261ecSmrg
33105b261ecSmrg    if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) {
33205b261ecSmrg	Atom * prev_level_names = type->level_names;
33305b261ecSmrg
3346747b715Smrg	type->level_names = realloc(type->level_names,
3356747b715Smrg				     new_num_lvls * sizeof(Atom));
33605b261ecSmrg	if (!type->level_names) {
3376747b715Smrg	    free(prev_level_names);
33805b261ecSmrg	    return BadAlloc;
33905b261ecSmrg	}
34005b261ecSmrg    }
34105b261ecSmrg    /*
34205b261ecSmrg     * Here's the theory:
34305b261ecSmrg     *    If the width of the type changed, we might have to resize the symbol
34405b261ecSmrg     * maps for any keys that use the type for one or more groups.  This is
34505b261ecSmrg     * expensive, so we'll try to cull out any keys that are obviously okay:
34605b261ecSmrg     * In any case:
34705b261ecSmrg     *    - keys that have a group width <= the old width are okay (because
34805b261ecSmrg     *      they could not possibly have been associated with the old type)
34905b261ecSmrg     * If the key type increased in size:
35005b261ecSmrg     *    - keys that already have a group width >= to the new width are okay
35105b261ecSmrg     *    + keys that have a group width >= the old width but < the new width
35205b261ecSmrg     *      might have to be enlarged.
35305b261ecSmrg     * If the key type decreased in size:
35405b261ecSmrg     *    - keys that have a group width > the old width don't have to be
35505b261ecSmrg     *      resized (because they must have some other wider type associated
35605b261ecSmrg     *      with some group).
35705b261ecSmrg     *    + keys that have a group width == the old width might have to be
35805b261ecSmrg     *      shrunk.
35905b261ecSmrg     * The possibilities marked with '+' require us to examine the key types
36005b261ecSmrg     * associated with each group for the key.
36105b261ecSmrg     */
3626747b715Smrg    memset(matchingKeys, 0, XkbMaxKeyCount*sizeof(KeyCode));
36305b261ecSmrg    nMatchingKeys= 0;
36405b261ecSmrg    if (new_num_lvls>type->num_levels) {
36505b261ecSmrg	int	 		nTotal;
36605b261ecSmrg	KeySym	*		newSyms;
36705b261ecSmrg	int			width,match,nResize;
36805b261ecSmrg	register int		i,g,nSyms;
36905b261ecSmrg
37005b261ecSmrg	nResize= 0;
37105b261ecSmrg	for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
37205b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,i);
37305b261ecSmrg	    if (width<type->num_levels)
37405b261ecSmrg		continue;
37505b261ecSmrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
37605b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
37705b261ecSmrg		    matchingKeys[nMatchingKeys++]= i;
37805b261ecSmrg		    match= 1;
37905b261ecSmrg		}
38005b261ecSmrg	    }
38105b261ecSmrg	    if ((!match)||(width>=new_num_lvls))
38205b261ecSmrg		nTotal+= XkbKeyNumSyms(xkb,i);
38305b261ecSmrg	    else {
38405b261ecSmrg		nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
38505b261ecSmrg		nResize++;
38605b261ecSmrg	    }
38705b261ecSmrg	}
38805b261ecSmrg	if (nResize>0) {
38905b261ecSmrg	    int nextMatch;
39005b261ecSmrg	    xkb->map->size_syms= (nTotal*15)/10;
3916747b715Smrg	    newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
39205b261ecSmrg	    if (newSyms==NULL)
39305b261ecSmrg		return BadAlloc;
39405b261ecSmrg	    nextMatch= 0;
39505b261ecSmrg	    nSyms= 1;
39605b261ecSmrg	    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
39705b261ecSmrg		if (matchingKeys[nextMatch]==i) {
39805b261ecSmrg		    KeySym *pOld;
39905b261ecSmrg		    nextMatch++;
40005b261ecSmrg		    width= XkbKeyGroupsWidth(xkb,i);
40105b261ecSmrg		    pOld= XkbKeySymsPtr(xkb,i);
40205b261ecSmrg		    for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
40305b261ecSmrg			memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g],
40405b261ecSmrg							width*sizeof(KeySym));
40505b261ecSmrg		    }
40605b261ecSmrg		    xkb->map->key_sym_map[i].offset= nSyms;
40705b261ecSmrg		    nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
40805b261ecSmrg		}
40905b261ecSmrg		else {
41005b261ecSmrg		    memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),
41105b261ecSmrg					XkbKeyNumSyms(xkb,i)*sizeof(KeySym));
41205b261ecSmrg		    xkb->map->key_sym_map[i].offset= nSyms;
41305b261ecSmrg		    nSyms+= XkbKeyNumSyms(xkb,i);
41405b261ecSmrg		}
41505b261ecSmrg	    }
41605b261ecSmrg	    type->num_levels= new_num_lvls;
4176747b715Smrg	    free(xkb->map->syms);
41805b261ecSmrg	    xkb->map->syms= newSyms;
41905b261ecSmrg	    xkb->map->num_syms= nSyms;
42005b261ecSmrg	    return Success;
42105b261ecSmrg	}
42205b261ecSmrg    }
42305b261ecSmrg    else if (new_num_lvls<type->num_levels) {
42405b261ecSmrg	int 		width,match;
42505b261ecSmrg	register int	g,i;
42605b261ecSmrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
42705b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,i);
42805b261ecSmrg	    if (width<type->num_levels)
42905b261ecSmrg		continue;
43005b261ecSmrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
43105b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
43205b261ecSmrg		    matchingKeys[nMatchingKeys++]= i;
43305b261ecSmrg		    match= 1;
43405b261ecSmrg		}
43505b261ecSmrg	    }
43605b261ecSmrg	}
43705b261ecSmrg    }
43805b261ecSmrg    if (nMatchingKeys>0) {
43905b261ecSmrg	int 		key,firstClear;
44005b261ecSmrg	register int	i,g;
44105b261ecSmrg	if (new_num_lvls>type->num_levels)
44205b261ecSmrg	     firstClear= type->num_levels;
44305b261ecSmrg	else firstClear= new_num_lvls;
44405b261ecSmrg	for (i=0;i<nMatchingKeys;i++) {
44505b261ecSmrg	    KeySym *	pSyms;
44605b261ecSmrg	    int		width,nClear;
44705b261ecSmrg
44805b261ecSmrg	    key= matchingKeys[i];
44905b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,key);
45005b261ecSmrg	    nClear= width-firstClear;
45105b261ecSmrg	    pSyms= XkbKeySymsPtr(xkb,key);
45205b261ecSmrg	    for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) {
45305b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) {
45405b261ecSmrg		    if (nClear>0)
4556747b715Smrg			memset(&pSyms[g*width+firstClear], 0, nClear*sizeof(KeySym));
45605b261ecSmrg		}
45705b261ecSmrg	    }
45805b261ecSmrg	}
45905b261ecSmrg    }
46005b261ecSmrg    type->num_levels= new_num_lvls;
46105b261ecSmrg    return Success;
46205b261ecSmrg}
46305b261ecSmrg
46405b261ecSmrgKeySym *
46505b261ecSmrgXkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)
46605b261ecSmrg{
46705b261ecSmrgregister int i,nSyms,nKeySyms;
46805b261ecSmrgunsigned nOldSyms;
46905b261ecSmrgKeySym	*newSyms;
47005b261ecSmrg
47105b261ecSmrg    if (needed==0) {
47205b261ecSmrg	xkb->map->key_sym_map[key].offset= 0;
47305b261ecSmrg	return xkb->map->syms;
47405b261ecSmrg    }
47505b261ecSmrg    nOldSyms= XkbKeyNumSyms(xkb,key);
47605b261ecSmrg    if (nOldSyms>=(unsigned)needed) {
47705b261ecSmrg	return XkbKeySymsPtr(xkb,key);
47805b261ecSmrg    }
47905b261ecSmrg    if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) {
48005b261ecSmrg	if (nOldSyms>0) {
48105b261ecSmrg	    memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key),
48205b261ecSmrg						nOldSyms*sizeof(KeySym));
48305b261ecSmrg	}
48405b261ecSmrg	if ((needed-nOldSyms)>0) {
4856747b715Smrg	    memset(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb, key)],
4866747b715Smrg                   0, (needed-nOldSyms)*sizeof(KeySym));
48705b261ecSmrg	}
48805b261ecSmrg	xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
48905b261ecSmrg	xkb->map->num_syms+= needed;
49005b261ecSmrg	return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
49105b261ecSmrg    }
49205b261ecSmrg    xkb->map->size_syms+= (needed>32?needed:32);
4936747b715Smrg    newSyms = calloc(xkb->map->size_syms, sizeof(KeySym));
49405b261ecSmrg    if (newSyms==NULL)
49505b261ecSmrg	return NULL;
49605b261ecSmrg    newSyms[0]= NoSymbol;
49705b261ecSmrg    nSyms = 1;
49805b261ecSmrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
49905b261ecSmrg	int nCopy;
50005b261ecSmrg
50105b261ecSmrg	nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
50205b261ecSmrg	if ((nKeySyms==0)&&(i!=key))
50305b261ecSmrg	    continue;
50405b261ecSmrg	if (i==key)
50505b261ecSmrg	    nKeySyms= needed;
50605b261ecSmrg	if (nCopy!=0)
50705b261ecSmrg	   memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym));
50805b261ecSmrg	if (nKeySyms>nCopy)
5096747b715Smrg	    memset(&newSyms[nSyms+nCopy], 0, (nKeySyms-nCopy)*sizeof(KeySym));
51005b261ecSmrg	xkb->map->key_sym_map[i].offset = nSyms;
51105b261ecSmrg	nSyms+= nKeySyms;
51205b261ecSmrg    }
5136747b715Smrg    free(xkb->map->syms);
51405b261ecSmrg    xkb->map->syms = newSyms;
51505b261ecSmrg    xkb->map->num_syms = nSyms;
51605b261ecSmrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
51705b261ecSmrg}
51805b261ecSmrg
51905b261ecSmrgstatic unsigned
52005b261ecSmrg_ExtendRange(	unsigned int 	old_flags,
52105b261ecSmrg		unsigned int	flag,
52205b261ecSmrg		KeyCode		newKC,
52305b261ecSmrg		KeyCode *	old_min,
52405b261ecSmrg		unsigned char *	old_num)
52505b261ecSmrg{
52605b261ecSmrg    if ((old_flags&flag)==0) {
52705b261ecSmrg	old_flags|= flag;
52805b261ecSmrg	*old_min= newKC;
52905b261ecSmrg	*old_num= 1;
53005b261ecSmrg    }
53105b261ecSmrg    else {
53205b261ecSmrg	int	last= (*old_min)+(*old_num)-1;
53305b261ecSmrg	if (newKC<*old_min) {
53405b261ecSmrg	    *old_min= newKC;
53505b261ecSmrg	    *old_num= (last-newKC)+1;
53605b261ecSmrg	}
53705b261ecSmrg	else if (newKC>last) {
53805b261ecSmrg	    *old_num= (newKC-(*old_min))+1;
53905b261ecSmrg	}
54005b261ecSmrg    }
54105b261ecSmrg    return old_flags;
54205b261ecSmrg}
54305b261ecSmrg
54405b261ecSmrgStatus
54505b261ecSmrgXkbChangeKeycodeRange(	XkbDescPtr	xkb,
54605b261ecSmrg			int 		minKC,
54705b261ecSmrg			int 		maxKC,
54805b261ecSmrg			XkbChangesPtr	changes)
54905b261ecSmrg{
55005b261ecSmrgint	tmp;
55105b261ecSmrg
55205b261ecSmrg    if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode))
55305b261ecSmrg	return BadValue;
55405b261ecSmrg    if (minKC>maxKC)
55505b261ecSmrg	return BadMatch;
55605b261ecSmrg    if (minKC<xkb->min_key_code) {
55705b261ecSmrg	if (changes)
55805b261ecSmrg	    changes->map.min_key_code= minKC;
55905b261ecSmrg	tmp= xkb->min_key_code-minKC;
56005b261ecSmrg	if (xkb->map)  {
56105b261ecSmrg	    if (xkb->map->key_sym_map) {
5626747b715Smrg		memset((char *)&xkb->map->key_sym_map[minKC], 0,
56305b261ecSmrg					tmp*sizeof(XkbSymMapRec));
56405b261ecSmrg		if (changes) {
56505b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
56605b261ecSmrg		    				XkbKeySymsMask,minKC,
56705b261ecSmrg	    					&changes->map.first_key_sym,
56805b261ecSmrg	    					&changes->map.num_key_syms);
56905b261ecSmrg		}
57005b261ecSmrg	    }
57105b261ecSmrg	    if (xkb->map->modmap) {
5726747b715Smrg		memset((char *)&xkb->map->modmap[minKC], 0, tmp);
57305b261ecSmrg		if (changes) {
57405b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
57505b261ecSmrg		    				XkbModifierMapMask,minKC,
57605b261ecSmrg	    					&changes->map.first_modmap_key,
57705b261ecSmrg	    					&changes->map.num_modmap_keys);
57805b261ecSmrg		}
57905b261ecSmrg	    }
58005b261ecSmrg	}
58105b261ecSmrg	if (xkb->server) {
58205b261ecSmrg	    if (xkb->server->behaviors) {
5836747b715Smrg		memset((char *)&xkb->server->behaviors[minKC], 0,
58405b261ecSmrg						tmp*sizeof(XkbBehavior));
58505b261ecSmrg		if (changes) {
58605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
58705b261ecSmrg		    			XkbKeyBehaviorsMask,minKC,
58805b261ecSmrg    					&changes->map.first_key_behavior,
58905b261ecSmrg    					&changes->map.num_key_behaviors);
59005b261ecSmrg		}
59105b261ecSmrg	    }
59205b261ecSmrg	    if (xkb->server->key_acts) {
5936747b715Smrg		memset((char *)&xkb->server->key_acts[minKC], 0,
59405b261ecSmrg						tmp*sizeof(unsigned short));
59505b261ecSmrg		if (changes) {
59605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
59705b261ecSmrg		    			XkbKeyActionsMask,minKC,
59805b261ecSmrg    					&changes->map.first_key_act,
59905b261ecSmrg    					&changes->map.num_key_acts);
60005b261ecSmrg		}
60105b261ecSmrg	    }
60205b261ecSmrg	    if (xkb->server->vmodmap) {
6036747b715Smrg		memset((char *)&xkb->server->vmodmap[minKC], 0,
60405b261ecSmrg						tmp*sizeof(unsigned short));
60505b261ecSmrg		if (changes) {
60605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
60705b261ecSmrg		    			XkbVirtualModMapMask,minKC,
60805b261ecSmrg		    			&changes->map.first_modmap_key,
60905b261ecSmrg    					&changes->map.num_vmodmap_keys);
61005b261ecSmrg		}
61105b261ecSmrg	    }
61205b261ecSmrg	}
61305b261ecSmrg	if ((xkb->names)&&(xkb->names->keys)) {
6146747b715Smrg	    memset((char *)&xkb->names->keys[minKC], 0, tmp*sizeof(XkbKeyNameRec));
61505b261ecSmrg	    if (changes) {
61605b261ecSmrg		changes->names.changed= _ExtendRange(changes->names.changed,
61705b261ecSmrg					XkbKeyNamesMask,minKC,
61805b261ecSmrg					&changes->names.first_key,
61905b261ecSmrg    					&changes->names.num_keys);
62005b261ecSmrg	    }
62105b261ecSmrg	}
62205b261ecSmrg	xkb->min_key_code= minKC;
62305b261ecSmrg    }
62405b261ecSmrg    if (maxKC>xkb->max_key_code) {
62505b261ecSmrg	if (changes)
62605b261ecSmrg	    changes->map.max_key_code= maxKC;
62705b261ecSmrg	tmp= maxKC-xkb->max_key_code;
62805b261ecSmrg	if (xkb->map)  {
62905b261ecSmrg	    if (xkb->map->key_sym_map) {
63005b261ecSmrg		XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
63105b261ecSmrg
6326747b715Smrg		xkb->map->key_sym_map = realloc(xkb->map->key_sym_map,
6336747b715Smrg						(maxKC+1) * sizeof(XkbSymMapRec));
63405b261ecSmrg		if (!xkb->map->key_sym_map) {
6356747b715Smrg		    free(prev_key_sym_map);
63605b261ecSmrg		    return BadAlloc;
63705b261ecSmrg		}
6386747b715Smrg		memset((char *)&xkb->map->key_sym_map[xkb->max_key_code], 0,
63905b261ecSmrg					tmp*sizeof(XkbSymMapRec));
64005b261ecSmrg		if (changes) {
64105b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
64205b261ecSmrg		    				XkbKeySymsMask,maxKC,
64305b261ecSmrg	    					&changes->map.first_key_sym,
64405b261ecSmrg	    					&changes->map.num_key_syms);
64505b261ecSmrg		}
64605b261ecSmrg	    }
64705b261ecSmrg	    if (xkb->map->modmap) {
64805b261ecSmrg		unsigned char *prev_modmap = xkb->map->modmap;
64905b261ecSmrg
6506747b715Smrg		xkb->map->modmap = realloc(xkb->map->modmap,
6516747b715Smrg					    (maxKC+1) * sizeof(unsigned char));
65205b261ecSmrg		if (!xkb->map->modmap) {
6536747b715Smrg		    free(prev_modmap);
65405b261ecSmrg		    return BadAlloc;
65505b261ecSmrg		}
6566747b715Smrg		memset((char *)&xkb->map->modmap[xkb->max_key_code], 0, tmp);
65705b261ecSmrg		if (changes) {
65805b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
65905b261ecSmrg		    				XkbModifierMapMask,maxKC,
66005b261ecSmrg	    					&changes->map.first_modmap_key,
66105b261ecSmrg	    					&changes->map.num_modmap_keys);
66205b261ecSmrg		}
66305b261ecSmrg	    }
66405b261ecSmrg	}
66505b261ecSmrg	if (xkb->server) {
66605b261ecSmrg	    if (xkb->server->behaviors) {
66705b261ecSmrg		XkbBehavior *prev_behaviors = xkb->server->behaviors;
66805b261ecSmrg
6696747b715Smrg		xkb->server->behaviors = realloc(xkb->server->behaviors,
6706747b715Smrg						(maxKC+1) * sizeof(XkbBehavior));
67105b261ecSmrg		if (!xkb->server->behaviors) {
6726747b715Smrg		    free(prev_behaviors);
67305b261ecSmrg		    return BadAlloc;
67405b261ecSmrg		}
6756747b715Smrg		memset((char *)&xkb->server->behaviors[xkb->max_key_code], 0,
67605b261ecSmrg						tmp*sizeof(XkbBehavior));
67705b261ecSmrg		if (changes) {
67805b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
67905b261ecSmrg		    			XkbKeyBehaviorsMask,maxKC,
68005b261ecSmrg    					&changes->map.first_key_behavior,
68105b261ecSmrg    					&changes->map.num_key_behaviors);
68205b261ecSmrg		}
68305b261ecSmrg	    }
68405b261ecSmrg	    if (xkb->server->key_acts) {
68505b261ecSmrg		unsigned short *prev_key_acts = xkb->server->key_acts;
68605b261ecSmrg
6876747b715Smrg		xkb->server->key_acts= realloc(xkb->server->key_acts,
6886747b715Smrg						(maxKC+1) * sizeof(unsigned short));
68905b261ecSmrg		if (!xkb->server->key_acts) {
6906747b715Smrg		    free(prev_key_acts);
69105b261ecSmrg		    return BadAlloc;
69205b261ecSmrg		}
6936747b715Smrg		memset((char *)&xkb->server->key_acts[xkb->max_key_code], 0,
69405b261ecSmrg						tmp*sizeof(unsigned short));
69505b261ecSmrg		if (changes) {
69605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
69705b261ecSmrg		    			XkbKeyActionsMask,maxKC,
69805b261ecSmrg    					&changes->map.first_key_act,
69905b261ecSmrg    					&changes->map.num_key_acts);
70005b261ecSmrg		}
70105b261ecSmrg	    }
70205b261ecSmrg	    if (xkb->server->vmodmap) {
70305b261ecSmrg		unsigned short *prev_vmodmap = xkb->server->vmodmap;
70405b261ecSmrg
7056747b715Smrg		xkb->server->vmodmap= realloc(xkb->server->vmodmap,
7066747b715Smrg						(maxKC+1) * sizeof(unsigned short));
70705b261ecSmrg		if (!xkb->server->vmodmap) {
7086747b715Smrg		    free(prev_vmodmap);
70905b261ecSmrg		    return BadAlloc;
71005b261ecSmrg		}
7116747b715Smrg		memset((char *)&xkb->server->vmodmap[xkb->max_key_code], 0,
71205b261ecSmrg						tmp*sizeof(unsigned short));
71305b261ecSmrg		if (changes) {
71405b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
71505b261ecSmrg		    			XkbVirtualModMapMask,maxKC,
71605b261ecSmrg		    			&changes->map.first_modmap_key,
71705b261ecSmrg    					&changes->map.num_vmodmap_keys);
71805b261ecSmrg		}
71905b261ecSmrg	    }
72005b261ecSmrg	}
72105b261ecSmrg	if ((xkb->names)&&(xkb->names->keys)) {
72205b261ecSmrg	    XkbKeyNameRec *prev_keys = xkb->names->keys;
72305b261ecSmrg
7246747b715Smrg	    xkb->names->keys = realloc(xkb->names->keys,
7256747b715Smrg					(maxKC+1) * sizeof(XkbKeyNameRec));
72605b261ecSmrg	    if (!xkb->names->keys) {
7276747b715Smrg		free(prev_keys);
72805b261ecSmrg		return BadAlloc;
72905b261ecSmrg	    }
7306747b715Smrg	    memset((char *)&xkb->names->keys[xkb->max_key_code], 0,
73105b261ecSmrg	    					tmp*sizeof(XkbKeyNameRec));
73205b261ecSmrg	    if (changes) {
73305b261ecSmrg		changes->names.changed= _ExtendRange(changes->names.changed,
73405b261ecSmrg					XkbKeyNamesMask,maxKC,
73505b261ecSmrg					&changes->names.first_key,
73605b261ecSmrg    					&changes->names.num_keys);
73705b261ecSmrg	    }
73805b261ecSmrg	}
73905b261ecSmrg	xkb->max_key_code= maxKC;
74005b261ecSmrg    }
74105b261ecSmrg    return Success;
74205b261ecSmrg}
74305b261ecSmrg
74405b261ecSmrgXkbAction *
74505b261ecSmrgXkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)
74605b261ecSmrg{
74705b261ecSmrgregister int i,nActs;
74805b261ecSmrgXkbAction *newActs;
74905b261ecSmrg
75005b261ecSmrg    if (needed==0) {
75105b261ecSmrg	xkb->server->key_acts[key]= 0;
75205b261ecSmrg	return NULL;
75305b261ecSmrg    }
75405b261ecSmrg    if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed))
75505b261ecSmrg	return XkbKeyActionsPtr(xkb,key);
75605b261ecSmrg    if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) {
75705b261ecSmrg	xkb->server->key_acts[key]= xkb->server->num_acts;
75805b261ecSmrg	xkb->server->num_acts+= needed;
75905b261ecSmrg	return &xkb->server->acts[xkb->server->key_acts[key]];
76005b261ecSmrg    }
76105b261ecSmrg    xkb->server->size_acts= xkb->server->num_acts+needed+8;
7626747b715Smrg    newActs = calloc(xkb->server->size_acts, sizeof(XkbAction));
76305b261ecSmrg    if (newActs==NULL)
76405b261ecSmrg	return NULL;
76505b261ecSmrg    newActs[0].type = XkbSA_NoAction;
76605b261ecSmrg    nActs = 1;
76705b261ecSmrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
76805b261ecSmrg	int nKeyActs,nCopy;
76905b261ecSmrg
77005b261ecSmrg	if ((xkb->server->key_acts[i]==0)&&(i!=key))
77105b261ecSmrg	    continue;
77205b261ecSmrg
77305b261ecSmrg	nCopy= nKeyActs= XkbKeyNumActions(xkb,i);
77405b261ecSmrg	if (i==key) {
77505b261ecSmrg	    nKeyActs= needed;
77605b261ecSmrg	    if (needed<nCopy)
77705b261ecSmrg		nCopy= needed;
77805b261ecSmrg	}
77905b261ecSmrg
78005b261ecSmrg	if (nCopy>0)
78105b261ecSmrg	    memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i),
78205b261ecSmrg						nCopy*sizeof(XkbAction));
78305b261ecSmrg	if (nCopy<nKeyActs)
7846747b715Smrg	    memset(&newActs[nActs+nCopy], 0, (nKeyActs-nCopy)*sizeof(XkbAction));
78505b261ecSmrg	xkb->server->key_acts[i]= nActs;
78605b261ecSmrg	nActs+= nKeyActs;
78705b261ecSmrg    }
7886747b715Smrg    free(xkb->server->acts);
78905b261ecSmrg    xkb->server->acts = newActs;
79005b261ecSmrg    xkb->server->num_acts= nActs;
79105b261ecSmrg    return &xkb->server->acts[xkb->server->key_acts[key]];
79205b261ecSmrg}
79305b261ecSmrg
79405b261ecSmrgvoid
79505b261ecSmrgXkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
79605b261ecSmrg{
79705b261ecSmrgXkbClientMapPtr	map;
79805b261ecSmrg
79905b261ecSmrg    if ((xkb==NULL)||(xkb->map==NULL))
80005b261ecSmrg	return;
80105b261ecSmrg    if (freeMap)
80205b261ecSmrg	what= XkbAllClientInfoMask;
80305b261ecSmrg    map= xkb->map;
80405b261ecSmrg    if (what&XkbKeyTypesMask) {
80505b261ecSmrg	if (map->types!=NULL) {
80605b261ecSmrg	    if (map->num_types>0) {
80705b261ecSmrg		register int 	i;
80805b261ecSmrg		XkbKeyTypePtr	type;
80905b261ecSmrg		for (i=0,type=map->types;i<map->num_types;i++,type++) {
81005b261ecSmrg		    if (type->map!=NULL) {
8116747b715Smrg			free(type->map);
81205b261ecSmrg			type->map= NULL;
81305b261ecSmrg		    }
81405b261ecSmrg		    if (type->preserve!=NULL) {
8156747b715Smrg			free(type->preserve);
81605b261ecSmrg			type->preserve= NULL;
81705b261ecSmrg		    }
81805b261ecSmrg		    type->map_count= 0;
81905b261ecSmrg		    if (type->level_names!=NULL) {
8206747b715Smrg			free(type->level_names);
82105b261ecSmrg			type->level_names= NULL;
82205b261ecSmrg		    }
82305b261ecSmrg		}
82405b261ecSmrg	    }
8256747b715Smrg	    free(map->types);
82605b261ecSmrg	    map->num_types= map->size_types= 0;
82705b261ecSmrg	    map->types= NULL;
82805b261ecSmrg	}
82905b261ecSmrg    }
83005b261ecSmrg    if (what&XkbKeySymsMask) {
83105b261ecSmrg	if (map->key_sym_map!=NULL) {
8326747b715Smrg	    free(map->key_sym_map);
83305b261ecSmrg	    map->key_sym_map= NULL;
83405b261ecSmrg	}
83505b261ecSmrg	if (map->syms!=NULL) {
8366747b715Smrg	    free(map->syms);
83705b261ecSmrg	    map->size_syms= map->num_syms= 0;
83805b261ecSmrg	    map->syms= NULL;
83905b261ecSmrg	}
84005b261ecSmrg    }
84105b261ecSmrg    if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
8426747b715Smrg	free(map->modmap);
84305b261ecSmrg	map->modmap= NULL;
84405b261ecSmrg    }
84505b261ecSmrg    if (freeMap) {
8466747b715Smrg	free(xkb->map);
84705b261ecSmrg	xkb->map= NULL;
84805b261ecSmrg    }
84905b261ecSmrg    return;
85005b261ecSmrg}
85105b261ecSmrg
85205b261ecSmrgvoid
85305b261ecSmrgXkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
85405b261ecSmrg{
85505b261ecSmrgXkbServerMapPtr	map;
85605b261ecSmrg
85705b261ecSmrg    if ((xkb==NULL)||(xkb->server==NULL))
85805b261ecSmrg	return;
85905b261ecSmrg    if (freeMap)
86005b261ecSmrg	what= XkbAllServerInfoMask;
86105b261ecSmrg    map= xkb->server;
86205b261ecSmrg    if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
8636747b715Smrg	free(map->explicit);
86405b261ecSmrg	map->explicit= NULL;
86505b261ecSmrg    }
86605b261ecSmrg    if (what&XkbKeyActionsMask) {
86705b261ecSmrg	if (map->key_acts!=NULL) {
8686747b715Smrg	    free(map->key_acts);
86905b261ecSmrg	    map->key_acts= NULL;
87005b261ecSmrg	}
87105b261ecSmrg	if (map->acts!=NULL) {
8726747b715Smrg	    free(map->acts);
87305b261ecSmrg	    map->num_acts= map->size_acts= 0;
87405b261ecSmrg	    map->acts= NULL;
87505b261ecSmrg	}
87605b261ecSmrg    }
87705b261ecSmrg    if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
8786747b715Smrg	free(map->behaviors);
87905b261ecSmrg	map->behaviors= NULL;
88005b261ecSmrg    }
88105b261ecSmrg    if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
8826747b715Smrg	free(map->vmodmap);
88305b261ecSmrg	map->vmodmap= NULL;
88405b261ecSmrg    }
88505b261ecSmrg
88605b261ecSmrg    if (freeMap) {
8876747b715Smrg	free(xkb->server);
88805b261ecSmrg	xkb->server= NULL;
88905b261ecSmrg    }
89005b261ecSmrg    return;
89105b261ecSmrg}
892