XKBMAlloc.c revision 61b2299d
11ab64890Smrg/* $Xorg: XKBMAlloc.c,v 1.4 2000/08/17 19:45:02 cpqbld Exp $ */
21ab64890Smrg/************************************************************
31ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
41ab64890Smrg
51ab64890SmrgPermission to use, copy, modify, and distribute this
61ab64890Smrgsoftware and its documentation for any purpose and without
71ab64890Smrgfee is hereby granted, provided that the above copyright
81ab64890Smrgnotice appear in all copies and that both that copyright
91ab64890Smrgnotice and this permission notice appear in supporting
1061b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1161b2299dSmrgused in advertising or publicity pertaining to distribution
121ab64890Smrgof the software without specific prior written permission.
1361b2299dSmrgSilicon Graphics makes no representation about the suitability
141ab64890Smrgof this software for any purpose. It is provided "as is"
151ab64890Smrgwithout any express or implied warranty.
161ab64890Smrg
1761b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1861b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
191ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
2061b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2161b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2261b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
231ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
241ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
251ab64890Smrg
261ab64890Smrg********************************************************/
271ab64890Smrg/* $XFree86: xc/lib/X11/XKBMAlloc.c,v 3.11 2001/01/17 19:41:48 dawes Exp $ */
281ab64890Smrg
291ab64890Smrg#ifdef HAVE_DIX_CONFIG_H
301ab64890Smrg#include <dix-config.h>
311ab64890Smrg#elif defined(HAVE_CONFIG_H)
321ab64890Smrg#include <config.h>
331ab64890Smrg#endif
341ab64890Smrg
351ab64890Smrg#ifndef XKB_IN_SERVER
361ab64890Smrg
371ab64890Smrg#include <stdio.h>
381ab64890Smrg#define NEED_REPLIES
391ab64890Smrg#define NEED_EVENTS
401ab64890Smrg#include "Xlibint.h"
411ab64890Smrg#include <X11/extensions/XKBproto.h>
421ab64890Smrg#include <X11/keysym.h>
431ab64890Smrg#include "XKBlibint.h"
441ab64890Smrg
4561b2299dSmrg#else
461ab64890Smrg
471ab64890Smrg#include <stdio.h>
481ab64890Smrg#include <X11/X.h>
491ab64890Smrg#define	NEED_EVENTS
501ab64890Smrg#define	NEED_REPLIES
511ab64890Smrg#include <X11/Xproto.h>
521ab64890Smrg#include "misc.h"
531ab64890Smrg#include "inputstr.h"
541ab64890Smrg#include <X11/keysym.h>
551ab64890Smrg#define	XKBSRV_NEED_FILE_FUNCS
561ab64890Smrg#include <X11/extensions/XKBsrv.h>
571ab64890Smrg
581ab64890Smrg#endif /* XKB_IN_SERVER */
591ab64890Smrg
601ab64890Smrg/***====================================================================***/
611ab64890Smrg
621ab64890SmrgStatus
631ab64890SmrgXkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)
641ab64890Smrg{
651ab64890Smrgregister int	i;
661ab64890SmrgXkbClientMapPtr map;
671ab64890Smrg
681ab64890Smrg    if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
691ab64890Smrg	return BadValue;
701ab64890Smrg    if ((which&XkbKeySymsMask)&&
711ab64890Smrg	((!XkbIsLegalKeycode(xkb->min_key_code))||
721ab64890Smrg	 (!XkbIsLegalKeycode(xkb->max_key_code))||
731ab64890Smrg	 (xkb->max_key_code<xkb->min_key_code))) {
741ab64890Smrg#ifdef DEBUG
751ab64890Smrgfprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n",
761ab64890Smrg				xkb->min_key_code,xkb->max_key_code);
771ab64890Smrg#endif
781ab64890Smrg	return BadValue;
791ab64890Smrg    }
801ab64890Smrg
811ab64890Smrg    if (xkb->map==NULL) {
821ab64890Smrg	map= _XkbTypedCalloc(1,XkbClientMapRec);
831ab64890Smrg	if (map==NULL)
841ab64890Smrg	    return BadAlloc;
851ab64890Smrg	xkb->map= map;
861ab64890Smrg    }
871ab64890Smrg    else map= xkb->map;
881ab64890Smrg
891ab64890Smrg    if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
901ab64890Smrg	if (map->types==NULL) {
911ab64890Smrg	    map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec);
921ab64890Smrg	    if (map->types==NULL)
931ab64890Smrg		return BadAlloc;
941ab64890Smrg	    map->num_types= 0;
951ab64890Smrg	    map->size_types= nTotalTypes;
961ab64890Smrg	}
971ab64890Smrg	else if (map->size_types<nTotalTypes) {
981ab64890Smrg	    XkbKeyTypeRec *prev_types = map->types;
991ab64890Smrg
1001ab64890Smrg	    map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec);
1011ab64890Smrg	    if (map->types==NULL) {
1021ab64890Smrg		_XkbFree(prev_types);
1031ab64890Smrg		map->num_types= map->size_types= 0;
1041ab64890Smrg		return BadAlloc;
1051ab64890Smrg	    }
1061ab64890Smrg	    map->size_types= nTotalTypes;
10761b2299dSmrg	    bzero(&map->types[map->num_types],
1081ab64890Smrg		  ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
1091ab64890Smrg	}
1101ab64890Smrg    }
1111ab64890Smrg    if (which&XkbKeySymsMask) {
1121ab64890Smrg	int nKeys= XkbNumKeys(xkb);
1131ab64890Smrg	if (map->syms==NULL) {
1141ab64890Smrg	    map->size_syms= (nKeys*15)/10;
1151ab64890Smrg	    map->syms= _XkbTypedCalloc(map->size_syms,KeySym);
1161ab64890Smrg	    if (!map->syms) {
1171ab64890Smrg		map->size_syms= 0;
1181ab64890Smrg		return BadAlloc;
1191ab64890Smrg	    }
1201ab64890Smrg	    map->num_syms= 1;
1211ab64890Smrg	    map->syms[0]= NoSymbol;
1221ab64890Smrg	}
1231ab64890Smrg	if (map->key_sym_map==NULL) {
1241ab64890Smrg	    i= xkb->max_key_code+1;
1251ab64890Smrg	    map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec);
1261ab64890Smrg	    if (map->key_sym_map==NULL)
1271ab64890Smrg		return BadAlloc;
1281ab64890Smrg	}
1291ab64890Smrg    }
1301ab64890Smrg    if (which&XkbModifierMapMask) {
1311ab64890Smrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
1321ab64890Smrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
1331ab64890Smrg	    (xkb->max_key_code<xkb->min_key_code))
1341ab64890Smrg	    return BadMatch;
1351ab64890Smrg	if (map->modmap==NULL) {
1361ab64890Smrg	    i= xkb->max_key_code+1;
1371ab64890Smrg	    map->modmap= _XkbTypedCalloc(i,unsigned char);
1381ab64890Smrg	    if (map->modmap==NULL)
1391ab64890Smrg		return BadAlloc;
1401ab64890Smrg	}
1411ab64890Smrg    }
1421ab64890Smrg    return Success;
1431ab64890Smrg}
1441ab64890Smrg
1451ab64890SmrgStatus
1461ab64890SmrgXkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)
1471ab64890Smrg{
1481ab64890Smrgregister int	i;
1491ab64890SmrgXkbServerMapPtr map;
1501ab64890Smrg
1511ab64890Smrg    if (xkb==NULL)
1521ab64890Smrg	return BadMatch;
1531ab64890Smrg    if (xkb->server==NULL) {
1541ab64890Smrg	map= _XkbTypedCalloc(1,XkbServerMapRec);
1551ab64890Smrg	if (map==NULL)
1561ab64890Smrg	    return BadAlloc;
1571ab64890Smrg	for (i=0;i<XkbNumVirtualMods;i++) {
1581ab64890Smrg	    map->vmods[i]= XkbNoModifierMask;
1591ab64890Smrg	}
1601ab64890Smrg	xkb->server= map;
1611ab64890Smrg    }
1621ab64890Smrg    else map= xkb->server;
1631ab64890Smrg    if (which&XkbExplicitComponentsMask) {
1641ab64890Smrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
1651ab64890Smrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
1661ab64890Smrg	    (xkb->max_key_code<xkb->min_key_code))
1671ab64890Smrg	    return BadMatch;
1681ab64890Smrg	if (map->explicit==NULL) {
1691ab64890Smrg	    i= xkb->max_key_code+1;
1701ab64890Smrg	    map->explicit= _XkbTypedCalloc(i,unsigned char);
1711ab64890Smrg	    if (map->explicit==NULL)
1721ab64890Smrg		return BadAlloc;
1731ab64890Smrg	}
1741ab64890Smrg    }
1751ab64890Smrg    if (which&XkbKeyActionsMask) {
1761ab64890Smrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
1771ab64890Smrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
1781ab64890Smrg	    (xkb->max_key_code<xkb->min_key_code))
1791ab64890Smrg	    return BadMatch;
1801ab64890Smrg        if (nNewActions<1)
1811ab64890Smrg	    nNewActions= 1;
1821ab64890Smrg	if (map->acts==NULL) {
1831ab64890Smrg	    map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction);
1841ab64890Smrg	    if (map->acts==NULL)
1851ab64890Smrg		return BadAlloc;
1861ab64890Smrg	    map->num_acts= 1;
1871ab64890Smrg	    map->size_acts= nNewActions+1;
1881ab64890Smrg	}
1891ab64890Smrg	else if ((map->size_acts-map->num_acts)<nNewActions) {
1901ab64890Smrg	    unsigned need;
1911ab64890Smrg	    XkbAction *prev_acts = map->acts;
1921ab64890Smrg	    need= map->num_acts+nNewActions;
1931ab64890Smrg	    map->acts= _XkbTypedRealloc(map->acts,need,XkbAction);
1941ab64890Smrg	    if (map->acts==NULL) {
1951ab64890Smrg		_XkbFree(prev_acts);
1961ab64890Smrg	        map->num_acts= map->size_acts= 0;
1971ab64890Smrg	        return BadAlloc;
1981ab64890Smrg	    }
1991ab64890Smrg	    map->size_acts= need;
20061b2299dSmrg	    bzero(&map->acts[map->num_acts],
2011ab64890Smrg		    ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
2021ab64890Smrg	}
2031ab64890Smrg	if (map->key_acts==NULL) {
2041ab64890Smrg	    i= xkb->max_key_code+1;
2051ab64890Smrg	    map->key_acts= _XkbTypedCalloc(i,unsigned short);
2061ab64890Smrg	    if (map->key_acts==NULL)
2071ab64890Smrg		return BadAlloc;
2081ab64890Smrg	}
2091ab64890Smrg    }
2101ab64890Smrg    if (which&XkbKeyBehaviorsMask) {
2111ab64890Smrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
2121ab64890Smrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
2131ab64890Smrg	    (xkb->max_key_code<xkb->min_key_code))
2141ab64890Smrg	    return BadMatch;
2151ab64890Smrg	if (map->behaviors==NULL) {
2161ab64890Smrg	    i= xkb->max_key_code+1;
2171ab64890Smrg	    map->behaviors= _XkbTypedCalloc(i,XkbBehavior);
2181ab64890Smrg	    if (map->behaviors==NULL)
2191ab64890Smrg		return BadAlloc;
2201ab64890Smrg	}
2211ab64890Smrg    }
2221ab64890Smrg    if (which&XkbVirtualModMapMask) {
2231ab64890Smrg	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
2241ab64890Smrg	    (!XkbIsLegalKeycode(xkb->max_key_code))||
2251ab64890Smrg	    (xkb->max_key_code<xkb->min_key_code))
2261ab64890Smrg	    return BadMatch;
2271ab64890Smrg	if (map->vmodmap==NULL) {
2281ab64890Smrg	    i= xkb->max_key_code+1;
2291ab64890Smrg	    map->vmodmap= _XkbTypedCalloc(i,unsigned short);
2301ab64890Smrg	    if (map->vmodmap==NULL)
2311ab64890Smrg		return BadAlloc;
2321ab64890Smrg	}
2331ab64890Smrg    }
2341ab64890Smrg    return Success;
2351ab64890Smrg}
2361ab64890Smrg
2371ab64890Smrg/***====================================================================***/
2381ab64890Smrg
2391ab64890SmrgStatus
2401ab64890SmrgXkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)
2411ab64890Smrg{
2421ab64890Smrg    if ((!from)||(!into))
2431ab64890Smrg	return BadMatch;
2441ab64890Smrg    if (into->map) {
2451ab64890Smrg	_XkbFree(into->map);
2461ab64890Smrg	into->map= NULL;
2471ab64890Smrg    }
2481ab64890Smrg    if (into->preserve) {
2491ab64890Smrg	_XkbFree(into->preserve);
2501ab64890Smrg	into->preserve= NULL;
2511ab64890Smrg    }
2521ab64890Smrg    if (into->level_names) {
2531ab64890Smrg	_XkbFree(into->level_names);
2541ab64890Smrg	into->level_names= NULL;
2551ab64890Smrg    }
2561ab64890Smrg    *into= *from;
2571ab64890Smrg    if ((from->map)&&(into->map_count>0)) {
2581ab64890Smrg	into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec);
2591ab64890Smrg	if (!into->map)
2601ab64890Smrg	    return BadAlloc;
2611ab64890Smrg	memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec));
2621ab64890Smrg    }
2631ab64890Smrg    if ((from->preserve)&&(into->map_count>0)) {
2641ab64890Smrg	into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec);
2651ab64890Smrg	if (!into->preserve)
2661ab64890Smrg	    return BadAlloc;
2671ab64890Smrg	memcpy(into->preserve,from->preserve,
2681ab64890Smrg				into->map_count*sizeof(XkbModsRec));
2691ab64890Smrg    }
2701ab64890Smrg    if ((from->level_names)&&(into->num_levels>0)) {
2711ab64890Smrg	into->level_names= _XkbTypedCalloc(into->num_levels,Atom);
2721ab64890Smrg	if (!into->level_names)
2731ab64890Smrg	    return BadAlloc;
2741ab64890Smrg	memcpy(into->level_names,from->level_names,
2751ab64890Smrg				 into->num_levels*sizeof(Atom));
2761ab64890Smrg    }
2771ab64890Smrg    return Success;
2781ab64890Smrg}
2791ab64890Smrg
2801ab64890SmrgStatus
2811ab64890SmrgXkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)
2821ab64890Smrg{
2831ab64890Smrgregister int i,rtrn;
2841ab64890Smrg
2851ab64890Smrg    if ((!from)||(!into)||(num_types<0))
2861ab64890Smrg	return BadMatch;
2871ab64890Smrg    for (i=0;i<num_types;i++) {
2881ab64890Smrg	if ((rtrn= XkbCopyKeyType(from++,into++))!=Success)
2891ab64890Smrg	    return rtrn;
2901ab64890Smrg    }
2911ab64890Smrg    return Success;
2921ab64890Smrg}
2931ab64890Smrg
2941ab64890SmrgXkbKeyTypePtr
2951ab64890SmrgXkbAddKeyType(	XkbDescPtr	xkb,
2961ab64890Smrg		Atom 		name,
2971ab64890Smrg		int 		map_count,
2981ab64890Smrg		Bool 		want_preserve,
2991ab64890Smrg		int		num_lvls)
3001ab64890Smrg{
3011ab64890Smrgregister int 	i;
3021ab64890Smrgunsigned	tmp;
3031ab64890SmrgXkbKeyTypePtr	type;
3041ab64890SmrgXkbClientMapPtr	map;
3051ab64890Smrg
3061ab64890Smrg    if ((!xkb)||(num_lvls<1))
3071ab64890Smrg	return NULL;
3081ab64890Smrg    map= xkb->map;
3091ab64890Smrg    if ((map)&&(map->types)) {
3101ab64890Smrg	for (i=0;i<map->num_types;i++) {
3111ab64890Smrg	    if (map->types[i].name==name) {
3121ab64890Smrg		Status status;
3131ab64890Smrg		status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
3141ab64890Smrg		return (status==Success?&map->types[i]:NULL);
3151ab64890Smrg	    }
3161ab64890Smrg	}
3171ab64890Smrg    }
3181ab64890Smrg    if ((!map)||(!map->types)||(!map->num_types<XkbNumRequiredTypes)) {
3191ab64890Smrg	tmp= XkbNumRequiredTypes+1;
3201ab64890Smrg	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,tmp)!=Success)
3211ab64890Smrg	    return NULL;
3221ab64890Smrg        if (!map)
3231ab64890Smrg            map = xkb->map;
3241ab64890Smrg	tmp= 0;
3251ab64890Smrg	if (map->num_types<=XkbKeypadIndex)
3261ab64890Smrg	    tmp|= XkbKeypadMask;
3271ab64890Smrg	if (map->num_types<=XkbAlphabeticIndex)
3281ab64890Smrg	    tmp|= XkbAlphabeticMask;
3291ab64890Smrg	if (map->num_types<=XkbTwoLevelIndex)
3301ab64890Smrg	    tmp|= XkbTwoLevelMask;
3311ab64890Smrg	if (map->num_types<=XkbOneLevelIndex)
3321ab64890Smrg	    tmp|= XkbOneLevelMask;
3331ab64890Smrg	if (XkbInitCanonicalKeyTypes(xkb,tmp,XkbNoModifier)==Success) {
3341ab64890Smrg	    for (i=0;i<map->num_types;i++) {
3351ab64890Smrg		Status status;
3361ab64890Smrg		if (map->types[i].name!=name)
3371ab64890Smrg		    continue;
3381ab64890Smrg		status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
3391ab64890Smrg		return (status==Success?&map->types[i]:NULL);
3401ab64890Smrg	    }
3411ab64890Smrg	}
3421ab64890Smrg    }
3431ab64890Smrg    if ((map->num_types<=map->size_types)&&
3441ab64890Smrg	(XkbAllocClientMap(xkb,XkbKeyTypesMask,map->num_types+1)!=Success)) {
3451ab64890Smrg	return NULL;
3461ab64890Smrg    }
3471ab64890Smrg    type= &map->types[map->num_types];
3481ab64890Smrg    map->num_types++;
3491ab64890Smrg    bzero((char *)type,sizeof(XkbKeyTypeRec));
3501ab64890Smrg    type->num_levels=	num_lvls;
3511ab64890Smrg    type->map_count=	map_count;
3521ab64890Smrg    type->name=		name;
3531ab64890Smrg    if (map_count>0) {
3541ab64890Smrg	type->map=	_XkbTypedCalloc(map_count,XkbKTMapEntryRec);
3551ab64890Smrg	if (!type->map) {
3561ab64890Smrg	    map->num_types--;
3571ab64890Smrg	    return NULL;
3581ab64890Smrg	}
3591ab64890Smrg	if (want_preserve) {
3601ab64890Smrg	    type->preserve=	_XkbTypedCalloc(map_count,XkbModsRec);
3611ab64890Smrg	    if (!type->preserve) {
3621ab64890Smrg		_XkbFree(type->map);
3631ab64890Smrg		map->num_types--;
3641ab64890Smrg		return NULL;
3651ab64890Smrg	    }
3661ab64890Smrg	}
3671ab64890Smrg    }
3681ab64890Smrg    return type;
3691ab64890Smrg}
3701ab64890Smrg
3711ab64890SmrgStatus
3721ab64890SmrgXkbResizeKeyType(	XkbDescPtr	xkb,
3731ab64890Smrg			int		type_ndx,
3741ab64890Smrg			int		map_count,
3751ab64890Smrg			Bool		want_preserve,
3761ab64890Smrg			int		new_num_lvls)
3771ab64890Smrg{
3781ab64890SmrgXkbKeyTypePtr	type;
3791ab64890SmrgKeyCode		matchingKeys[XkbMaxKeyCount],nMatchingKeys;
3801ab64890Smrg
3811ab64890Smrg    if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)||
3821ab64890Smrg    							(new_num_lvls<1))
3831ab64890Smrg	return BadValue;
3841ab64890Smrg    switch (type_ndx) {
3851ab64890Smrg	case XkbOneLevelIndex:
3861ab64890Smrg	    if (new_num_lvls!=1)
3871ab64890Smrg		return BadMatch;
3881ab64890Smrg	    break;
3891ab64890Smrg	case XkbTwoLevelIndex:
3901ab64890Smrg	case XkbAlphabeticIndex:
3911ab64890Smrg	case XkbKeypadIndex:
3921ab64890Smrg	    if (new_num_lvls!=2)
3931ab64890Smrg		return BadMatch;
3941ab64890Smrg	    break;
3951ab64890Smrg    }
3961ab64890Smrg    type= &xkb->map->types[type_ndx];
3971ab64890Smrg    if (map_count==0) {
3981ab64890Smrg	if (type->map!=NULL)
3991ab64890Smrg	    _XkbFree(type->map);
4001ab64890Smrg	type->map= NULL;
4011ab64890Smrg	if (type->preserve!=NULL)
4021ab64890Smrg	    _XkbFree(type->preserve);
4031ab64890Smrg	type->preserve= NULL;
4041ab64890Smrg	type->map_count= 0;
4051ab64890Smrg    }
4061ab64890Smrg    else {
4071ab64890Smrg	XkbKTMapEntryRec *prev_map = type->map;
4081ab64890Smrg
4091ab64890Smrg	if ((map_count>type->map_count)||(type->map==NULL))
4101ab64890Smrg	    type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec);
4111ab64890Smrg	if (!type->map) {
41261b2299dSmrg	    if (prev_map)
4131ab64890Smrg		_XkbFree(prev_map);
4141ab64890Smrg	    return BadAlloc;
4151ab64890Smrg	}
4161ab64890Smrg	if (want_preserve) {
4171ab64890Smrg	    XkbModsRec *prev_preserve = type->preserve;
4181ab64890Smrg
4191ab64890Smrg	    if ((map_count>type->map_count)||(type->preserve==NULL)) {
4201ab64890Smrg		type->preserve= _XkbTypedRealloc(type->preserve,map_count,
4211ab64890Smrg	     						    XkbModsRec);
4221ab64890Smrg	    }
4231ab64890Smrg	    if (!type->preserve) {
42461b2299dSmrg		if (prev_preserve)
4251ab64890Smrg		    _XkbFree(prev_preserve);
4261ab64890Smrg		return BadAlloc;
4271ab64890Smrg	    }
4281ab64890Smrg	}
4291ab64890Smrg	else if (type->preserve!=NULL) {
4301ab64890Smrg	    _XkbFree(type->preserve);
4311ab64890Smrg	    type->preserve= NULL;
4321ab64890Smrg	}
4331ab64890Smrg	type->map_count= map_count;
4341ab64890Smrg    }
4351ab64890Smrg
4361ab64890Smrg    if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) {
4371ab64890Smrg	Atom * prev_level_names = type->level_names;
4381ab64890Smrg
4391ab64890Smrg	type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom);
4401ab64890Smrg	if (!type->level_names) {
44161b2299dSmrg	    if (prev_level_names)
4421ab64890Smrg		_XkbFree(prev_level_names);
4431ab64890Smrg	    return BadAlloc;
4441ab64890Smrg	}
4451ab64890Smrg    }
4461ab64890Smrg    /*
4471ab64890Smrg     * Here's the theory:
4481ab64890Smrg     *    If the width of the type changed, we might have to resize the symbol
4491ab64890Smrg     * maps for any keys that use the type for one or more groups.  This is
4501ab64890Smrg     * expensive, so we'll try to cull out any keys that are obviously okay:
4511ab64890Smrg     * In any case:
4521ab64890Smrg     *    - keys that have a group width <= the old width are okay (because
4531ab64890Smrg     *      they could not possibly have been associated with the old type)
4541ab64890Smrg     * If the key type increased in size:
4551ab64890Smrg     *    - keys that already have a group width >= to the new width are okay
4561ab64890Smrg     *    + keys that have a group width >= the old width but < the new width
4571ab64890Smrg     *      might have to be enlarged.
4581ab64890Smrg     * If the key type decreased in size:
4591ab64890Smrg     *    - keys that have a group width > the old width don't have to be
46061b2299dSmrg     *      resized (because they must have some other wider type associated
4611ab64890Smrg     *      with some group).
4621ab64890Smrg     *    + keys that have a group width == the old width might have to be
4631ab64890Smrg     *      shrunk.
4641ab64890Smrg     * The possibilities marked with '+' require us to examine the key types
4651ab64890Smrg     * associated with each group for the key.
4661ab64890Smrg     */
4671ab64890Smrg    bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode));
4681ab64890Smrg    nMatchingKeys= 0;
4691ab64890Smrg    if (new_num_lvls>type->num_levels) {
4701ab64890Smrg	int	 		nTotal;
4711ab64890Smrg	KeySym	*		newSyms;
4721ab64890Smrg	int			width,match,nResize;
4731ab64890Smrg	register int		i,g,nSyms;
4741ab64890Smrg
4751ab64890Smrg	nResize= 0;
4761ab64890Smrg	for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
4771ab64890Smrg	    width= XkbKeyGroupsWidth(xkb,i);
4781ab64890Smrg	    if (width<type->num_levels)
4791ab64890Smrg		continue;
4801ab64890Smrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
4811ab64890Smrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
4821ab64890Smrg		    matchingKeys[nMatchingKeys++]= i;
4831ab64890Smrg		    match= 1;
4841ab64890Smrg		}
4851ab64890Smrg	    }
4861ab64890Smrg	    if ((!match)||(width>=new_num_lvls))
4871ab64890Smrg		nTotal+= XkbKeyNumSyms(xkb,i);
4881ab64890Smrg	    else {
4891ab64890Smrg		nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
4901ab64890Smrg		nResize++;
4911ab64890Smrg	    }
4921ab64890Smrg	}
4931ab64890Smrg	if (nResize>0) {
4941ab64890Smrg	    int nextMatch;
4951ab64890Smrg	    xkb->map->size_syms= (nTotal*12)/10;
4961ab64890Smrg	    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
4971ab64890Smrg	    if (newSyms==NULL)
4981ab64890Smrg		return BadAlloc;
4991ab64890Smrg	    nextMatch= 0;
5001ab64890Smrg	    nSyms= 1;
5011ab64890Smrg	    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5021ab64890Smrg		if (matchingKeys[nextMatch]==i) {
5031ab64890Smrg		    KeySym *pOld;
5041ab64890Smrg		    nextMatch++;
5051ab64890Smrg		    width= XkbKeyGroupsWidth(xkb,i);
5061ab64890Smrg		    pOld= XkbKeySymsPtr(xkb,i);
5071ab64890Smrg		    for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
5081ab64890Smrg			memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g],
5091ab64890Smrg							width*sizeof(KeySym));
5101ab64890Smrg		    }
5111ab64890Smrg		    xkb->map->key_sym_map[i].offset= nSyms;
5121ab64890Smrg		    nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
5131ab64890Smrg		}
5141ab64890Smrg		else {
5151ab64890Smrg		    memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),
5161ab64890Smrg					XkbKeyNumSyms(xkb,i)*sizeof(KeySym));
5171ab64890Smrg		    xkb->map->key_sym_map[i].offset= nSyms;
5181ab64890Smrg		    nSyms+= XkbKeyNumSyms(xkb,i);
5191ab64890Smrg		}
5201ab64890Smrg	    }
5211ab64890Smrg	    type->num_levels= new_num_lvls;
5221ab64890Smrg	    _XkbFree(xkb->map->syms);
5231ab64890Smrg	    xkb->map->syms= newSyms;
5241ab64890Smrg	    xkb->map->num_syms= nSyms;
5251ab64890Smrg	    return Success;
5261ab64890Smrg	}
5271ab64890Smrg    }
5281ab64890Smrg    else if (new_num_lvls<type->num_levels) {
5291ab64890Smrg	int 		width,match;
5301ab64890Smrg	register int	g,i;
5311ab64890Smrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5321ab64890Smrg	    width= XkbKeyGroupsWidth(xkb,i);
5331ab64890Smrg	    if (width<type->num_levels)
5341ab64890Smrg		continue;
5351ab64890Smrg	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
5361ab64890Smrg		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
5371ab64890Smrg		    matchingKeys[nMatchingKeys++]= i;
5381ab64890Smrg		    match= 1;
5391ab64890Smrg		}
5401ab64890Smrg	    }
5411ab64890Smrg	}
5421ab64890Smrg    }
5431ab64890Smrg    if (nMatchingKeys>0) {
5441ab64890Smrg	int 		key,firstClear;
5451ab64890Smrg	register int	i,g;
5461ab64890Smrg	if (new_num_lvls>type->num_levels)
5471ab64890Smrg	     firstClear= type->num_levels;
5481ab64890Smrg	else firstClear= new_num_lvls;
5491ab64890Smrg	for (i=0;i<nMatchingKeys;i++) {
5501ab64890Smrg	    KeySym *	pSyms;
5511ab64890Smrg	    int		width,nClear;
5521ab64890Smrg
5531ab64890Smrg	    key= matchingKeys[i];
5541ab64890Smrg	    width= XkbKeyGroupsWidth(xkb,key);
5551ab64890Smrg	    nClear= width-firstClear;
5561ab64890Smrg	    pSyms= XkbKeySymsPtr(xkb,key);
5571ab64890Smrg	    for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) {
5581ab64890Smrg		if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) {
5591ab64890Smrg		    if (nClear>0)
5601ab64890Smrg			bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym));
5611ab64890Smrg		}
5621ab64890Smrg	    }
5631ab64890Smrg	}
5641ab64890Smrg    }
5651ab64890Smrg    type->num_levels= new_num_lvls;
5661ab64890Smrg    return Success;
5671ab64890Smrg}
5681ab64890Smrg
5691ab64890SmrgKeySym *
5701ab64890SmrgXkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)
5711ab64890Smrg{
5721ab64890Smrgregister int i,nSyms,nKeySyms;
5731ab64890Smrgunsigned nOldSyms;
5741ab64890SmrgKeySym	*newSyms;
5751ab64890Smrg
5761ab64890Smrg    if (needed==0) {
5771ab64890Smrg	xkb->map->key_sym_map[key].offset= 0;
5781ab64890Smrg	return xkb->map->syms;
5791ab64890Smrg    }
5801ab64890Smrg    nOldSyms= XkbKeyNumSyms(xkb,key);
5811ab64890Smrg    if (nOldSyms>=(unsigned)needed) {
5821ab64890Smrg	return XkbKeySymsPtr(xkb,key);
5831ab64890Smrg    }
5841ab64890Smrg    if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) {
5851ab64890Smrg	if (nOldSyms>0) {
5861ab64890Smrg	    memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key),
5871ab64890Smrg						nOldSyms*sizeof(KeySym));
5881ab64890Smrg	}
5891ab64890Smrg	if ((needed-nOldSyms)>0) {
5901ab64890Smrg	    bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)],
5911ab64890Smrg					(needed-nOldSyms)*sizeof(KeySym));
5921ab64890Smrg	}
5931ab64890Smrg	xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
5941ab64890Smrg	xkb->map->num_syms+= needed;
5951ab64890Smrg	return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
5961ab64890Smrg    }
5971ab64890Smrg    xkb->map->size_syms+= (needed>32?needed:32);
5981ab64890Smrg    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
5991ab64890Smrg    if (newSyms==NULL)
6001ab64890Smrg	return NULL;
6011ab64890Smrg    newSyms[0]= NoSymbol;
6021ab64890Smrg    nSyms = 1;
6031ab64890Smrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
6041ab64890Smrg	int nCopy;
6051ab64890Smrg
6061ab64890Smrg	nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
6071ab64890Smrg	if ((nKeySyms==0)&&(i!=key))
6081ab64890Smrg	    continue;
6091ab64890Smrg	if (i==key)
6101ab64890Smrg	    nKeySyms= needed;
6111ab64890Smrg	if (nCopy!=0)
6121ab64890Smrg	   memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym));
6131ab64890Smrg	if (nKeySyms>nCopy)
6141ab64890Smrg	    bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym));
6151ab64890Smrg	xkb->map->key_sym_map[i].offset = nSyms;
6161ab64890Smrg	nSyms+= nKeySyms;
6171ab64890Smrg    }
6181ab64890Smrg    _XkbFree(xkb->map->syms);
6191ab64890Smrg    xkb->map->syms = newSyms;
6201ab64890Smrg    xkb->map->num_syms = nSyms;
6211ab64890Smrg    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
6221ab64890Smrg}
6231ab64890Smrg
6241ab64890Smrgstatic unsigned
6251ab64890Smrg_ExtendRange(	unsigned int 	old_flags,
6261ab64890Smrg		unsigned int	flag,
6271ab64890Smrg		KeyCode		newKC,
6281ab64890Smrg		KeyCode *	old_min,
6291ab64890Smrg		unsigned char *	old_num)
6301ab64890Smrg{
6311ab64890Smrg    if ((old_flags&flag)==0) {
6321ab64890Smrg	old_flags|= flag;
6331ab64890Smrg	*old_min= newKC;
6341ab64890Smrg	*old_num= 1;
6351ab64890Smrg    }
6361ab64890Smrg    else {
6371ab64890Smrg	int	last= (*old_min)+(*old_num)-1;
6381ab64890Smrg	if (newKC<*old_min) {
6391ab64890Smrg	    *old_min= newKC;
6401ab64890Smrg	    *old_num= (last-newKC)+1;
6411ab64890Smrg	}
6421ab64890Smrg	else if (newKC>last) {
6431ab64890Smrg	    *old_num= (newKC-(*old_min))+1;
6441ab64890Smrg	}
6451ab64890Smrg    }
6461ab64890Smrg    return old_flags;
6471ab64890Smrg}
6481ab64890Smrg
6491ab64890SmrgStatus
6501ab64890SmrgXkbChangeKeycodeRange(	XkbDescPtr	xkb,
6511ab64890Smrg			int 		minKC,
6521ab64890Smrg			int 		maxKC,
6531ab64890Smrg			XkbChangesPtr	changes)
6541ab64890Smrg{
6551ab64890Smrgint	tmp;
6561ab64890Smrg
6571ab64890Smrg    if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode))
6581ab64890Smrg	return BadValue;
6591ab64890Smrg    if (minKC>maxKC)
6601ab64890Smrg	return BadMatch;
6611ab64890Smrg    if (minKC<xkb->min_key_code) {
6621ab64890Smrg	if (changes)
6631ab64890Smrg	    changes->map.min_key_code= minKC;
6641ab64890Smrg	tmp= xkb->min_key_code-minKC;
6651ab64890Smrg	if (xkb->map)  {
6661ab64890Smrg	    if (xkb->map->key_sym_map) {
6671ab64890Smrg		bzero((char *)&xkb->map->key_sym_map[minKC],
6681ab64890Smrg					tmp*sizeof(XkbSymMapRec));
6691ab64890Smrg		if (changes) {
6701ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
6711ab64890Smrg		    				XkbKeySymsMask,minKC,
6721ab64890Smrg	    					&changes->map.first_key_sym,
6731ab64890Smrg	    					&changes->map.num_key_syms);
6741ab64890Smrg		}
6751ab64890Smrg	    }
6761ab64890Smrg	    if (xkb->map->modmap) {
6771ab64890Smrg		bzero((char *)&xkb->map->modmap[minKC],tmp);
6781ab64890Smrg		if (changes) {
6791ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
6801ab64890Smrg		    				XkbModifierMapMask,minKC,
6811ab64890Smrg	    					&changes->map.first_modmap_key,
6821ab64890Smrg	    					&changes->map.num_modmap_keys);
6831ab64890Smrg		}
6841ab64890Smrg	    }
6851ab64890Smrg	}
6861ab64890Smrg	if (xkb->server) {
6871ab64890Smrg	    if (xkb->server->behaviors) {
6881ab64890Smrg		bzero((char *)&xkb->server->behaviors[minKC],
6891ab64890Smrg						tmp*sizeof(XkbBehavior));
6901ab64890Smrg		if (changes) {
6911ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
6921ab64890Smrg		    			XkbKeyBehaviorsMask,minKC,
6931ab64890Smrg    					&changes->map.first_key_behavior,
6941ab64890Smrg    					&changes->map.num_key_behaviors);
6951ab64890Smrg		}
6961ab64890Smrg	    }
6971ab64890Smrg	    if (xkb->server->key_acts) {
6981ab64890Smrg		bzero((char *)&xkb->server->key_acts[minKC],
6991ab64890Smrg						tmp*sizeof(unsigned short));
7001ab64890Smrg		if (changes) {
7011ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
7021ab64890Smrg		    			XkbKeyActionsMask,minKC,
7031ab64890Smrg    					&changes->map.first_key_act,
7041ab64890Smrg    					&changes->map.num_key_acts);
7051ab64890Smrg		}
7061ab64890Smrg	    }
7071ab64890Smrg	    if (xkb->server->vmodmap) {
7081ab64890Smrg		bzero((char *)&xkb->server->vmodmap[minKC],
7091ab64890Smrg						tmp*sizeof(unsigned short));
7101ab64890Smrg		if (changes) {
7111ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
7121ab64890Smrg		    			XkbVirtualModMapMask,minKC,
7131ab64890Smrg		    			&changes->map.first_modmap_key,
7141ab64890Smrg    					&changes->map.num_vmodmap_keys);
7151ab64890Smrg		}
7161ab64890Smrg	    }
7171ab64890Smrg	}
7181ab64890Smrg	if ((xkb->names)&&(xkb->names->keys)) {
7191ab64890Smrg	    bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec));
7201ab64890Smrg	    if (changes) {
7211ab64890Smrg		changes->names.changed= _ExtendRange(changes->names.changed,
7221ab64890Smrg					XkbKeyNamesMask,minKC,
7231ab64890Smrg					&changes->names.first_key,
7241ab64890Smrg    					&changes->names.num_keys);
7251ab64890Smrg	    }
7261ab64890Smrg	}
7271ab64890Smrg	xkb->min_key_code= minKC;
7281ab64890Smrg    }
7291ab64890Smrg    if (maxKC>xkb->max_key_code) {
7301ab64890Smrg	if (changes)
7311ab64890Smrg	    changes->map.max_key_code= maxKC;
7321ab64890Smrg	tmp= maxKC-xkb->max_key_code;
7331ab64890Smrg	if (xkb->map)  {
7341ab64890Smrg	    if (xkb->map->key_sym_map) {
7351ab64890Smrg		XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
7361ab64890Smrg
7371ab64890Smrg		xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map,
7381ab64890Smrg						(maxKC+1),XkbSymMapRec);
7391ab64890Smrg		if (!xkb->map->key_sym_map) {
7401ab64890Smrg		    _XkbFree(prev_key_sym_map);
7411ab64890Smrg		    return BadAlloc;
7421ab64890Smrg		}
7431ab64890Smrg		bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
7441ab64890Smrg					tmp*sizeof(XkbSymMapRec));
7451ab64890Smrg		if (changes) {
7461ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
7471ab64890Smrg		    				XkbKeySymsMask,maxKC,
7481ab64890Smrg	    					&changes->map.first_key_sym,
7491ab64890Smrg	    					&changes->map.num_key_syms);
7501ab64890Smrg		}
7511ab64890Smrg	    }
7521ab64890Smrg	    if (xkb->map->modmap) {
7531ab64890Smrg		unsigned char *prev_modmap = xkb->map->modmap;
7541ab64890Smrg
7551ab64890Smrg		xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap,
7561ab64890Smrg						(maxKC+1),unsigned char);
7571ab64890Smrg		if (!xkb->map->modmap) {
7581ab64890Smrg		    _XkbFree(prev_modmap);
7591ab64890Smrg		    return BadAlloc;
7601ab64890Smrg		}
7611ab64890Smrg		bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
7621ab64890Smrg		if (changes) {
7631ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
7641ab64890Smrg		    				XkbModifierMapMask,maxKC,
7651ab64890Smrg	    					&changes->map.first_modmap_key,
7661ab64890Smrg	    					&changes->map.num_modmap_keys);
7671ab64890Smrg		}
7681ab64890Smrg	    }
7691ab64890Smrg	}
7701ab64890Smrg	if (xkb->server) {
7711ab64890Smrg	    if (xkb->server->behaviors) {
7721ab64890Smrg		XkbBehavior *prev_behaviors = xkb->server->behaviors;
7731ab64890Smrg
7741ab64890Smrg		xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors,
7751ab64890Smrg						(maxKC+1),XkbBehavior);
7761ab64890Smrg		if (!xkb->server->behaviors) {
7771ab64890Smrg		    _XkbFree(prev_behaviors);
7781ab64890Smrg		    return BadAlloc;
7791ab64890Smrg		}
7801ab64890Smrg		bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
7811ab64890Smrg						tmp*sizeof(XkbBehavior));
7821ab64890Smrg		if (changes) {
7831ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
7841ab64890Smrg		    			XkbKeyBehaviorsMask,maxKC,
7851ab64890Smrg    					&changes->map.first_key_behavior,
7861ab64890Smrg    					&changes->map.num_key_behaviors);
7871ab64890Smrg		}
7881ab64890Smrg	    }
7891ab64890Smrg	    if (xkb->server->key_acts) {
7901ab64890Smrg		unsigned short *prev_key_acts = xkb->server->key_acts;
7911ab64890Smrg
7921ab64890Smrg		xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts,
7931ab64890Smrg						(maxKC+1),unsigned short);
7941ab64890Smrg		if (!xkb->server->key_acts) {
7951ab64890Smrg		    _XkbFree(prev_key_acts);
7961ab64890Smrg		    return BadAlloc;
7971ab64890Smrg		}
7981ab64890Smrg		bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
7991ab64890Smrg						tmp*sizeof(unsigned short));
8001ab64890Smrg		if (changes) {
8011ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
8021ab64890Smrg		    			XkbKeyActionsMask,maxKC,
8031ab64890Smrg    					&changes->map.first_key_act,
8041ab64890Smrg    					&changes->map.num_key_acts);
8051ab64890Smrg		}
8061ab64890Smrg	    }
8071ab64890Smrg	    if (xkb->server->vmodmap) {
8081ab64890Smrg		unsigned short *prev_vmodmap = xkb->server->vmodmap;
8091ab64890Smrg
8101ab64890Smrg		xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap,
8111ab64890Smrg						(maxKC+1),unsigned short);
8121ab64890Smrg		if (!xkb->server->vmodmap) {
8131ab64890Smrg		    _XkbFree(prev_vmodmap);
8141ab64890Smrg		    return BadAlloc;
8151ab64890Smrg		}
8161ab64890Smrg		bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
8171ab64890Smrg						tmp*sizeof(unsigned short));
8181ab64890Smrg		if (changes) {
8191ab64890Smrg		    changes->map.changed= _ExtendRange(changes->map.changed,
8201ab64890Smrg		    			XkbVirtualModMapMask,maxKC,
8211ab64890Smrg		    			&changes->map.first_modmap_key,
8221ab64890Smrg    					&changes->map.num_vmodmap_keys);
8231ab64890Smrg		}
8241ab64890Smrg	    }
8251ab64890Smrg	}
8261ab64890Smrg	if ((xkb->names)&&(xkb->names->keys)) {
8271ab64890Smrg	    XkbKeyNameRec *prev_keys = xkb->names->keys;
8281ab64890Smrg
8291ab64890Smrg	    xkb->names->keys= _XkbTypedRealloc(xkb->names->keys,
8301ab64890Smrg	    					(maxKC+1),XkbKeyNameRec);
8311ab64890Smrg	    if (!xkb->names->keys) {
8321ab64890Smrg		_XkbFree(prev_keys);
8331ab64890Smrg		return BadAlloc;
8341ab64890Smrg	    }
8351ab64890Smrg	    bzero((char *)&xkb->names->keys[xkb->max_key_code],
8361ab64890Smrg	    					tmp*sizeof(XkbKeyNameRec));
8371ab64890Smrg	    if (changes) {
8381ab64890Smrg		changes->names.changed= _ExtendRange(changes->names.changed,
8391ab64890Smrg					XkbKeyNamesMask,maxKC,
8401ab64890Smrg					&changes->names.first_key,
8411ab64890Smrg    					&changes->names.num_keys);
8421ab64890Smrg	    }
8431ab64890Smrg	}
8441ab64890Smrg	xkb->max_key_code= maxKC;
8451ab64890Smrg    }
8461ab64890Smrg    return Success;
8471ab64890Smrg}
8481ab64890Smrg
8491ab64890SmrgXkbAction *
8501ab64890SmrgXkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)
8511ab64890Smrg{
8521ab64890Smrgregister int i,nActs;
8531ab64890SmrgXkbAction *newActs;
8541ab64890Smrg
8551ab64890Smrg    if (needed==0) {
8561ab64890Smrg	xkb->server->key_acts[key]= 0;
8571ab64890Smrg	return NULL;
8581ab64890Smrg    }
8591ab64890Smrg    if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed))
8601ab64890Smrg	return XkbKeyActionsPtr(xkb,key);
8611ab64890Smrg    if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) {
8621ab64890Smrg	xkb->server->key_acts[key]= xkb->server->num_acts;
8631ab64890Smrg	xkb->server->num_acts+= needed;
8641ab64890Smrg	return &xkb->server->acts[xkb->server->key_acts[key]];
8651ab64890Smrg    }
8661ab64890Smrg    xkb->server->size_acts= xkb->server->num_acts+needed+8;
8671ab64890Smrg    newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction);
8681ab64890Smrg    if (newActs==NULL)
8691ab64890Smrg	return NULL;
8701ab64890Smrg    newActs[0].type = XkbSA_NoAction;
8711ab64890Smrg    nActs = 1;
8721ab64890Smrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
8731ab64890Smrg	int nKeyActs,nCopy;
8741ab64890Smrg
8751ab64890Smrg	if ((xkb->server->key_acts[i]==0)&&(i!=key))
8761ab64890Smrg	    continue;
8771ab64890Smrg
8781ab64890Smrg	nCopy= nKeyActs= XkbKeyNumActions(xkb,i);
8791ab64890Smrg	if (i==key) {
8801ab64890Smrg	    nKeyActs= needed;
8811ab64890Smrg	    if (needed<nCopy)
8821ab64890Smrg		nCopy= needed;
8831ab64890Smrg	}
8841ab64890Smrg
8851ab64890Smrg	if (nCopy>0)
8861ab64890Smrg	    memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i),
8871ab64890Smrg						nCopy*sizeof(XkbAction));
8881ab64890Smrg	if (nCopy<nKeyActs)
8891ab64890Smrg	    bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction));
8901ab64890Smrg	xkb->server->key_acts[i]= nActs;
8911ab64890Smrg	nActs+= nKeyActs;
8921ab64890Smrg    }
8931ab64890Smrg    _XkbFree(xkb->server->acts);
8941ab64890Smrg    xkb->server->acts = newActs;
8951ab64890Smrg    xkb->server->num_acts= nActs;
8961ab64890Smrg    return &xkb->server->acts[xkb->server->key_acts[key]];
8971ab64890Smrg}
8981ab64890Smrg
8991ab64890Smrgvoid
9001ab64890SmrgXkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
9011ab64890Smrg{
9021ab64890SmrgXkbClientMapPtr	map;
9031ab64890Smrg
9041ab64890Smrg    if ((xkb==NULL)||(xkb->map==NULL))
9051ab64890Smrg	return;
9061ab64890Smrg    if (freeMap)
9071ab64890Smrg	what= XkbAllClientInfoMask;
9081ab64890Smrg    map= xkb->map;
9091ab64890Smrg    if (what&XkbKeyTypesMask) {
9101ab64890Smrg	if (map->types!=NULL) {
9111ab64890Smrg	    if (map->num_types>0) {
9121ab64890Smrg		register int 	i;
9131ab64890Smrg		XkbKeyTypePtr	type;
9141ab64890Smrg		for (i=0,type=map->types;i<map->num_types;i++,type++) {
9151ab64890Smrg		    if (type->map!=NULL) {
9161ab64890Smrg			_XkbFree(type->map);
9171ab64890Smrg			type->map= NULL;
9181ab64890Smrg		    }
9191ab64890Smrg		    if (type->preserve!=NULL) {
9201ab64890Smrg			_XkbFree(type->preserve);
9211ab64890Smrg			type->preserve= NULL;
9221ab64890Smrg		    }
9231ab64890Smrg		    type->map_count= 0;
9241ab64890Smrg		    if (type->level_names!=NULL) {
9251ab64890Smrg			_XkbFree(type->level_names);
9261ab64890Smrg			type->level_names= NULL;
9271ab64890Smrg		    }
9281ab64890Smrg		}
9291ab64890Smrg	    }
9301ab64890Smrg	    _XkbFree(map->types);
9311ab64890Smrg	    map->num_types= map->size_types= 0;
9321ab64890Smrg	    map->types= NULL;
9331ab64890Smrg	}
9341ab64890Smrg    }
9351ab64890Smrg    if (what&XkbKeySymsMask) {
9361ab64890Smrg	if (map->key_sym_map!=NULL) {
9371ab64890Smrg	    _XkbFree(map->key_sym_map);
9381ab64890Smrg	    map->key_sym_map= NULL;
9391ab64890Smrg	}
9401ab64890Smrg	if (map->syms!=NULL) {
9411ab64890Smrg	    _XkbFree(map->syms);
9421ab64890Smrg	    map->size_syms= map->num_syms= 0;
9431ab64890Smrg	    map->syms= NULL;
9441ab64890Smrg	}
9451ab64890Smrg    }
9461ab64890Smrg    if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
9471ab64890Smrg	_XkbFree(map->modmap);
9481ab64890Smrg	map->modmap= NULL;
9491ab64890Smrg    }
9501ab64890Smrg    if (freeMap) {
9511ab64890Smrg	_XkbFree(xkb->map);
9521ab64890Smrg	xkb->map= NULL;
9531ab64890Smrg    }
9541ab64890Smrg    return;
9551ab64890Smrg}
9561ab64890Smrg
9571ab64890Smrgvoid
9581ab64890SmrgXkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
9591ab64890Smrg{
9601ab64890SmrgXkbServerMapPtr	map;
9611ab64890Smrg
9621ab64890Smrg    if ((xkb==NULL)||(xkb->server==NULL))
9631ab64890Smrg	return;
9641ab64890Smrg    if (freeMap)
9651ab64890Smrg	what= XkbAllServerInfoMask;
9661ab64890Smrg    map= xkb->server;
9671ab64890Smrg    if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
9681ab64890Smrg	_XkbFree(map->explicit);
9691ab64890Smrg	map->explicit= NULL;
9701ab64890Smrg    }
9711ab64890Smrg    if (what&XkbKeyActionsMask) {
9721ab64890Smrg	if (map->key_acts!=NULL) {
9731ab64890Smrg	    _XkbFree(map->key_acts);
9741ab64890Smrg	    map->key_acts= NULL;
9751ab64890Smrg	}
9761ab64890Smrg	if (map->acts!=NULL) {
9771ab64890Smrg	    _XkbFree(map->acts);
9781ab64890Smrg	    map->num_acts= map->size_acts= 0;
9791ab64890Smrg	    map->acts= NULL;
9801ab64890Smrg	}
9811ab64890Smrg    }
9821ab64890Smrg    if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
9831ab64890Smrg	_XkbFree(map->behaviors);
9841ab64890Smrg	map->behaviors= NULL;
9851ab64890Smrg    }
9861ab64890Smrg    if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
9871ab64890Smrg	_XkbFree(map->vmodmap);
9881ab64890Smrg	map->vmodmap= NULL;
9891ab64890Smrg    }
9901ab64890Smrg
9911ab64890Smrg    if (freeMap) {
9921ab64890Smrg	_XkbFree(xkb->server);
9931ab64890Smrg	xkb->server= NULL;
9941ab64890Smrg    }
9951ab64890Smrg    return;
9961ab64890Smrg}
997