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