XKBMAlloc.c revision 4642e01f
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#define	NEED_EVENTS
3605b261ecSmrg#define	NEED_REPLIES
3705b261ecSmrg#include <X11/Xproto.h>
3805b261ecSmrg#include "misc.h"
3905b261ecSmrg#include "inputstr.h"
4005b261ecSmrg#include <X11/keysym.h>
4105b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
4205b261ecSmrg#include <xkbsrv.h>
4305b261ecSmrg
4405b261ecSmrg/***====================================================================***/
4505b261ecSmrg
4605b261ecSmrgStatus
4705b261ecSmrgXkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)
4805b261ecSmrg{
4905b261ecSmrgregister int	i;
5005b261ecSmrgXkbClientMapPtr map;
5105b261ecSmrg
5205b261ecSmrg    if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
5305b261ecSmrg	return BadValue;
5405b261ecSmrg    if ((which&XkbKeySymsMask)&&
5505b261ecSmrg	((!XkbIsLegalKeycode(xkb->min_key_code))||
5605b261ecSmrg	 (!XkbIsLegalKeycode(xkb->max_key_code))||
5705b261ecSmrg	 (xkb->max_key_code<xkb->min_key_code))) {
584642e01fSmrg        DebugF("bad keycode (%d,%d) in XkbAllocClientMap\n",
5905b261ecSmrg				xkb->min_key_code,xkb->max_key_code);
6005b261ecSmrg	return BadValue;
6105b261ecSmrg    }
6205b261ecSmrg
6305b261ecSmrg    if (xkb->map==NULL) {
6405b261ecSmrg	map= _XkbTypedCalloc(1,XkbClientMapRec);
6505b261ecSmrg	if (map==NULL)
6605b261ecSmrg	    return BadAlloc;
6705b261ecSmrg	xkb->map= map;
6805b261ecSmrg    }
6905b261ecSmrg    else map= xkb->map;
7005b261ecSmrg
7105b261ecSmrg    if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
7205b261ecSmrg	if (map->types==NULL) {
7305b261ecSmrg	    map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec);
7405b261ecSmrg	    if (map->types==NULL)
7505b261ecSmrg		return BadAlloc;
7605b261ecSmrg	    map->num_types= 0;
7705b261ecSmrg	    map->size_types= nTotalTypes;
7805b261ecSmrg	}
7905b261ecSmrg	else if (map->size_types<nTotalTypes) {
8005b261ecSmrg	    XkbKeyTypeRec *prev_types = map->types;
8105b261ecSmrg
8205b261ecSmrg	    map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec);
8305b261ecSmrg	    if (map->types==NULL) {
8405b261ecSmrg		_XkbFree(prev_types);
8505b261ecSmrg		map->num_types= map->size_types= 0;
8605b261ecSmrg		return BadAlloc;
8705b261ecSmrg	    }
8805b261ecSmrg	    map->size_types= nTotalTypes;
8905b261ecSmrg	    bzero(&map->types[map->num_types],
9005b261ecSmrg		  ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
9105b261ecSmrg	}
9205b261ecSmrg    }
9305b261ecSmrg    if (which&XkbKeySymsMask) {
9405b261ecSmrg	int nKeys= XkbNumKeys(xkb);
9505b261ecSmrg	if (map->syms==NULL) {
9605b261ecSmrg	    map->size_syms= (nKeys*15)/10;
9705b261ecSmrg	    map->syms= _XkbTypedCalloc(map->size_syms,KeySym);
9805b261ecSmrg	    if (!map->syms) {
9905b261ecSmrg		map->size_syms= 0;
10005b261ecSmrg		return BadAlloc;
10105b261ecSmrg	    }
10205b261ecSmrg	    map->num_syms= 1;
10305b261ecSmrg	    map->syms[0]= NoSymbol;
10405b261ecSmrg	}
10505b261ecSmrg	if (map->key_sym_map==NULL) {
10605b261ecSmrg	    i= xkb->max_key_code+1;
10705b261ecSmrg	    map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec);
10805b261ecSmrg	    if (map->key_sym_map==NULL)
10905b261ecSmrg		return BadAlloc;
11005b261ecSmrg	}
11105b261ecSmrg    }
11205b261ecSmrg    if (which&XkbModifierMapMask) {
11305b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
11405b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
11505b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
11605b261ecSmrg	    return BadMatch;
11705b261ecSmrg	if (map->modmap==NULL) {
11805b261ecSmrg	    i= xkb->max_key_code+1;
11905b261ecSmrg	    map->modmap= _XkbTypedCalloc(i,unsigned char);
12005b261ecSmrg	    if (map->modmap==NULL)
12105b261ecSmrg		return BadAlloc;
12205b261ecSmrg	}
12305b261ecSmrg    }
12405b261ecSmrg    return Success;
12505b261ecSmrg}
12605b261ecSmrg
12705b261ecSmrgStatus
12805b261ecSmrgXkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)
12905b261ecSmrg{
13005b261ecSmrgregister int	i;
13105b261ecSmrgXkbServerMapPtr map;
13205b261ecSmrg
13305b261ecSmrg    if (xkb==NULL)
13405b261ecSmrg	return BadMatch;
13505b261ecSmrg    if (xkb->server==NULL) {
13605b261ecSmrg	map= _XkbTypedCalloc(1,XkbServerMapRec);
13705b261ecSmrg	if (map==NULL)
13805b261ecSmrg	    return BadAlloc;
13905b261ecSmrg	for (i=0;i<XkbNumVirtualMods;i++) {
14005b261ecSmrg	    map->vmods[i]= XkbNoModifierMask;
14105b261ecSmrg	}
14205b261ecSmrg	xkb->server= map;
14305b261ecSmrg    }
14405b261ecSmrg    else map= xkb->server;
14505b261ecSmrg    if (which&XkbExplicitComponentsMask) {
14605b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
14705b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
14805b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
14905b261ecSmrg	    return BadMatch;
15005b261ecSmrg	if (map->explicit==NULL) {
15105b261ecSmrg	    i= xkb->max_key_code+1;
15205b261ecSmrg	    map->explicit= _XkbTypedCalloc(i,unsigned char);
15305b261ecSmrg	    if (map->explicit==NULL)
15405b261ecSmrg		return BadAlloc;
15505b261ecSmrg	}
15605b261ecSmrg    }
15705b261ecSmrg    if (which&XkbKeyActionsMask) {
15805b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
15905b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
16005b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
16105b261ecSmrg	    return BadMatch;
16205b261ecSmrg        if (nNewActions<1)
16305b261ecSmrg	    nNewActions= 1;
16405b261ecSmrg	if (map->acts==NULL) {
16505b261ecSmrg	    map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction);
16605b261ecSmrg	    if (map->acts==NULL)
16705b261ecSmrg		return BadAlloc;
16805b261ecSmrg	    map->num_acts= 1;
16905b261ecSmrg	    map->size_acts= nNewActions+1;
17005b261ecSmrg	}
17105b261ecSmrg	else if ((map->size_acts-map->num_acts)<nNewActions) {
17205b261ecSmrg	    unsigned need;
17305b261ecSmrg	    XkbAction *prev_acts = map->acts;
17405b261ecSmrg	    need= map->num_acts+nNewActions;
17505b261ecSmrg	    map->acts= _XkbTypedRealloc(map->acts,need,XkbAction);
17605b261ecSmrg	    if (map->acts==NULL) {
17705b261ecSmrg		_XkbFree(prev_acts);
17805b261ecSmrg	        map->num_acts= map->size_acts= 0;
17905b261ecSmrg	        return BadAlloc;
18005b261ecSmrg	    }
18105b261ecSmrg	    map->size_acts= need;
18205b261ecSmrg	    bzero(&map->acts[map->num_acts],
18305b261ecSmrg		    ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
18405b261ecSmrg	}
18505b261ecSmrg	if (map->key_acts==NULL) {
18605b261ecSmrg	    i= xkb->max_key_code+1;
18705b261ecSmrg	    map->key_acts= _XkbTypedCalloc(i,unsigned short);
18805b261ecSmrg	    if (map->key_acts==NULL)
18905b261ecSmrg		return BadAlloc;
19005b261ecSmrg	}
19105b261ecSmrg    }
19205b261ecSmrg    if (which&XkbKeyBehaviorsMask) {
19305b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
19405b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
19505b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
19605b261ecSmrg	    return BadMatch;
19705b261ecSmrg	if (map->behaviors==NULL) {
19805b261ecSmrg	    i= xkb->max_key_code+1;
19905b261ecSmrg	    map->behaviors= _XkbTypedCalloc(i,XkbBehavior);
20005b261ecSmrg	    if (map->behaviors==NULL)
20105b261ecSmrg		return BadAlloc;
20205b261ecSmrg	}
20305b261ecSmrg    }
20405b261ecSmrg    if (which&XkbVirtualModMapMask) {
20505b261ecSmrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
20605b261ecSmrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
20705b261ecSmrg	    (xkb->max_key_code<xkb->min_key_code))
20805b261ecSmrg	    return BadMatch;
20905b261ecSmrg	if (map->vmodmap==NULL) {
21005b261ecSmrg	    i= xkb->max_key_code+1;
21105b261ecSmrg	    map->vmodmap= _XkbTypedCalloc(i,unsigned short);
21205b261ecSmrg	    if (map->vmodmap==NULL)
21305b261ecSmrg		return BadAlloc;
21405b261ecSmrg	}
21505b261ecSmrg    }
21605b261ecSmrg    return Success;
21705b261ecSmrg}
21805b261ecSmrg
21905b261ecSmrg/***====================================================================***/
22005b261ecSmrg
22105b261ecSmrgstatic Status
22205b261ecSmrgXkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)
22305b261ecSmrg{
22405b261ecSmrg    if ((!from)||(!into))
22505b261ecSmrg	return BadMatch;
22605b261ecSmrg    if (into->map) {
22705b261ecSmrg	_XkbFree(into->map);
22805b261ecSmrg	into->map= NULL;
22905b261ecSmrg    }
23005b261ecSmrg    if (into->preserve) {
23105b261ecSmrg	_XkbFree(into->preserve);
23205b261ecSmrg	into->preserve= NULL;
23305b261ecSmrg    }
23405b261ecSmrg    if (into->level_names) {
23505b261ecSmrg	_XkbFree(into->level_names);
23605b261ecSmrg	into->level_names= NULL;
23705b261ecSmrg    }
23805b261ecSmrg    *into= *from;
23905b261ecSmrg    if ((from->map)&&(into->map_count>0)) {
24005b261ecSmrg	into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec);
24105b261ecSmrg	if (!into->map)
24205b261ecSmrg	    return BadAlloc;
24305b261ecSmrg	memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec));
24405b261ecSmrg    }
24505b261ecSmrg    if ((from->preserve)&&(into->map_count>0)) {
24605b261ecSmrg	into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec);
24705b261ecSmrg	if (!into->preserve)
24805b261ecSmrg	    return BadAlloc;
24905b261ecSmrg	memcpy(into->preserve,from->preserve,
25005b261ecSmrg				into->map_count*sizeof(XkbModsRec));
25105b261ecSmrg    }
25205b261ecSmrg    if ((from->level_names)&&(into->num_levels>0)) {
25305b261ecSmrg	into->level_names= _XkbTypedCalloc(into->num_levels,Atom);
25405b261ecSmrg	if (!into->level_names)
25505b261ecSmrg	    return BadAlloc;
25605b261ecSmrg	memcpy(into->level_names,from->level_names,
25705b261ecSmrg				 into->num_levels*sizeof(Atom));
25805b261ecSmrg    }
25905b261ecSmrg    return Success;
26005b261ecSmrg}
26105b261ecSmrg
26205b261ecSmrgStatus
26305b261ecSmrgXkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)
26405b261ecSmrg{
26505b261ecSmrgregister int i,rtrn;
26605b261ecSmrg
26705b261ecSmrg    if ((!from)||(!into)||(num_types<0))
26805b261ecSmrg	return BadMatch;
26905b261ecSmrg    for (i=0;i<num_types;i++) {
27005b261ecSmrg	if ((rtrn= XkbCopyKeyType(from++,into++))!=Success)
27105b261ecSmrg	    return rtrn;
27205b261ecSmrg    }
27305b261ecSmrg    return Success;
27405b261ecSmrg}
27505b261ecSmrg
27605b261ecSmrgStatus
27705b261ecSmrgXkbResizeKeyType(	XkbDescPtr	xkb,
27805b261ecSmrg			int		type_ndx,
27905b261ecSmrg			int		map_count,
28005b261ecSmrg			Bool		want_preserve,
28105b261ecSmrg			int		new_num_lvls)
28205b261ecSmrg{
28305b261ecSmrgXkbKeyTypePtr	type;
28405b261ecSmrgKeyCode		matchingKeys[XkbMaxKeyCount],nMatchingKeys;
28505b261ecSmrg
28605b261ecSmrg    if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)||
28705b261ecSmrg    							(new_num_lvls<1))
28805b261ecSmrg	return BadValue;
28905b261ecSmrg    switch (type_ndx) {
29005b261ecSmrg	case XkbOneLevelIndex:
29105b261ecSmrg	    if (new_num_lvls!=1)
29205b261ecSmrg		return BadMatch;
29305b261ecSmrg	    break;
29405b261ecSmrg	case XkbTwoLevelIndex:
29505b261ecSmrg	case XkbAlphabeticIndex:
29605b261ecSmrg	case XkbKeypadIndex:
29705b261ecSmrg	    if (new_num_lvls!=2)
29805b261ecSmrg		return BadMatch;
29905b261ecSmrg	    break;
30005b261ecSmrg    }
30105b261ecSmrg    type= &xkb->map->types[type_ndx];
30205b261ecSmrg    if (map_count==0) {
30305b261ecSmrg	if (type->map!=NULL)
30405b261ecSmrg	    _XkbFree(type->map);
30505b261ecSmrg	type->map= NULL;
30605b261ecSmrg	if (type->preserve!=NULL)
30705b261ecSmrg	    _XkbFree(type->preserve);
30805b261ecSmrg	type->preserve= NULL;
30905b261ecSmrg	type->map_count= 0;
31005b261ecSmrg    }
31105b261ecSmrg    else {
31205b261ecSmrg	XkbKTMapEntryRec *prev_map = type->map;
31305b261ecSmrg
31405b261ecSmrg	if ((map_count>type->map_count)||(type->map==NULL))
31505b261ecSmrg	    type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec);
31605b261ecSmrg	if (!type->map) {
31705b261ecSmrg	    if (prev_map)
31805b261ecSmrg		_XkbFree(prev_map);
31905b261ecSmrg	    return BadAlloc;
32005b261ecSmrg	}
32105b261ecSmrg	if (want_preserve) {
32205b261ecSmrg	    XkbModsRec *prev_preserve = type->preserve;
32305b261ecSmrg
32405b261ecSmrg	    if ((map_count>type->map_count)||(type->preserve==NULL)) {
32505b261ecSmrg		type->preserve= _XkbTypedRealloc(type->preserve,map_count,
32605b261ecSmrg	     						    XkbModsRec);
32705b261ecSmrg	    }
32805b261ecSmrg	    if (!type->preserve) {
32905b261ecSmrg		if (prev_preserve)
33005b261ecSmrg		    _XkbFree(prev_preserve);
33105b261ecSmrg		return BadAlloc;
33205b261ecSmrg	    }
33305b261ecSmrg	}
33405b261ecSmrg	else if (type->preserve!=NULL) {
33505b261ecSmrg	    _XkbFree(type->preserve);
33605b261ecSmrg	    type->preserve= NULL;
33705b261ecSmrg	}
33805b261ecSmrg	type->map_count= map_count;
33905b261ecSmrg    }
34005b261ecSmrg
34105b261ecSmrg    if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) {
34205b261ecSmrg	Atom * prev_level_names = type->level_names;
34305b261ecSmrg
34405b261ecSmrg	type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom);
34505b261ecSmrg	if (!type->level_names) {
34605b261ecSmrg	    if (prev_level_names)
34705b261ecSmrg		_XkbFree(prev_level_names);
34805b261ecSmrg	    return BadAlloc;
34905b261ecSmrg	}
35005b261ecSmrg    }
35105b261ecSmrg    /*
35205b261ecSmrg     * Here's the theory:
35305b261ecSmrg     *    If the width of the type changed, we might have to resize the symbol
35405b261ecSmrg     * maps for any keys that use the type for one or more groups.  This is
35505b261ecSmrg     * expensive, so we'll try to cull out any keys that are obviously okay:
35605b261ecSmrg     * In any case:
35705b261ecSmrg     *    - keys that have a group width <= the old width are okay (because
35805b261ecSmrg     *      they could not possibly have been associated with the old type)
35905b261ecSmrg     * If the key type increased in size:
36005b261ecSmrg     *    - keys that already have a group width >= to the new width are okay
36105b261ecSmrg     *    + keys that have a group width >= the old width but < the new width
36205b261ecSmrg     *      might have to be enlarged.
36305b261ecSmrg     * If the key type decreased in size:
36405b261ecSmrg     *    - keys that have a group width > the old width don't have to be
36505b261ecSmrg     *      resized (because they must have some other wider type associated
36605b261ecSmrg     *      with some group).
36705b261ecSmrg     *    + keys that have a group width == the old width might have to be
36805b261ecSmrg     *      shrunk.
36905b261ecSmrg     * The possibilities marked with '+' require us to examine the key types
37005b261ecSmrg     * associated with each group for the key.
37105b261ecSmrg     */
37205b261ecSmrg    bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode));
37305b261ecSmrg    nMatchingKeys= 0;
37405b261ecSmrg    if (new_num_lvls>type->num_levels) {
37505b261ecSmrg	int	 		nTotal;
37605b261ecSmrg	KeySym	*		newSyms;
37705b261ecSmrg	int			width,match,nResize;
37805b261ecSmrg	register int		i,g,nSyms;
37905b261ecSmrg
38005b261ecSmrg	nResize= 0;
38105b261ecSmrg	for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
38205b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,i);
38305b261ecSmrg	    if (width<type->num_levels)
38405b261ecSmrg		continue;
38505b261ecSmrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
38605b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
38705b261ecSmrg		    matchingKeys[nMatchingKeys++]= i;
38805b261ecSmrg		    match= 1;
38905b261ecSmrg		}
39005b261ecSmrg	    }
39105b261ecSmrg	    if ((!match)||(width>=new_num_lvls))
39205b261ecSmrg		nTotal+= XkbKeyNumSyms(xkb,i);
39305b261ecSmrg	    else {
39405b261ecSmrg		nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
39505b261ecSmrg		nResize++;
39605b261ecSmrg	    }
39705b261ecSmrg	}
39805b261ecSmrg	if (nResize>0) {
39905b261ecSmrg	    int nextMatch;
40005b261ecSmrg	    xkb->map->size_syms= (nTotal*15)/10;
40105b261ecSmrg	    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
40205b261ecSmrg	    if (newSyms==NULL)
40305b261ecSmrg		return BadAlloc;
40405b261ecSmrg	    nextMatch= 0;
40505b261ecSmrg	    nSyms= 1;
40605b261ecSmrg	    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
40705b261ecSmrg		if (matchingKeys[nextMatch]==i) {
40805b261ecSmrg		    KeySym *pOld;
40905b261ecSmrg		    nextMatch++;
41005b261ecSmrg		    width= XkbKeyGroupsWidth(xkb,i);
41105b261ecSmrg		    pOld= XkbKeySymsPtr(xkb,i);
41205b261ecSmrg		    for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
41305b261ecSmrg			memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g],
41405b261ecSmrg							width*sizeof(KeySym));
41505b261ecSmrg		    }
41605b261ecSmrg		    xkb->map->key_sym_map[i].offset= nSyms;
41705b261ecSmrg		    nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
41805b261ecSmrg		}
41905b261ecSmrg		else {
42005b261ecSmrg		    memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),
42105b261ecSmrg					XkbKeyNumSyms(xkb,i)*sizeof(KeySym));
42205b261ecSmrg		    xkb->map->key_sym_map[i].offset= nSyms;
42305b261ecSmrg		    nSyms+= XkbKeyNumSyms(xkb,i);
42405b261ecSmrg		}
42505b261ecSmrg	    }
42605b261ecSmrg	    type->num_levels= new_num_lvls;
42705b261ecSmrg	    _XkbFree(xkb->map->syms);
42805b261ecSmrg	    xkb->map->syms= newSyms;
42905b261ecSmrg	    xkb->map->num_syms= nSyms;
43005b261ecSmrg	    return Success;
43105b261ecSmrg	}
43205b261ecSmrg    }
43305b261ecSmrg    else if (new_num_lvls<type->num_levels) {
43405b261ecSmrg	int 		width,match;
43505b261ecSmrg	register int	g,i;
43605b261ecSmrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
43705b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,i);
43805b261ecSmrg	    if (width<type->num_levels)
43905b261ecSmrg		continue;
44005b261ecSmrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
44105b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
44205b261ecSmrg		    matchingKeys[nMatchingKeys++]= i;
44305b261ecSmrg		    match= 1;
44405b261ecSmrg		}
44505b261ecSmrg	    }
44605b261ecSmrg	}
44705b261ecSmrg    }
44805b261ecSmrg    if (nMatchingKeys>0) {
44905b261ecSmrg	int 		key,firstClear;
45005b261ecSmrg	register int	i,g;
45105b261ecSmrg	if (new_num_lvls>type->num_levels)
45205b261ecSmrg	     firstClear= type->num_levels;
45305b261ecSmrg	else firstClear= new_num_lvls;
45405b261ecSmrg	for (i=0;i<nMatchingKeys;i++) {
45505b261ecSmrg	    KeySym *	pSyms;
45605b261ecSmrg	    int		width,nClear;
45705b261ecSmrg
45805b261ecSmrg	    key= matchingKeys[i];
45905b261ecSmrg	    width= XkbKeyGroupsWidth(xkb,key);
46005b261ecSmrg	    nClear= width-firstClear;
46105b261ecSmrg	    pSyms= XkbKeySymsPtr(xkb,key);
46205b261ecSmrg	    for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) {
46305b261ecSmrg		if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) {
46405b261ecSmrg		    if (nClear>0)
46505b261ecSmrg			bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym));
46605b261ecSmrg		}
46705b261ecSmrg	    }
46805b261ecSmrg	}
46905b261ecSmrg    }
47005b261ecSmrg    type->num_levels= new_num_lvls;
47105b261ecSmrg    return Success;
47205b261ecSmrg}
47305b261ecSmrg
47405b261ecSmrgKeySym *
47505b261ecSmrgXkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)
47605b261ecSmrg{
47705b261ecSmrgregister int i,nSyms,nKeySyms;
47805b261ecSmrgunsigned nOldSyms;
47905b261ecSmrgKeySym	*newSyms;
48005b261ecSmrg
48105b261ecSmrg    if (needed==0) {
48205b261ecSmrg	xkb->map->key_sym_map[key].offset= 0;
48305b261ecSmrg	return xkb->map->syms;
48405b261ecSmrg    }
48505b261ecSmrg    nOldSyms= XkbKeyNumSyms(xkb,key);
48605b261ecSmrg    if (nOldSyms>=(unsigned)needed) {
48705b261ecSmrg	return XkbKeySymsPtr(xkb,key);
48805b261ecSmrg    }
48905b261ecSmrg    if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) {
49005b261ecSmrg	if (nOldSyms>0) {
49105b261ecSmrg	    memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key),
49205b261ecSmrg						nOldSyms*sizeof(KeySym));
49305b261ecSmrg	}
49405b261ecSmrg	if ((needed-nOldSyms)>0) {
49505b261ecSmrg	    bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)],
49605b261ecSmrg					(needed-nOldSyms)*sizeof(KeySym));
49705b261ecSmrg	}
49805b261ecSmrg	xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
49905b261ecSmrg	xkb->map->num_syms+= needed;
50005b261ecSmrg	return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
50105b261ecSmrg    }
50205b261ecSmrg    xkb->map->size_syms+= (needed>32?needed:32);
50305b261ecSmrg    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
50405b261ecSmrg    if (newSyms==NULL)
50505b261ecSmrg	return NULL;
50605b261ecSmrg    newSyms[0]= NoSymbol;
50705b261ecSmrg    nSyms = 1;
50805b261ecSmrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
50905b261ecSmrg	int nCopy;
51005b261ecSmrg
51105b261ecSmrg	nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
51205b261ecSmrg	if ((nKeySyms==0)&&(i!=key))
51305b261ecSmrg	    continue;
51405b261ecSmrg	if (i==key)
51505b261ecSmrg	    nKeySyms= needed;
51605b261ecSmrg	if (nCopy!=0)
51705b261ecSmrg	   memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym));
51805b261ecSmrg	if (nKeySyms>nCopy)
51905b261ecSmrg	    bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym));
52005b261ecSmrg	xkb->map->key_sym_map[i].offset = nSyms;
52105b261ecSmrg	nSyms+= nKeySyms;
52205b261ecSmrg    }
52305b261ecSmrg    _XkbFree(xkb->map->syms);
52405b261ecSmrg    xkb->map->syms = newSyms;
52505b261ecSmrg    xkb->map->num_syms = nSyms;
52605b261ecSmrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
52705b261ecSmrg}
52805b261ecSmrg
52905b261ecSmrgstatic unsigned
53005b261ecSmrg_ExtendRange(	unsigned int 	old_flags,
53105b261ecSmrg		unsigned int	flag,
53205b261ecSmrg		KeyCode		newKC,
53305b261ecSmrg		KeyCode *	old_min,
53405b261ecSmrg		unsigned char *	old_num)
53505b261ecSmrg{
53605b261ecSmrg    if ((old_flags&flag)==0) {
53705b261ecSmrg	old_flags|= flag;
53805b261ecSmrg	*old_min= newKC;
53905b261ecSmrg	*old_num= 1;
54005b261ecSmrg    }
54105b261ecSmrg    else {
54205b261ecSmrg	int	last= (*old_min)+(*old_num)-1;
54305b261ecSmrg	if (newKC<*old_min) {
54405b261ecSmrg	    *old_min= newKC;
54505b261ecSmrg	    *old_num= (last-newKC)+1;
54605b261ecSmrg	}
54705b261ecSmrg	else if (newKC>last) {
54805b261ecSmrg	    *old_num= (newKC-(*old_min))+1;
54905b261ecSmrg	}
55005b261ecSmrg    }
55105b261ecSmrg    return old_flags;
55205b261ecSmrg}
55305b261ecSmrg
55405b261ecSmrgStatus
55505b261ecSmrgXkbChangeKeycodeRange(	XkbDescPtr	xkb,
55605b261ecSmrg			int 		minKC,
55705b261ecSmrg			int 		maxKC,
55805b261ecSmrg			XkbChangesPtr	changes)
55905b261ecSmrg{
56005b261ecSmrgint	tmp;
56105b261ecSmrg
56205b261ecSmrg    if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode))
56305b261ecSmrg	return BadValue;
56405b261ecSmrg    if (minKC>maxKC)
56505b261ecSmrg	return BadMatch;
56605b261ecSmrg    if (minKC<xkb->min_key_code) {
56705b261ecSmrg	if (changes)
56805b261ecSmrg	    changes->map.min_key_code= minKC;
56905b261ecSmrg	tmp= xkb->min_key_code-minKC;
57005b261ecSmrg	if (xkb->map)  {
57105b261ecSmrg	    if (xkb->map->key_sym_map) {
57205b261ecSmrg		bzero((char *)&xkb->map->key_sym_map[minKC],
57305b261ecSmrg					tmp*sizeof(XkbSymMapRec));
57405b261ecSmrg		if (changes) {
57505b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
57605b261ecSmrg		    				XkbKeySymsMask,minKC,
57705b261ecSmrg	    					&changes->map.first_key_sym,
57805b261ecSmrg	    					&changes->map.num_key_syms);
57905b261ecSmrg		}
58005b261ecSmrg	    }
58105b261ecSmrg	    if (xkb->map->modmap) {
58205b261ecSmrg		bzero((char *)&xkb->map->modmap[minKC],tmp);
58305b261ecSmrg		if (changes) {
58405b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
58505b261ecSmrg		    				XkbModifierMapMask,minKC,
58605b261ecSmrg	    					&changes->map.first_modmap_key,
58705b261ecSmrg	    					&changes->map.num_modmap_keys);
58805b261ecSmrg		}
58905b261ecSmrg	    }
59005b261ecSmrg	}
59105b261ecSmrg	if (xkb->server) {
59205b261ecSmrg	    if (xkb->server->behaviors) {
59305b261ecSmrg		bzero((char *)&xkb->server->behaviors[minKC],
59405b261ecSmrg						tmp*sizeof(XkbBehavior));
59505b261ecSmrg		if (changes) {
59605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
59705b261ecSmrg		    			XkbKeyBehaviorsMask,minKC,
59805b261ecSmrg    					&changes->map.first_key_behavior,
59905b261ecSmrg    					&changes->map.num_key_behaviors);
60005b261ecSmrg		}
60105b261ecSmrg	    }
60205b261ecSmrg	    if (xkb->server->key_acts) {
60305b261ecSmrg		bzero((char *)&xkb->server->key_acts[minKC],
60405b261ecSmrg						tmp*sizeof(unsigned short));
60505b261ecSmrg		if (changes) {
60605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
60705b261ecSmrg		    			XkbKeyActionsMask,minKC,
60805b261ecSmrg    					&changes->map.first_key_act,
60905b261ecSmrg    					&changes->map.num_key_acts);
61005b261ecSmrg		}
61105b261ecSmrg	    }
61205b261ecSmrg	    if (xkb->server->vmodmap) {
61305b261ecSmrg		bzero((char *)&xkb->server->vmodmap[minKC],
61405b261ecSmrg						tmp*sizeof(unsigned short));
61505b261ecSmrg		if (changes) {
61605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
61705b261ecSmrg		    			XkbVirtualModMapMask,minKC,
61805b261ecSmrg		    			&changes->map.first_modmap_key,
61905b261ecSmrg    					&changes->map.num_vmodmap_keys);
62005b261ecSmrg		}
62105b261ecSmrg	    }
62205b261ecSmrg	}
62305b261ecSmrg	if ((xkb->names)&&(xkb->names->keys)) {
62405b261ecSmrg	    bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec));
62505b261ecSmrg	    if (changes) {
62605b261ecSmrg		changes->names.changed= _ExtendRange(changes->names.changed,
62705b261ecSmrg					XkbKeyNamesMask,minKC,
62805b261ecSmrg					&changes->names.first_key,
62905b261ecSmrg    					&changes->names.num_keys);
63005b261ecSmrg	    }
63105b261ecSmrg	}
63205b261ecSmrg	xkb->min_key_code= minKC;
63305b261ecSmrg    }
63405b261ecSmrg    if (maxKC>xkb->max_key_code) {
63505b261ecSmrg	if (changes)
63605b261ecSmrg	    changes->map.max_key_code= maxKC;
63705b261ecSmrg	tmp= maxKC-xkb->max_key_code;
63805b261ecSmrg	if (xkb->map)  {
63905b261ecSmrg	    if (xkb->map->key_sym_map) {
64005b261ecSmrg		XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
64105b261ecSmrg
64205b261ecSmrg		xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map,
64305b261ecSmrg						(maxKC+1),XkbSymMapRec);
64405b261ecSmrg		if (!xkb->map->key_sym_map) {
64505b261ecSmrg		    _XkbFree(prev_key_sym_map);
64605b261ecSmrg		    return BadAlloc;
64705b261ecSmrg		}
64805b261ecSmrg		bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
64905b261ecSmrg					tmp*sizeof(XkbSymMapRec));
65005b261ecSmrg		if (changes) {
65105b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
65205b261ecSmrg		    				XkbKeySymsMask,maxKC,
65305b261ecSmrg	    					&changes->map.first_key_sym,
65405b261ecSmrg	    					&changes->map.num_key_syms);
65505b261ecSmrg		}
65605b261ecSmrg	    }
65705b261ecSmrg	    if (xkb->map->modmap) {
65805b261ecSmrg		unsigned char *prev_modmap = xkb->map->modmap;
65905b261ecSmrg
66005b261ecSmrg		xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap,
66105b261ecSmrg						(maxKC+1),unsigned char);
66205b261ecSmrg		if (!xkb->map->modmap) {
66305b261ecSmrg		    _XkbFree(prev_modmap);
66405b261ecSmrg		    return BadAlloc;
66505b261ecSmrg		}
66605b261ecSmrg		bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
66705b261ecSmrg		if (changes) {
66805b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
66905b261ecSmrg		    				XkbModifierMapMask,maxKC,
67005b261ecSmrg	    					&changes->map.first_modmap_key,
67105b261ecSmrg	    					&changes->map.num_modmap_keys);
67205b261ecSmrg		}
67305b261ecSmrg	    }
67405b261ecSmrg	}
67505b261ecSmrg	if (xkb->server) {
67605b261ecSmrg	    if (xkb->server->behaviors) {
67705b261ecSmrg		XkbBehavior *prev_behaviors = xkb->server->behaviors;
67805b261ecSmrg
67905b261ecSmrg		xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors,
68005b261ecSmrg						(maxKC+1),XkbBehavior);
68105b261ecSmrg		if (!xkb->server->behaviors) {
68205b261ecSmrg		    _XkbFree(prev_behaviors);
68305b261ecSmrg		    return BadAlloc;
68405b261ecSmrg		}
68505b261ecSmrg		bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
68605b261ecSmrg						tmp*sizeof(XkbBehavior));
68705b261ecSmrg		if (changes) {
68805b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
68905b261ecSmrg		    			XkbKeyBehaviorsMask,maxKC,
69005b261ecSmrg    					&changes->map.first_key_behavior,
69105b261ecSmrg    					&changes->map.num_key_behaviors);
69205b261ecSmrg		}
69305b261ecSmrg	    }
69405b261ecSmrg	    if (xkb->server->key_acts) {
69505b261ecSmrg		unsigned short *prev_key_acts = xkb->server->key_acts;
69605b261ecSmrg
69705b261ecSmrg		xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts,
69805b261ecSmrg						(maxKC+1),unsigned short);
69905b261ecSmrg		if (!xkb->server->key_acts) {
70005b261ecSmrg		    _XkbFree(prev_key_acts);
70105b261ecSmrg		    return BadAlloc;
70205b261ecSmrg		}
70305b261ecSmrg		bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
70405b261ecSmrg						tmp*sizeof(unsigned short));
70505b261ecSmrg		if (changes) {
70605b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
70705b261ecSmrg		    			XkbKeyActionsMask,maxKC,
70805b261ecSmrg    					&changes->map.first_key_act,
70905b261ecSmrg    					&changes->map.num_key_acts);
71005b261ecSmrg		}
71105b261ecSmrg	    }
71205b261ecSmrg	    if (xkb->server->vmodmap) {
71305b261ecSmrg		unsigned short *prev_vmodmap = xkb->server->vmodmap;
71405b261ecSmrg
71505b261ecSmrg		xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap,
71605b261ecSmrg						(maxKC+1),unsigned short);
71705b261ecSmrg		if (!xkb->server->vmodmap) {
71805b261ecSmrg		    _XkbFree(prev_vmodmap);
71905b261ecSmrg		    return BadAlloc;
72005b261ecSmrg		}
72105b261ecSmrg		bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
72205b261ecSmrg						tmp*sizeof(unsigned short));
72305b261ecSmrg		if (changes) {
72405b261ecSmrg		    changes->map.changed= _ExtendRange(changes->map.changed,
72505b261ecSmrg		    			XkbVirtualModMapMask,maxKC,
72605b261ecSmrg		    			&changes->map.first_modmap_key,
72705b261ecSmrg    					&changes->map.num_vmodmap_keys);
72805b261ecSmrg		}
72905b261ecSmrg	    }
73005b261ecSmrg	}
73105b261ecSmrg	if ((xkb->names)&&(xkb->names->keys)) {
73205b261ecSmrg	    XkbKeyNameRec *prev_keys = xkb->names->keys;
73305b261ecSmrg
73405b261ecSmrg	    xkb->names->keys= _XkbTypedRealloc(xkb->names->keys,
73505b261ecSmrg	    					(maxKC+1),XkbKeyNameRec);
73605b261ecSmrg	    if (!xkb->names->keys) {
73705b261ecSmrg		_XkbFree(prev_keys);
73805b261ecSmrg		return BadAlloc;
73905b261ecSmrg	    }
74005b261ecSmrg	    bzero((char *)&xkb->names->keys[xkb->max_key_code],
74105b261ecSmrg	    					tmp*sizeof(XkbKeyNameRec));
74205b261ecSmrg	    if (changes) {
74305b261ecSmrg		changes->names.changed= _ExtendRange(changes->names.changed,
74405b261ecSmrg					XkbKeyNamesMask,maxKC,
74505b261ecSmrg					&changes->names.first_key,
74605b261ecSmrg    					&changes->names.num_keys);
74705b261ecSmrg	    }
74805b261ecSmrg	}
74905b261ecSmrg	xkb->max_key_code= maxKC;
75005b261ecSmrg    }
75105b261ecSmrg    return Success;
75205b261ecSmrg}
75305b261ecSmrg
75405b261ecSmrgXkbAction *
75505b261ecSmrgXkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)
75605b261ecSmrg{
75705b261ecSmrgregister int i,nActs;
75805b261ecSmrgXkbAction *newActs;
75905b261ecSmrg
76005b261ecSmrg    if (needed==0) {
76105b261ecSmrg	xkb->server->key_acts[key]= 0;
76205b261ecSmrg	return NULL;
76305b261ecSmrg    }
76405b261ecSmrg    if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed))
76505b261ecSmrg	return XkbKeyActionsPtr(xkb,key);
76605b261ecSmrg    if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) {
76705b261ecSmrg	xkb->server->key_acts[key]= xkb->server->num_acts;
76805b261ecSmrg	xkb->server->num_acts+= needed;
76905b261ecSmrg	return &xkb->server->acts[xkb->server->key_acts[key]];
77005b261ecSmrg    }
77105b261ecSmrg    xkb->server->size_acts= xkb->server->num_acts+needed+8;
77205b261ecSmrg    newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction);
77305b261ecSmrg    if (newActs==NULL)
77405b261ecSmrg	return NULL;
77505b261ecSmrg    newActs[0].type = XkbSA_NoAction;
77605b261ecSmrg    nActs = 1;
77705b261ecSmrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
77805b261ecSmrg	int nKeyActs,nCopy;
77905b261ecSmrg
78005b261ecSmrg	if ((xkb->server->key_acts[i]==0)&&(i!=key))
78105b261ecSmrg	    continue;
78205b261ecSmrg
78305b261ecSmrg	nCopy= nKeyActs= XkbKeyNumActions(xkb,i);
78405b261ecSmrg	if (i==key) {
78505b261ecSmrg	    nKeyActs= needed;
78605b261ecSmrg	    if (needed<nCopy)
78705b261ecSmrg		nCopy= needed;
78805b261ecSmrg	}
78905b261ecSmrg
79005b261ecSmrg	if (nCopy>0)
79105b261ecSmrg	    memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i),
79205b261ecSmrg						nCopy*sizeof(XkbAction));
79305b261ecSmrg	if (nCopy<nKeyActs)
79405b261ecSmrg	    bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction));
79505b261ecSmrg	xkb->server->key_acts[i]= nActs;
79605b261ecSmrg	nActs+= nKeyActs;
79705b261ecSmrg    }
79805b261ecSmrg    _XkbFree(xkb->server->acts);
79905b261ecSmrg    xkb->server->acts = newActs;
80005b261ecSmrg    xkb->server->num_acts= nActs;
80105b261ecSmrg    return &xkb->server->acts[xkb->server->key_acts[key]];
80205b261ecSmrg}
80305b261ecSmrg
80405b261ecSmrgvoid
80505b261ecSmrgXkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
80605b261ecSmrg{
80705b261ecSmrgXkbClientMapPtr	map;
80805b261ecSmrg
80905b261ecSmrg    if ((xkb==NULL)||(xkb->map==NULL))
81005b261ecSmrg	return;
81105b261ecSmrg    if (freeMap)
81205b261ecSmrg	what= XkbAllClientInfoMask;
81305b261ecSmrg    map= xkb->map;
81405b261ecSmrg    if (what&XkbKeyTypesMask) {
81505b261ecSmrg	if (map->types!=NULL) {
81605b261ecSmrg	    if (map->num_types>0) {
81705b261ecSmrg		register int 	i;
81805b261ecSmrg		XkbKeyTypePtr	type;
81905b261ecSmrg		for (i=0,type=map->types;i<map->num_types;i++,type++) {
82005b261ecSmrg		    if (type->map!=NULL) {
82105b261ecSmrg			_XkbFree(type->map);
82205b261ecSmrg			type->map= NULL;
82305b261ecSmrg		    }
82405b261ecSmrg		    if (type->preserve!=NULL) {
82505b261ecSmrg			_XkbFree(type->preserve);
82605b261ecSmrg			type->preserve= NULL;
82705b261ecSmrg		    }
82805b261ecSmrg		    type->map_count= 0;
82905b261ecSmrg		    if (type->level_names!=NULL) {
83005b261ecSmrg			_XkbFree(type->level_names);
83105b261ecSmrg			type->level_names= NULL;
83205b261ecSmrg		    }
83305b261ecSmrg		}
83405b261ecSmrg	    }
83505b261ecSmrg	    _XkbFree(map->types);
83605b261ecSmrg	    map->num_types= map->size_types= 0;
83705b261ecSmrg	    map->types= NULL;
83805b261ecSmrg	}
83905b261ecSmrg    }
84005b261ecSmrg    if (what&XkbKeySymsMask) {
84105b261ecSmrg	if (map->key_sym_map!=NULL) {
84205b261ecSmrg	    _XkbFree(map->key_sym_map);
84305b261ecSmrg	    map->key_sym_map= NULL;
84405b261ecSmrg	}
84505b261ecSmrg	if (map->syms!=NULL) {
84605b261ecSmrg	    _XkbFree(map->syms);
84705b261ecSmrg	    map->size_syms= map->num_syms= 0;
84805b261ecSmrg	    map->syms= NULL;
84905b261ecSmrg	}
85005b261ecSmrg    }
85105b261ecSmrg    if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
85205b261ecSmrg	_XkbFree(map->modmap);
85305b261ecSmrg	map->modmap= NULL;
85405b261ecSmrg    }
85505b261ecSmrg    if (freeMap) {
85605b261ecSmrg	_XkbFree(xkb->map);
85705b261ecSmrg	xkb->map= NULL;
85805b261ecSmrg    }
85905b261ecSmrg    return;
86005b261ecSmrg}
86105b261ecSmrg
86205b261ecSmrgvoid
86305b261ecSmrgXkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
86405b261ecSmrg{
86505b261ecSmrgXkbServerMapPtr	map;
86605b261ecSmrg
86705b261ecSmrg    if ((xkb==NULL)||(xkb->server==NULL))
86805b261ecSmrg	return;
86905b261ecSmrg    if (freeMap)
87005b261ecSmrg	what= XkbAllServerInfoMask;
87105b261ecSmrg    map= xkb->server;
87205b261ecSmrg    if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
87305b261ecSmrg	_XkbFree(map->explicit);
87405b261ecSmrg	map->explicit= NULL;
87505b261ecSmrg    }
87605b261ecSmrg    if (what&XkbKeyActionsMask) {
87705b261ecSmrg	if (map->key_acts!=NULL) {
87805b261ecSmrg	    _XkbFree(map->key_acts);
87905b261ecSmrg	    map->key_acts= NULL;
88005b261ecSmrg	}
88105b261ecSmrg	if (map->acts!=NULL) {
88205b261ecSmrg	    _XkbFree(map->acts);
88305b261ecSmrg	    map->num_acts= map->size_acts= 0;
88405b261ecSmrg	    map->acts= NULL;
88505b261ecSmrg	}
88605b261ecSmrg    }
88705b261ecSmrg    if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
88805b261ecSmrg	_XkbFree(map->behaviors);
88905b261ecSmrg	map->behaviors= NULL;
89005b261ecSmrg    }
89105b261ecSmrg    if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
89205b261ecSmrg	_XkbFree(map->vmodmap);
89305b261ecSmrg	map->vmodmap= NULL;
89405b261ecSmrg    }
89505b261ecSmrg
89605b261ecSmrg    if (freeMap) {
89705b261ecSmrg	_XkbFree(xkb->server);
89805b261ecSmrg	xkb->server= NULL;
89905b261ecSmrg    }
90005b261ecSmrg    return;
90105b261ecSmrg}
902