From f0c0ff41bdb9b4f83703548f2a4076317115aeb3 Mon Sep 17 00:00:00 2001
From: Ulrich Sibiller <uli42@gmx.de>
Date: Wed, 21 Sep 2016 20:54:53 +0200
Subject: copy files from libX11 to xserver dir

Before those files where symlinked in the makefile. While trying to
upgrade libX11 to 1.3.4 it turned out that the symlinked did not work
in the xserver anymore.

Upstream has copies of those files, too.
---
 nx-X11/programs/Xserver/xkb/Imakefile   |    6 -
 nx-X11/programs/Xserver/xkb/XKBAlloc.c  |  498 +++++++++++++++
 nx-X11/programs/Xserver/xkb/XKBGAlloc.c | 1016 ++++++++++++++++++++++++++++++
 nx-X11/programs/Xserver/xkb/XKBMAlloc.c | 1017 +++++++++++++++++++++++++++++++
 nx-X11/programs/Xserver/xkb/XKBMisc.c   |  975 +++++++++++++++++++++++++++++
 5 files changed, 3506 insertions(+), 6 deletions(-)
 create mode 100644 nx-X11/programs/Xserver/xkb/XKBAlloc.c
 create mode 100644 nx-X11/programs/Xserver/xkb/XKBGAlloc.c
 create mode 100644 nx-X11/programs/Xserver/xkb/XKBMAlloc.c
 create mode 100644 nx-X11/programs/Xserver/xkb/XKBMisc.c

diff --git a/nx-X11/programs/Xserver/xkb/Imakefile b/nx-X11/programs/Xserver/xkb/Imakefile
index 6a949807e..6d57cda09 100644
--- a/nx-X11/programs/Xserver/xkb/Imakefile
+++ b/nx-X11/programs/Xserver/xkb/Imakefile
@@ -72,12 +72,6 @@ AllTarget($(XF86_OBJS))
 
 SpecialCObjectRule(xkbInit,$(ICONFIGFILES),$(XKB_DEFINES))
 
-XCOMM avoid clash between XKBMisc.c and xkbmisc.c on NT
-LinkSourceFile(XKBMisc.c,$(XLIBSRC))
-LinkSourceFile(XKBMAlloc.c,$(XLIBSRC))
-LinkSourceFile(XKBAlloc.c,$(XLIBSRC))
-LinkSourceFile(XKBGAlloc.c,$(XLIBSRC))
-
 LinkSourceFile(modinit.h,../Xext/extmod)
 
 #if BuildLibraries
diff --git a/nx-X11/programs/Xserver/xkb/XKBAlloc.c b/nx-X11/programs/Xserver/xkb/XKBAlloc.c
new file mode 100644
index 000000000..826bf6ed8
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/XKBAlloc.c
@@ -0,0 +1,498 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be 
+used in advertising or publicity pertaining to distribution 
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability 
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#ifndef XKB_IN_SERVER
+
+#include <stdio.h>
+#include "Xlibint.h"
+#include "XKBlibint.h"
+#include <nx-X11/extensions/XKBgeom.h>
+#include <nx-X11/extensions/XKBproto.h>
+#include "XKBlibint.h"
+
+#else 
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <nx-X11/extensions/XKBsrv.h>
+#include <nx-X11/extensions/XKBgeom.h>
+
+#endif /* XKB_IN_SERVER */
+
+/***===================================================================***/
+
+/*ARGSUSED*/
+Status
+XkbAllocCompatMap(XkbDescPtr xkb,unsigned which,unsigned nSI)
+{
+XkbCompatMapPtr	compat;
+XkbSymInterpretRec *prev_interpret;
+
+    if (!xkb)
+	return BadMatch;
+    if (xkb->compat) {
+	if (xkb->compat->size_si>=nSI)
+	    return Success;
+	compat= xkb->compat;
+	compat->size_si= nSI;
+	if (compat->sym_interpret==NULL)
+	    compat->num_si= 0;
+	prev_interpret = compat->sym_interpret;
+	compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
+						     nSI,XkbSymInterpretRec);
+	if (compat->sym_interpret==NULL) {
+	    _XkbFree(prev_interpret);
+	    compat->size_si= compat->num_si= 0;
+	    return BadAlloc;
+	}
+	if (compat->num_si!=0) {
+	    _XkbClearElems(compat->sym_interpret,compat->num_si,
+					compat->size_si-1,XkbSymInterpretRec);
+	}
+	return Success;
+    }
+    compat= _XkbTypedCalloc(1,XkbCompatMapRec);
+    if (compat==NULL)
+	return BadAlloc;
+    if (nSI>0) {
+	compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec);
+	if (!compat->sym_interpret) {
+	    _XkbFree(compat);
+	    return BadAlloc;
+	}
+    }
+    compat->size_si= nSI;
+    compat->num_si= 0;
+    bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
+    xkb->compat= compat;
+    return Success;
+}
+
+
+void
+XkbFreeCompatMap(XkbDescPtr xkb,unsigned which,Bool freeMap)
+{
+register XkbCompatMapPtr compat;
+
+    if ((xkb==NULL)||(xkb->compat==NULL))
+	return;
+    compat= xkb->compat;
+    if (freeMap)
+	which= XkbAllCompatMask;
+    if (which&XkbGroupCompatMask)
+	bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec));
+    if (which&XkbSymInterpMask) {
+	if ((compat->sym_interpret)&&(compat->size_si>0))
+	    _XkbFree(compat->sym_interpret);
+	compat->size_si= compat->num_si= 0;
+	compat->sym_interpret= NULL;
+    }
+    if (freeMap) {
+	_XkbFree(compat);
+	xkb->compat= NULL;
+    }
+    return;
+}
+
+/***===================================================================***/
+
+Status
+XkbAllocNames(XkbDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases)
+{
+XkbNamesPtr	names;
+
+    if (xkb==NULL)
+	return BadMatch;
+    if (xkb->names==NULL) {
+	xkb->names = _XkbTypedCalloc(1,XkbNamesRec);
+	if (xkb->names==NULL)
+	    return BadAlloc;
+    }
+    names= xkb->names;
+    if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){
+	register int	i;
+	XkbKeyTypePtr	type;
+
+	type= xkb->map->types;
+	for (i=0;i<xkb->map->num_types;i++,type++) {
+	    if (type->level_names==NULL) {
+		type->level_names= _XkbTypedCalloc(type->num_levels,Atom);
+		if (type->level_names==NULL)
+		    return BadAlloc;
+	    }
+	}
+    }
+    if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code)) 
+	    return BadValue;
+	names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec);
+	if (names->keys==NULL)
+	    return BadAlloc;
+    }
+    if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) {
+	if (names->key_aliases==NULL) {
+	    names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec);
+	}
+	else if (nTotalAliases>names->num_key_aliases) {
+	    XkbKeyAliasRec *prev_aliases = names->key_aliases;
+
+	    names->key_aliases= _XkbTypedRealloc(names->key_aliases,
+						nTotalAliases,XkbKeyAliasRec);
+	    if (names->key_aliases!=NULL) {
+		_XkbClearElems(names->key_aliases,names->num_key_aliases,
+						nTotalAliases-1,XkbKeyAliasRec);
+	    } else {
+		_XkbFree(prev_aliases);
+	    }
+	}
+	if (names->key_aliases==NULL) {
+	    names->num_key_aliases= 0;
+	    return BadAlloc;
+	}
+	names->num_key_aliases= nTotalAliases;
+    }
+    if ((which&XkbRGNamesMask)&&(nTotalRG>0)) {
+	if (names->radio_groups==NULL) {
+	    names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom);
+	}
+	else if (nTotalRG>names->num_rg) {
+	    Atom *prev_radio_groups = names->radio_groups;
+
+	    names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG,
+									Atom);
+	    if (names->radio_groups!=NULL) {
+		_XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1,
+									Atom);
+	    } else {
+		_XkbFree(prev_radio_groups);
+	    }
+	}
+	if (names->radio_groups==NULL)
+	    return BadAlloc;
+	names->num_rg= nTotalRG;
+    }
+    return Success;
+}
+
+void
+XkbFreeNames(XkbDescPtr xkb,unsigned which,Bool freeMap)
+{
+XkbNamesPtr	names;
+
+    if ((xkb==NULL)||(xkb->names==NULL))
+	return;
+    names= xkb->names;
+    if (freeMap)
+	which= XkbAllNamesMask; 
+    if (which&XkbKTLevelNamesMask) {
+	XkbClientMapPtr	map= xkb->map;
+	if ((map!=NULL)&&(map->types!=NULL)) {
+	    register int 		i;
+	    register XkbKeyTypePtr	type;
+	    type= map->types;
+	    for (i=0;i<map->num_types;i++,type++) {
+		if (type->level_names!=NULL) {
+		    _XkbFree(type->level_names);
+		    type->level_names= NULL;
+		}
+	    }
+	}
+    }
+    if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
+	_XkbFree(names->keys);
+	names->keys= NULL;
+	names->num_keys= 0;
+    }
+    if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){
+	_XkbFree(names->key_aliases);
+	names->key_aliases=NULL;
+	names->num_key_aliases=0;
+    }
+    if ((which&XkbRGNamesMask)&&(names->radio_groups)) {
+	_XkbFree(names->radio_groups);
+	names->radio_groups= NULL;
+	names->num_rg= 0;
+    }
+    if (freeMap) {
+	_XkbFree(names);
+	xkb->names= NULL;
+    }
+    return;
+}
+
+/***===================================================================***/
+
+/*ARGSUSED*/
+Status
+XkbAllocControls(XkbDescPtr xkb,unsigned which)
+{
+    if (xkb==NULL)
+	return BadMatch;
+
+    if (xkb->ctrls==NULL) {
+	xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec);
+	if (!xkb->ctrls)
+	    return BadAlloc;
+    }
+    return Success;
+}
+
+/*ARGSUSED*/
+void
+XkbFreeControls(XkbDescPtr xkb,unsigned which,Bool freeMap)
+{
+    if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) {
+	_XkbFree(xkb->ctrls);
+	xkb->ctrls= NULL;
+    }
+    return;
+}
+
+/***===================================================================***/
+
+Status 
+XkbAllocIndicatorMaps(XkbDescPtr xkb)
+{
+    if (xkb==NULL)
+	return BadMatch;
+    if (xkb->indicators==NULL) {
+	xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec);
+	if (!xkb->indicators)
+	    return BadAlloc;
+    }
+    return Success;
+}
+
+void
+XkbFreeIndicatorMaps(XkbDescPtr xkb)
+{
+    if ((xkb!=NULL)&&(xkb->indicators!=NULL)) {
+	_XkbFree(xkb->indicators);
+	xkb->indicators= NULL;
+    }
+    return;
+}
+
+/***====================================================================***/
+
+XkbDescRec	*
+XkbAllocKeyboard(void)
+{
+XkbDescRec *xkb;
+
+    xkb = _XkbTypedCalloc(1,XkbDescRec);
+    if (xkb)
+	xkb->device_spec= XkbUseCoreKbd;
+    return xkb;
+}
+
+void
+XkbFreeKeyboard(XkbDescPtr xkb,unsigned which,Bool freeAll)
+{
+    if (xkb==NULL)
+	return;
+    if (freeAll)
+	which= XkbAllComponentsMask;
+    if (which&XkbClientMapMask)
+	XkbFreeClientMap(xkb,XkbAllClientInfoMask,True);
+    if (which&XkbServerMapMask)
+	XkbFreeServerMap(xkb,XkbAllServerInfoMask,True);
+    if (which&XkbCompatMapMask)
+	XkbFreeCompatMap(xkb,XkbAllCompatMask,True);
+    if (which&XkbIndicatorMapMask)
+	XkbFreeIndicatorMaps(xkb);
+    if (which&XkbNamesMask)
+	XkbFreeNames(xkb,XkbAllNamesMask,True);
+    if ((which&XkbGeometryMask) && (xkb->geom!=NULL))
+	XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True);
+    if (which&XkbControlsMask)
+	XkbFreeControls(xkb,XkbAllControlsMask,True);
+    if (freeAll)
+	_XkbFree(xkb);
+    return;
+}
+
+/***====================================================================***/
+
+XkbDeviceLedInfoPtr
+XkbAddDeviceLedInfo(XkbDeviceInfoPtr devi,unsigned ledClass,unsigned ledId)
+{
+XkbDeviceLedInfoPtr	devli;
+register int		i;
+
+    if ((!devi)||(!XkbSingleXIClass(ledClass))||(!XkbSingleXIId(ledId)))
+	return NULL;
+    for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
+	if ((devli->led_class==ledClass)&&(devli->led_id==ledId))
+	    return devli;
+    }
+    if (devi->num_leds>=devi->sz_leds) {
+	XkbDeviceLedInfoRec *prev_leds = devi->leds;
+	
+	if (devi->sz_leds>0)	devi->sz_leds*= 2;
+	else			devi->sz_leds= 1;
+	devi->leds= _XkbTypedRealloc(devi->leds,devi->sz_leds,
+							XkbDeviceLedInfoRec);
+	if (!devi->leds) {
+	    _XkbFree(prev_leds);
+	    devi->sz_leds= devi->num_leds= 0;
+	    return NULL;
+	}
+	i= devi->num_leds;
+	for (devli=&devi->leds[i];i<devi->sz_leds;i++,devli++) {
+	    bzero(devli,sizeof(XkbDeviceLedInfoRec));
+	    devli->led_class= XkbXINone;
+	    devli->led_id= XkbXINone;
+	}
+    }
+    devli= &devi->leds[devi->num_leds++];
+    bzero(devli,sizeof(XkbDeviceLedInfoRec));
+    devli->led_class= ledClass;
+    devli->led_id= ledId;
+    return devli;
+}
+
+Status
+XkbResizeDeviceButtonActions(XkbDeviceInfoPtr devi,unsigned newTotal)
+{
+    XkbAction *prev_btn_acts;
+
+    if ((!devi)||(newTotal>255))
+	return BadValue;
+    if ((devi->btn_acts!=NULL)&&(newTotal==devi->num_btns))
+	return Success;
+    if (newTotal==0) {
+	if (devi->btn_acts!=NULL) {
+	    _XkbFree(devi->btn_acts);
+	    devi->btn_acts= NULL;
+	}
+	devi->num_btns= 0;
+	return Success;
+    }
+    prev_btn_acts = devi->btn_acts;
+    devi->btn_acts= _XkbTypedRealloc(devi->btn_acts,newTotal,XkbAction);
+    if (devi->btn_acts==NULL) {
+	_XkbFree(prev_btn_acts);
+	devi->num_btns= 0;
+	return BadAlloc;
+    }
+    if (newTotal>devi->num_btns) {
+	XkbAction *act;
+	act= &devi->btn_acts[devi->num_btns];
+	bzero((char *)act,(newTotal-devi->num_btns)*sizeof(XkbAction));
+    }
+    devi->num_btns= newTotal;
+    return Success;
+}
+
+/*ARGSUSED*/
+XkbDeviceInfoPtr
+XkbAllocDeviceInfo(unsigned deviceSpec,unsigned nButtons,unsigned szLeds)
+{
+XkbDeviceInfoPtr	devi;
+
+    devi= _XkbTypedCalloc(1,XkbDeviceInfoRec);
+    if (devi!=NULL) {
+	devi->device_spec= deviceSpec;
+	devi->has_own_state= False;
+	devi->num_btns= 0;
+	devi->btn_acts= NULL;
+	if (nButtons>0) {
+	    devi->num_btns= nButtons;
+	    devi->btn_acts= _XkbTypedCalloc(nButtons,XkbAction);
+	    if (!devi->btn_acts) {
+		_XkbFree(devi);
+		return NULL;
+	    }
+	}
+	devi->dflt_kbd_fb= XkbXINone;
+	devi->dflt_led_fb= XkbXINone;
+	devi->num_leds= 0;
+	devi->sz_leds= 0;
+	devi->leds= NULL;
+	if (szLeds>0) {
+	    devi->sz_leds= szLeds;
+	    devi->leds= _XkbTypedCalloc(szLeds,XkbDeviceLedInfoRec);
+	    if (!devi->leds) {
+		if (devi->btn_acts)
+		    _XkbFree(devi->btn_acts);
+		_XkbFree(devi);
+		return NULL;
+	    }
+	}
+    }
+    return devi;
+}
+
+
+void 
+XkbFreeDeviceInfo(XkbDeviceInfoPtr devi,unsigned which,Bool freeDevI)
+{
+    if (devi) {
+	if (freeDevI) {
+	    which= XkbXI_AllDeviceFeaturesMask;
+	    if (devi->name) {
+		_XkbFree(devi->name);
+		devi->name= NULL;
+	    }
+	}
+	if ((which&XkbXI_ButtonActionsMask)&&(devi->btn_acts)) {
+	    _XkbFree(devi->btn_acts);
+	    devi->num_btns= 0;
+	    devi->btn_acts= NULL;
+	}
+	if ((which&XkbXI_IndicatorsMask)&&(devi->leds)) {
+	    register int i;
+	    if ((which&XkbXI_IndicatorsMask)==XkbXI_IndicatorsMask) {
+		_XkbFree(devi->leds);
+		devi->sz_leds= devi->num_leds= 0;
+		devi->leds= NULL;
+	    }
+	    else {
+		XkbDeviceLedInfoPtr	devli;
+		for (i=0,devli=devi->leds;i<devi->num_leds;i++,devli++) {
+		    if (which&XkbXI_IndicatorMapsMask)
+			 bzero((char *)&devli->maps[0],sizeof(devli->maps));
+		    else bzero((char *)&devli->names[0],sizeof(devli->names));
+		}
+	    }
+	}
+	if (freeDevI)
+	    _XkbFree(devi);
+    }
+    return;
+}
diff --git a/nx-X11/programs/Xserver/xkb/XKBGAlloc.c b/nx-X11/programs/Xserver/xkb/XKBGAlloc.c
new file mode 100644
index 000000000..f5e6737af
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/XKBGAlloc.c
@@ -0,0 +1,1016 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be 
+used in advertising or publicity pertaining to distribution 
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability 
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#ifndef XKB_IN_SERVER
+
+#include <stdio.h>
+#include "Xlibint.h"
+#include "XKBlibint.h"
+#include <nx-X11/extensions/XKBgeom.h>
+#include <nx-X11/extensions/XKBproto.h>
+
+#else 
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <nx-X11/extensions/XKBsrv.h>
+#include <nx-X11/extensions/XKBgeom.h>
+
+#endif /* XKB_IN_SERVER */
+
+#ifdef X_NOT_POSIX
+#define Size_t unsigned int
+#else
+#define Size_t size_t
+#endif
+
+/***====================================================================***/
+
+static void 
+_XkbFreeGeomLeafElems(	Bool			freeAll,
+			int			first,
+			int 			count,
+			unsigned short *	num_inout,
+			unsigned short *	sz_inout,
+			char **			elems,
+			unsigned int		elem_sz)
+{
+    if ((freeAll)||(*elems==NULL)) {
+	*num_inout= *sz_inout= 0;
+	if (*elems!=NULL) {
+	    _XkbFree(*elems);
+	    *elems= NULL;
+	}	
+	return;
+    }
+
+    if ((first>=(*num_inout))||(first<0)||(count<1))
+	return;
+
+    if (first+count>=(*num_inout)) { 
+	/* truncating the array is easy */
+	(*num_inout)= first;
+    }
+    else {
+	char *	ptr;
+	int 	extra;
+	ptr= *elems;
+	extra= ((*num_inout)-(first+count))*elem_sz;
+	if (extra>0)
+	    memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra);
+	(*num_inout)-= count;
+    }
+    return;
+}
+
+typedef void (*ContentsClearFunc)(
+		char *		/* priv */
+);
+
+static void 
+_XkbFreeGeomNonLeafElems(	Bool			freeAll,
+				int			first,
+				int 			count,
+				unsigned short *	num_inout,
+				unsigned short *	sz_inout,
+				char **			elems,
+				unsigned int		elem_sz,
+				ContentsClearFunc	freeFunc)
+{
+register int i;
+register char *ptr;
+
+    if (freeAll) {
+	first= 0;
+	count= (*num_inout);
+    }
+    else if ((first>=(*num_inout))||(first<0)||(count<1))
+	return;
+    else if (first+count>(*num_inout))
+	count= (*num_inout)-first;
+    if (*elems==NULL)
+	return;
+
+    if (freeFunc) {
+	ptr= *elems;
+	ptr+= first*elem_sz;
+	for (i=0;i<count;i++) {
+	    (*freeFunc)(ptr);
+	    ptr+= elem_sz;
+	}
+    }
+    if (freeAll) {
+	(*num_inout)= (*sz_inout)= 0;
+	if (*elems) {
+	    _XkbFree(*elems);
+	    *elems= NULL;
+	}
+    }
+    else if (first+count>=(*num_inout))
+	*num_inout= first;
+    else {
+	i= ((*num_inout)-(first+count))*elem_sz;
+	ptr= *elems;
+	memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i);
+	(*num_inout)-= count;
+    }
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearProperty(char *prop_in)
+{
+XkbPropertyPtr	prop= (XkbPropertyPtr)prop_in;
+
+    if (prop->name) {
+	_XkbFree(prop->name);
+	prop->name= NULL;
+    }
+    if (prop->value) {
+	_XkbFree(prop->value);
+	prop->value= NULL;
+    }
+    return;
+}
+
+void
+XkbFreeGeomProperties(	XkbGeometryPtr	geom,
+			int		first,
+			int		count,
+			Bool		freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&geom->num_properties,&geom->sz_properties,
+				(char **)&geom->properties,
+				sizeof(XkbPropertyRec),_XkbClearProperty);
+    return;
+}
+
+/***====================================================================***/
+
+void
+XkbFreeGeomKeyAliases(	XkbGeometryPtr	geom,
+			int		first,
+			int		count,
+			Bool		freeAll)
+{	
+    _XkbFreeGeomLeafElems(freeAll,first,count,
+				&geom->num_key_aliases,&geom->sz_key_aliases,
+				(char **)&geom->key_aliases,
+				sizeof(XkbKeyAliasRec));
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearColor(char *color_in)
+{
+XkbColorPtr	color= (XkbColorPtr)color_in;
+
+    if (color->spec)
+	_XkbFree(color->spec);
+    return;
+}
+
+void
+XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&geom->num_colors,&geom->sz_colors,
+				(char **)&geom->colors,
+				sizeof(XkbColorRec),_XkbClearColor);
+    return;
+}
+
+/***====================================================================***/
+
+void
+XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomLeafElems(freeAll,first,count,
+				&outline->num_points,&outline->sz_points,
+				(char **)&outline->points,
+				sizeof(XkbPointRec));
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearOutline(char *outline_in)
+{
+XkbOutlinePtr	outline= (XkbOutlinePtr)outline_in;
+
+    if (outline->points!=NULL)
+	XkbFreeGeomPoints(outline,0,outline->num_points,True);
+    return;
+}
+
+void
+XkbFreeGeomOutlines(XkbShapePtr	shape,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&shape->num_outlines,&shape->sz_outlines,
+				(char **)&shape->outlines,
+				sizeof(XkbOutlineRec),_XkbClearOutline);
+	
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearShape(char *shape_in)
+{
+XkbShapePtr	shape= (XkbShapePtr)shape_in;
+
+    if (shape->outlines)
+	XkbFreeGeomOutlines(shape,0,shape->num_outlines,True);
+    return;
+}
+
+void
+XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&geom->num_shapes,&geom->sz_shapes,
+				(char **)&geom->shapes,
+				sizeof(XkbShapeRec),_XkbClearShape);
+    return;
+}
+
+/***====================================================================***/
+
+void 
+XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomLeafElems(freeAll,first,count,
+				&row->num_keys,&row->sz_keys,
+				(char **)&row->keys,
+				sizeof(XkbOverlayKeyRec));
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearOverlayRow(char *row_in)
+{
+XkbOverlayRowPtr	row= (XkbOverlayRowPtr)row_in;
+
+    if (row->keys!=NULL)
+	XkbFreeGeomOverlayKeys(row,0,row->num_keys,True);
+    return;
+}
+
+void
+XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&overlay->num_rows,&overlay->sz_rows,
+				(char **)&overlay->rows,
+				sizeof(XkbOverlayRowRec),_XkbClearOverlayRow);
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearOverlay(char *overlay_in)
+{
+XkbOverlayPtr	overlay= (XkbOverlayPtr)overlay_in;
+
+    if (overlay->rows!=NULL)
+	XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True);
+    return;
+}
+
+void
+XkbFreeGeomOverlays(XkbSectionPtr section,int first,int	count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&section->num_overlays,&section->sz_overlays,
+				(char **)&section->overlays,
+				sizeof(XkbOverlayRec),_XkbClearOverlay);
+    return;
+}
+
+/***====================================================================***/
+
+void
+XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomLeafElems(freeAll,first,count,
+				&row->num_keys,&row->sz_keys,
+				(char **)&row->keys,
+				sizeof(XkbKeyRec));
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearRow(char *row_in)
+{
+XkbRowPtr	row= (XkbRowPtr)row_in;
+
+    if (row->keys!=NULL)
+	XkbFreeGeomKeys(row,0,row->num_keys,True);
+    return;
+}
+
+void
+XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&section->num_rows,&section->sz_rows,
+				(char **)&section->rows,
+				sizeof(XkbRowRec),_XkbClearRow);
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearSection(char *section_in)
+{
+XkbSectionPtr	section= (XkbSectionPtr)section_in;
+
+    if (section->rows!=NULL)
+	XkbFreeGeomRows(section,0,section->num_rows,True);
+    if (section->doodads!=NULL) {
+	XkbFreeGeomDoodads(section->doodads,section->num_doodads,True);
+	section->doodads= NULL;
+    }
+    return;
+}
+
+void
+XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)
+{
+    _XkbFreeGeomNonLeafElems(freeAll,first,count,
+				&geom->num_sections,&geom->sz_sections,
+				(char **)&geom->sections,
+				sizeof(XkbSectionRec),_XkbClearSection);
+    return;
+}
+
+/***====================================================================***/
+
+static void
+_XkbClearDoodad(char *doodad_in)
+{
+XkbDoodadPtr	doodad= (XkbDoodadPtr)doodad_in;
+
+    switch (doodad->any.type) {
+   	case XkbTextDoodad: 
+	    {
+		if (doodad->text.text!=NULL) {
+		    _XkbFree(doodad->text.text);
+		    doodad->text.text= NULL;
+		}
+		if (doodad->text.font!=NULL) {
+		    _XkbFree(doodad->text.font);
+		    doodad->text.font= NULL;
+		}
+	    }
+	    break;
+   	case XkbLogoDoodad: 
+	    {
+		if (doodad->logo.logo_name!=NULL) {
+		    _XkbFree(doodad->logo.logo_name);
+		    doodad->logo.logo_name= NULL;
+		}
+	    }
+	    break;
+    }
+    return;
+}
+
+void
+XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)
+{
+register int 		i;
+register XkbDoodadPtr	doodad;
+
+    if (doodads) {
+	for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) {
+	    _XkbClearDoodad((char *)doodad);
+	}
+	if (freeAll)
+	    _XkbFree(doodads);
+    }
+    return;
+}
+
+void
+XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)
+{
+    if (geom==NULL)
+	return;
+    if (freeMap)
+	which= XkbGeomAllMask;
+    if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL))
+	XkbFreeGeomProperties(geom,0,geom->num_properties,True);
+    if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL))
+	XkbFreeGeomColors(geom,0,geom->num_colors,True);
+    if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL))
+	XkbFreeGeomShapes(geom,0,geom->num_shapes,True);
+    if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL))
+	XkbFreeGeomSections(geom,0,geom->num_sections,True);
+    if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) {
+	XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True);
+	geom->doodads= NULL;
+	geom->num_doodads= geom->sz_doodads= 0;
+    }
+    if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL))
+	XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True);
+    if (freeMap) {
+	if (geom->label_font!=NULL) {
+	    _XkbFree(geom->label_font);
+	    geom->label_font= NULL;
+	}
+	_XkbFree(geom);
+    }
+    return;
+}
+
+/***====================================================================***/
+
+static Status
+_XkbGeomAlloc(	XPointer *		old,
+		unsigned short *	num,
+		unsigned short *	total,
+		int			num_new,
+		Size_t			sz_elem)
+{
+    if (num_new<1)
+	return Success;
+    if ((*old)==NULL)
+	*num= *total= 0;
+
+    if ((*num)+num_new<=(*total))
+	return Success;
+
+    *total= (*num)+num_new;
+    if ((*old)!=NULL)
+	 (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem);
+    else (*old)= (XPointer)_XkbCalloc((*total),sz_elem);
+    if ((*old)==NULL) {
+	*total= *num= 0;
+	return BadAlloc;
+    }
+
+    if (*num>0) {
+	char *tmp= (char *)(*old);
+	bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem));
+    }
+    return Success;
+}
+
+#define	_XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\
+				&(g)->num_properties,&(g)->sz_properties,\
+				(n),sizeof(XkbPropertyRec))
+#define	_XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\
+				&(g)->num_colors,&(g)->sz_colors,\
+				(n),sizeof(XkbColorRec))
+#define	_XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\
+				&(g)->num_shapes,&(g)->sz_shapes,\
+				(n),sizeof(XkbShapeRec))
+#define	_XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\
+				&(g)->num_sections,&(g)->sz_sections,\
+				(n),sizeof(XkbSectionRec))
+#define	_XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\
+				&(g)->num_doodads,&(g)->sz_doodads,\
+				(n),sizeof(XkbDoodadRec))
+#define	_XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\
+				&(g)->num_key_aliases,&(g)->sz_key_aliases,\
+				(n),sizeof(XkbKeyAliasRec))
+
+#define	_XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\
+				&(s)->num_outlines,&(s)->sz_outlines,\
+				(n),sizeof(XkbOutlineRec))
+#define	_XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\
+				&(s)->num_rows,&(s)->sz_rows,\
+				(n),sizeof(XkbRowRec))
+#define	_XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\
+				&(o)->num_points,&(o)->sz_points,\
+				(n),sizeof(XkbPointRec))
+#define	_XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
+				&(r)->num_keys,&(r)->sz_keys,\
+				(n),sizeof(XkbKeyRec))
+#define	_XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\
+				&(s)->num_overlays,&(s)->sz_overlays,\
+				(n),sizeof(XkbOverlayRec))
+#define	_XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\
+				&(o)->num_rows,&(o)->sz_rows,\
+				(n),sizeof(XkbOverlayRowRec))
+#define	_XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
+				&(r)->num_keys,&(r)->sz_keys,\
+				(n),sizeof(XkbOverlayKeyRec))
+    
+Status
+XkbAllocGeomProps(XkbGeometryPtr geom,int nProps)
+{
+    return _XkbAllocProps(geom,nProps);
+}
+
+Status
+XkbAllocGeomColors(XkbGeometryPtr geom,int nColors)
+{
+    return _XkbAllocColors(geom,nColors);
+}
+
+Status
+XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases)
+{
+    return _XkbAllocKeyAliases(geom,nKeyAliases);
+}
+
+Status
+XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes)
+{
+    return _XkbAllocShapes(geom,nShapes);
+}
+
+Status
+XkbAllocGeomSections(XkbGeometryPtr geom,int nSections)
+{
+    return _XkbAllocSections(geom,nSections);
+}
+
+Status
+XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays)
+{
+    return _XkbAllocOverlays(section,nOverlays);
+}
+
+Status
+XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows)
+{
+    return _XkbAllocOverlayRows(overlay,nRows);
+}
+
+Status
+XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys)
+{
+    return _XkbAllocOverlayKeys(row,nKeys);
+}
+
+Status
+XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads)
+{
+    return _XkbAllocDoodads(geom,nDoodads);
+}
+
+Status
+XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads)
+{
+    return _XkbAllocDoodads(section,nDoodads);
+}
+
+Status
+XkbAllocGeomOutlines(XkbShapePtr shape,int nOL)
+{
+    return _XkbAllocOutlines(shape,nOL);
+}
+
+Status
+XkbAllocGeomRows(XkbSectionPtr section,int nRows)
+{
+    return _XkbAllocRows(section,nRows);
+}
+
+Status
+XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts)
+{
+    return _XkbAllocPoints(ol,nPts);
+}
+
+Status
+XkbAllocGeomKeys(XkbRowPtr row,int nKeys)
+{
+    return _XkbAllocKeys(row,nKeys);
+}
+
+Status
+XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)
+{
+XkbGeometryPtr	geom;
+Status		rtrn;
+
+    if (xkb->geom==NULL) {
+	xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec);
+	if (!xkb->geom)
+	    return BadAlloc;
+    }
+    geom= xkb->geom;
+    if ((sizes->which&XkbGeomPropertiesMask)&&
+	((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) {
+	goto BAIL;
+    }
+    if ((sizes->which&XkbGeomColorsMask)&&
+	((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) {
+	goto BAIL;
+    }
+    if ((sizes->which&XkbGeomShapesMask)&&
+	((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) {
+	goto BAIL;
+    }
+    if ((sizes->which&XkbGeomSectionsMask)&&
+	((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) {
+	goto BAIL;
+    }
+    if ((sizes->which&XkbGeomDoodadsMask)&&
+	((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) {
+	goto BAIL;
+    }
+    if ((sizes->which&XkbGeomKeyAliasesMask)&&
+	((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) {
+	goto BAIL;
+    }
+    return Success;
+BAIL:
+    XkbFreeGeometry(geom,XkbGeomAllMask,True);
+    xkb->geom= NULL;
+    return rtrn;
+}
+
+/***====================================================================***/
+
+XkbPropertyPtr
+XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value)
+{
+register int i;
+register XkbPropertyPtr prop;
+
+    if ((!geom)||(!name)||(!value))
+	return NULL;
+    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
+	if ((prop->name)&&(strcmp(name,prop->name)==0)) {
+	    if (prop->value)
+		_XkbFree(prop->value);
+	    prop->value= (char *)_XkbAlloc(strlen(value)+1);
+	    if (prop->value)
+		strcpy(prop->value,value);
+	    return prop;
+	}    
+    }
+    if ((geom->num_properties>=geom->sz_properties)&&
+					(_XkbAllocProps(geom,1)!=Success)) {
+	return NULL;
+    }
+    prop= &geom->properties[geom->num_properties];
+    prop->name= (char *)_XkbAlloc(strlen(name)+1);
+    if (!name)
+	return NULL;
+    strcpy(prop->name,name);
+    prop->value= (char *)_XkbAlloc(strlen(value)+1);
+    if (!value) {
+	_XkbFree(prop->name);
+	prop->name= NULL;
+	return NULL;
+    }
+    strcpy(prop->value,value);
+    geom->num_properties++;
+    return prop;
+}
+
+XkbKeyAliasPtr
+XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
+{
+register int i;
+register XkbKeyAliasPtr alias;
+
+    if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
+	return NULL;
+    for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
+	if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
+	    bzero(alias->real,XkbKeyNameLength);
+	    strncpy(alias->real,realStr,XkbKeyNameLength);
+	    return alias;
+	}
+    }
+    if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
+				(_XkbAllocKeyAliases(geom,1)!=Success)) {
+	return NULL;
+    }
+    alias= &geom->key_aliases[geom->num_key_aliases];
+    bzero(alias,sizeof(XkbKeyAliasRec));
+    strncpy(alias->alias,aliasStr,XkbKeyNameLength);
+    strncpy(alias->real,realStr,XkbKeyNameLength);
+    geom->num_key_aliases++;
+    return alias;
+}
+
+XkbColorPtr
+XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
+{
+register int i;
+register XkbColorPtr color;
+
+    if ((!geom)||(!spec))
+	return NULL;
+    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
+	if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
+	    color->pixel= pixel;
+	    return color;
+	}
+    }
+    if ((geom->num_colors>=geom->sz_colors)&&
+					(_XkbAllocColors(geom,1)!=Success)) {
+	return NULL;
+    }
+    color= &geom->colors[geom->num_colors];
+    color->pixel= pixel;
+    color->spec= (char *)_XkbAlloc(strlen(spec)+1);
+    if (!color->spec)
+	return NULL;
+    strcpy(color->spec,spec);
+    geom->num_colors++;
+    return color;
+}
+
+XkbOutlinePtr
+XkbAddGeomOutline(XkbShapePtr shape,int sz_points)
+{
+XkbOutlinePtr	outline;
+
+    if ((!shape)||(sz_points<0))
+	return NULL;
+    if ((shape->num_outlines>=shape->sz_outlines)&&
+					(_XkbAllocOutlines(shape,1)!=Success)) {
+	return NULL;
+    }
+    outline= &shape->outlines[shape->num_outlines];
+    bzero(outline,sizeof(XkbOutlineRec));
+    if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
+	return NULL;
+    shape->num_outlines++;
+    return outline;
+}
+
+XkbShapePtr
+XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
+{
+XkbShapePtr	shape;
+register int	i;
+
+    if ((!geom)||(!name)||(sz_outlines<0))
+	return NULL;
+    if (geom->num_shapes>0) {
+	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
+	    if (name==shape->name)
+		return shape;
+	}
+    }
+    if ((geom->num_shapes>=geom->sz_shapes)&&
+					(_XkbAllocShapes(geom,1)!=Success))
+	return NULL;
+    shape= &geom->shapes[geom->num_shapes];
+    bzero(shape,sizeof(XkbShapeRec));
+    if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
+	return NULL;
+    shape->name= name;
+    shape->primary= shape->approx= NULL;
+    geom->num_shapes++;
+    return shape;
+}
+
+XkbKeyPtr
+XkbAddGeomKey(XkbRowPtr row)
+{
+XkbKeyPtr	key;
+    if (!row)
+	return NULL;
+    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
+	return NULL;
+    key= &row->keys[row->num_keys++];
+    bzero(key,sizeof(XkbKeyRec));
+    return key;
+}
+
+XkbRowPtr
+XkbAddGeomRow(XkbSectionPtr section,int sz_keys)
+{
+XkbRowPtr	row;
+
+    if ((!section)||(sz_keys<0))
+	return NULL;
+    if ((section->num_rows>=section->sz_rows)&&
+    					(_XkbAllocRows(section,1)!=Success))
+	return NULL;
+    row= &section->rows[section->num_rows];
+    bzero(row,sizeof(XkbRowRec));
+    if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
+	return NULL;
+    section->num_rows++;
+    return row;
+}
+
+XkbSectionPtr
+XkbAddGeomSection(	XkbGeometryPtr	geom,
+			Atom		name,
+			int		sz_rows,
+			int		sz_doodads,
+			int		sz_over)
+{
+register int	i;
+XkbSectionPtr	section;
+
+    if ((!geom)||(name==None)||(sz_rows<0))
+	return NULL;
+    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
+	if (section->name!=name)
+	    continue;
+	if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
+	    ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
+	    ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
+	    return NULL;
+	return section;
+    }
+    if ((geom->num_sections>=geom->sz_sections)&&
+					(_XkbAllocSections(geom,1)!=Success))
+	return NULL;
+    section= &geom->sections[geom->num_sections];
+    if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
+	return NULL;
+    if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
+	if (section->rows) {
+	    _XkbFree(section->rows);
+	    section->rows= NULL;
+	    section->sz_rows= section->num_rows= 0;
+	}
+	return NULL;
+    }
+    section->name= name;
+    geom->num_sections++;
+    return section;
+}
+
+XkbDoodadPtr
+XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
+{
+XkbDoodadPtr	old,doodad;
+register int	i,nDoodads;
+
+    if ((!geom)||(name==None))
+	return NULL;
+    if ((section!=NULL)&&(section->num_doodads>0)) {
+	old= section->doodads;
+	nDoodads= section->num_doodads;
+    }
+    else {
+	old= geom->doodads;
+	nDoodads= geom->num_doodads;
+    }
+    for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
+	if (doodad->any.name==name)
+	    return doodad;
+    }
+    if (section) {
+	if ((section->num_doodads>=geom->sz_doodads)&&
+	    (_XkbAllocDoodads(section,1)!=Success)) {
+	    return NULL;
+	}
+	doodad= &section->doodads[section->num_doodads++];
+    }
+    else {
+	if ((geom->num_doodads>=geom->sz_doodads)&&
+					(_XkbAllocDoodads(geom,1)!=Success))
+	    return NULL;
+	doodad= &geom->doodads[geom->num_doodads++];
+    }
+    bzero(doodad,sizeof(XkbDoodadRec));
+    doodad->any.name= name;
+    return doodad;
+}
+
+XkbOverlayKeyPtr
+XkbAddGeomOverlayKey(	XkbOverlayPtr		overlay,
+			XkbOverlayRowPtr 	row,
+			char *			over,
+			char *			under)
+{
+register int	i;
+XkbOverlayKeyPtr key;
+XkbSectionPtr	section;
+XkbRowPtr	row_under;
+Bool		found;
+
+    if ((!overlay)||(!row)||(!over)||(!under))
+	return NULL;
+    section= overlay->section_under;
+    if (row->row_under>=section->num_rows)
+	return NULL;
+    row_under= &section->rows[row->row_under];
+    for (i=0,found=False;i<row_under->num_keys;i++) {
+	if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
+	    found= True;
+	    break;
+	}
+    }
+    if (!found)
+   	return NULL; 
+    if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
+	return NULL;
+    key= &row->keys[row->num_keys];
+    strncpy(key->under.name,under,XkbKeyNameLength);
+    strncpy(key->over.name,over,XkbKeyNameLength);
+    row->num_keys++;
+    return key;
+}
+
+XkbOverlayRowPtr
+XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
+{
+register int		i;
+XkbOverlayRowPtr	row;
+
+    if ((!overlay)||(sz_keys<0))
+	return NULL;
+    if (row_under>=overlay->section_under->num_rows)
+	return NULL;
+    for (i=0;i<overlay->num_rows;i++) {
+	if (overlay->rows[i].row_under==row_under) {
+	    row= &overlay->rows[i];
+	    if ((row->sz_keys<sz_keys)&&
+				(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
+		return NULL;
+	    }
+	    return &overlay->rows[i];
+	}
+    }
+    if ((overlay->num_rows>=overlay->sz_rows)&&
+				(_XkbAllocOverlayRows(overlay,1)!=Success))
+	return NULL;
+    row= &overlay->rows[overlay->num_rows];
+    bzero(row,sizeof(XkbOverlayRowRec));
+    if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
+	return NULL;
+    row->row_under= row_under;
+    overlay->num_rows++;
+    return row;
+}
+
+XkbOverlayPtr
+XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
+{
+register int	i;
+XkbOverlayPtr	overlay;
+
+    if ((!section)||(name==None)||(sz_rows==0))
+	return NULL;
+
+    for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
+	if (overlay->name==name) {
+	    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
+		return NULL;
+	    return overlay;
+	}
+    }
+    if ((section->num_overlays>=section->sz_overlays)&&
+				(_XkbAllocOverlays(section,1)!=Success))
+	return NULL;
+    overlay= &section->overlays[section->num_overlays];
+    if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
+	return NULL;
+    overlay->name= name;
+    overlay->section_under= section;
+    section->num_overlays++;
+    return overlay;
+}
diff --git a/nx-X11/programs/Xserver/xkb/XKBMAlloc.c b/nx-X11/programs/Xserver/xkb/XKBMAlloc.c
new file mode 100644
index 000000000..ffc822fed
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/XKBMAlloc.c
@@ -0,0 +1,1017 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be 
+used in advertising or publicity pertaining to distribution 
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability 
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#ifndef XKB_IN_SERVER
+
+#include <stdio.h>
+#include "Xlibint.h"
+#include <nx-X11/extensions/XKBproto.h>
+#include <nx-X11/keysym.h>
+#include "XKBlibint.h"
+
+#else 
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <nx-X11/keysym.h>
+#define	XKBSRV_NEED_FILE_FUNCS
+#include <nx-X11/extensions/XKBsrv.h>
+
+#endif /* XKB_IN_SERVER */
+
+/***====================================================================***/
+
+Status
+XkbAllocClientMap(XkbDescPtr xkb,unsigned which,unsigned nTotalTypes)
+{
+register int	i;
+XkbClientMapPtr map;
+
+    if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypes<XkbNumRequiredTypes)))
+	return BadValue;
+    if ((which&XkbKeySymsMask)&&
+	((!XkbIsLegalKeycode(xkb->min_key_code))||
+	 (!XkbIsLegalKeycode(xkb->max_key_code))||
+	 (xkb->max_key_code<xkb->min_key_code))) {
+#ifdef DEBUG
+fprintf(stderr,"bad keycode (%d,%d) in XkbAllocClientMap\n",
+				xkb->min_key_code,xkb->max_key_code);
+#endif
+	return BadValue;
+    }
+
+    if (xkb->map==NULL) {
+	map= _XkbTypedCalloc(1,XkbClientMapRec);
+	if (map==NULL)
+	    return BadAlloc;
+	xkb->map= map;
+    }
+    else map= xkb->map;
+
+    if ((which&XkbKeyTypesMask)&&(nTotalTypes>0)) {
+	if (map->types==NULL) {
+	    map->types= _XkbTypedCalloc(nTotalTypes,XkbKeyTypeRec);
+	    if (map->types==NULL)
+		return BadAlloc;
+	    map->num_types= 0;
+	    map->size_types= nTotalTypes;
+	}
+	else if (map->size_types<nTotalTypes) {
+	    XkbKeyTypeRec *prev_types = map->types;
+
+	    map->types= _XkbTypedRealloc(map->types,nTotalTypes,XkbKeyTypeRec);
+	    if (map->types==NULL) {
+		_XkbFree(prev_types);
+		map->num_types= map->size_types= 0;
+		return BadAlloc;
+	    }
+	    map->size_types= nTotalTypes;
+	    bzero(&map->types[map->num_types], 
+		  ((map->size_types-map->num_types)*sizeof(XkbKeyTypeRec)));
+	}
+    }
+    if (which&XkbKeySymsMask) {
+	int nKeys= XkbNumKeys(xkb);
+	if (map->syms==NULL) {
+	    map->size_syms= (nKeys*15)/10;
+	    map->syms= _XkbTypedCalloc(map->size_syms,KeySym);
+	    if (!map->syms) {
+		map->size_syms= 0;
+		return BadAlloc;
+	    }
+	    map->num_syms= 1;
+	    map->syms[0]= NoSymbol;
+	}
+	if (map->key_sym_map==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->key_sym_map= _XkbTypedCalloc(i,XkbSymMapRec);
+	    if (map->key_sym_map==NULL)
+		return BadAlloc;
+	}
+    }
+    if (which&XkbModifierMapMask) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code))
+	    return BadMatch;
+	if (map->modmap==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->modmap= _XkbTypedCalloc(i,unsigned char);
+	    if (map->modmap==NULL)
+		return BadAlloc;
+	}
+    }
+    return Success;
+}
+
+Status
+XkbAllocServerMap(XkbDescPtr xkb,unsigned which,unsigned nNewActions)
+{
+register int	i;
+XkbServerMapPtr map;
+
+    if (xkb==NULL)
+	return BadMatch;
+    if (xkb->server==NULL) {
+	map= _XkbTypedCalloc(1,XkbServerMapRec);
+	if (map==NULL)
+	    return BadAlloc;
+	for (i=0;i<XkbNumVirtualMods;i++) {
+	    map->vmods[i]= XkbNoModifierMask;
+	}
+	xkb->server= map;
+    }
+    else map= xkb->server;
+    if (which&XkbExplicitComponentsMask) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code))
+	    return BadMatch;
+	if (map->explicit==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->explicit= _XkbTypedCalloc(i,unsigned char);
+	    if (map->explicit==NULL)
+		return BadAlloc;
+	}
+    }
+    if (which&XkbKeyActionsMask) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code))
+	    return BadMatch;
+        if (nNewActions<1)
+	    nNewActions= 1;
+	if (map->acts==NULL) {
+	    map->acts= _XkbTypedCalloc((nNewActions+1),XkbAction);
+	    if (map->acts==NULL)
+		return BadAlloc;
+	    map->num_acts= 1;
+	    map->size_acts= nNewActions+1;
+	}
+	else if ((map->size_acts-map->num_acts)<nNewActions) {
+	    unsigned need;
+	    XkbAction *prev_acts = map->acts;
+	    need= map->num_acts+nNewActions;
+	    map->acts= _XkbTypedRealloc(map->acts,need,XkbAction);
+	    if (map->acts==NULL) {
+		_XkbFree(prev_acts);
+	        map->num_acts= map->size_acts= 0;
+	        return BadAlloc;
+	    }
+	    map->size_acts= need;
+	    bzero(&map->acts[map->num_acts], 
+		    ((map->size_acts-map->num_acts)*sizeof(XkbAction)));
+	}
+	if (map->key_acts==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->key_acts= _XkbTypedCalloc(i,unsigned short);
+	    if (map->key_acts==NULL)
+		return BadAlloc;
+	}
+    }
+    if (which&XkbKeyBehaviorsMask) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code))
+	    return BadMatch;
+	if (map->behaviors==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->behaviors= _XkbTypedCalloc(i,XkbBehavior);
+	    if (map->behaviors==NULL)
+		return BadAlloc;
+	}
+    }
+    if (which&XkbVirtualModMapMask) {
+	if ((!XkbIsLegalKeycode(xkb->min_key_code))||
+	    (!XkbIsLegalKeycode(xkb->max_key_code))||
+	    (xkb->max_key_code<xkb->min_key_code))
+	    return BadMatch;
+	if (map->vmodmap==NULL) {
+	    i= xkb->max_key_code+1;
+	    map->vmodmap= _XkbTypedCalloc(i,unsigned short);
+	    if (map->vmodmap==NULL)
+		return BadAlloc;
+	}
+    }
+    return Success;
+}
+
+/***====================================================================***/
+
+Status
+XkbCopyKeyType(XkbKeyTypePtr from,XkbKeyTypePtr into)
+{
+    if ((!from)||(!into))
+	return BadMatch;
+    if (into->map) {
+	_XkbFree(into->map);
+	into->map= NULL;
+    }
+    if (into->preserve) {
+	_XkbFree(into->preserve);
+	into->preserve= NULL;
+    }
+    if (into->level_names) {
+	_XkbFree(into->level_names);
+	into->level_names= NULL;
+    }
+    *into= *from;
+    if ((from->map)&&(into->map_count>0)) {
+	into->map= _XkbTypedCalloc(into->map_count,XkbKTMapEntryRec);
+	if (!into->map)
+	    return BadAlloc;
+	memcpy(into->map,from->map,into->map_count*sizeof(XkbKTMapEntryRec));
+    }
+    if ((from->preserve)&&(into->map_count>0)) {
+	into->preserve= _XkbTypedCalloc(into->map_count,XkbModsRec);
+	if (!into->preserve)
+	    return BadAlloc;
+	memcpy(into->preserve,from->preserve,
+				into->map_count*sizeof(XkbModsRec));
+    }
+    if ((from->level_names)&&(into->num_levels>0)) {
+	into->level_names= _XkbTypedCalloc(into->num_levels,Atom);
+	if (!into->level_names)
+	    return BadAlloc;
+	memcpy(into->level_names,from->level_names,
+				 into->num_levels*sizeof(Atom));
+    }
+    return Success;
+}
+
+Status
+XkbCopyKeyTypes(XkbKeyTypePtr from,XkbKeyTypePtr into,int num_types)
+{
+register int i,rtrn;
+
+    if ((!from)||(!into)||(num_types<0))
+	return BadMatch;
+    for (i=0;i<num_types;i++) {
+	if ((rtrn= XkbCopyKeyType(from++,into++))!=Success)
+	    return rtrn;
+    }
+    return Success;
+}
+
+XkbKeyTypePtr
+XkbAddKeyType(	XkbDescPtr	xkb,
+		Atom 		name,
+		int 		map_count,
+		Bool 		want_preserve,
+		int		num_lvls)
+{
+register int 	i;
+unsigned	tmp;
+XkbKeyTypePtr	type;
+XkbClientMapPtr	map;
+
+    if ((!xkb)||(num_lvls<1))
+	return NULL;
+    map= xkb->map;
+    if ((map)&&(map->types)) {
+	for (i=0;i<map->num_types;i++) {
+	    if (map->types[i].name==name) {
+		Status status;
+		status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
+		return (status==Success?&map->types[i]:NULL);
+	    }
+	}
+    }
+    if ((!map)||(!map->types)||(!map->num_types<XkbNumRequiredTypes)) {
+	tmp= XkbNumRequiredTypes+1;
+	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,tmp)!=Success)
+	    return NULL;
+	tmp= 0;
+	if (map->num_types<=XkbKeypadIndex)
+	    tmp|= XkbKeypadMask;
+	if (map->num_types<=XkbAlphabeticIndex)
+	    tmp|= XkbAlphabeticMask;
+	if (map->num_types<=XkbTwoLevelIndex)
+	    tmp|= XkbTwoLevelMask;
+	if (map->num_types<=XkbOneLevelIndex)
+	    tmp|= XkbOneLevelMask;
+	if (XkbInitCanonicalKeyTypes(xkb,tmp,XkbNoModifier)==Success) {
+	    for (i=0;i<map->num_types;i++) {
+		Status status;
+		if (map->types[i].name!=name)
+		    continue;
+		status=XkbResizeKeyType(xkb,i,map_count,want_preserve,num_lvls);
+		return (status==Success?&map->types[i]:NULL);
+	    }
+	}
+    }
+    if ((map->num_types<=map->size_types)&&
+	(XkbAllocClientMap(xkb,XkbKeyTypesMask,map->num_types+1)!=Success)) {
+	return NULL;
+    }
+    type= &map->types[map->num_types];
+    map->num_types++;
+    bzero((char *)type,sizeof(XkbKeyTypeRec));
+    type->num_levels=	num_lvls;
+    type->map_count=	map_count;
+    type->name=		name;
+    if (map_count>0) {
+	type->map=	_XkbTypedCalloc(map_count,XkbKTMapEntryRec);
+	if (!type->map) {
+	    map->num_types--;
+	    return NULL;
+	}
+	if (want_preserve) {
+	    type->preserve=	_XkbTypedCalloc(map_count,XkbModsRec);
+	    if (!type->preserve) {
+		_XkbFree(type->map);
+		map->num_types--;
+		return NULL;
+	    }
+	}
+    }
+    return type;
+}
+
+Status
+XkbResizeKeyType(	XkbDescPtr	xkb,
+			int		type_ndx,
+			int		map_count,
+			Bool		want_preserve,
+			int		new_num_lvls)
+{
+XkbKeyTypePtr	type;
+KeyCode		matchingKeys[XkbMaxKeyCount],nMatchingKeys;
+
+    if ((type_ndx<0)||(type_ndx>=xkb->map->num_types)||(map_count<0)||
+    							(new_num_lvls<1))
+	return BadValue;
+    switch (type_ndx) {
+	case XkbOneLevelIndex:
+	    if (new_num_lvls!=1)
+		return BadMatch;
+	    break;
+	case XkbTwoLevelIndex:
+	case XkbAlphabeticIndex:
+	case XkbKeypadIndex:
+	    if (new_num_lvls!=2)
+		return BadMatch;
+	    break;
+    }
+    type= &xkb->map->types[type_ndx];
+    if (map_count==0) {
+	if (type->map!=NULL)
+	    _XkbFree(type->map);
+	type->map= NULL;
+	if (type->preserve!=NULL)
+	    _XkbFree(type->preserve);
+	type->preserve= NULL;
+	type->map_count= 0;
+    }
+    else {
+	XkbKTMapEntryRec *prev_map = type->map;
+
+	if ((map_count>type->map_count)||(type->map==NULL))
+	    type->map=_XkbTypedRealloc(type->map,map_count,XkbKTMapEntryRec);
+	if (!type->map) {
+	    if (prev_map) 
+		_XkbFree(prev_map);
+	    return BadAlloc;
+	}
+	if (want_preserve) {
+	    XkbModsRec *prev_preserve = type->preserve;
+
+	    if ((map_count>type->map_count)||(type->preserve==NULL)) {
+		type->preserve= _XkbTypedRealloc(type->preserve,map_count,
+	     						    XkbModsRec);
+	    }
+	    if (!type->preserve) {
+		if (prev_preserve) 
+		    _XkbFree(prev_preserve);
+		return BadAlloc;
+	    }
+	}
+	else if (type->preserve!=NULL) {
+	    _XkbFree(type->preserve);
+	    type->preserve= NULL;
+	}
+	type->map_count= map_count;
+    }
+
+    if ((new_num_lvls>type->num_levels)||(type->level_names==NULL)) {
+	Atom * prev_level_names = type->level_names;
+
+	type->level_names=_XkbTypedRealloc(type->level_names,new_num_lvls,Atom);
+	if (!type->level_names) {
+	    if (prev_level_names) 
+		_XkbFree(prev_level_names);
+	    return BadAlloc;
+	}
+    }
+    /*
+     * Here's the theory:
+     *    If the width of the type changed, we might have to resize the symbol
+     * maps for any keys that use the type for one or more groups.  This is
+     * expensive, so we'll try to cull out any keys that are obviously okay:
+     * In any case:
+     *    - keys that have a group width <= the old width are okay (because
+     *      they could not possibly have been associated with the old type)
+     * If the key type increased in size:
+     *    - keys that already have a group width >= to the new width are okay
+     *    + keys that have a group width >= the old width but < the new width
+     *      might have to be enlarged.
+     * If the key type decreased in size:
+     *    - keys that have a group width > the old width don't have to be
+     *      resized (because they must have some other wider type associated 
+     *      with some group).
+     *    + keys that have a group width == the old width might have to be
+     *      shrunk.
+     * The possibilities marked with '+' require us to examine the key types
+     * associated with each group for the key.
+     */
+    bzero(matchingKeys,XkbMaxKeyCount*sizeof(KeyCode));
+    nMatchingKeys= 0;
+    if (new_num_lvls>type->num_levels) {
+	int	 		nTotal;
+	KeySym	*		newSyms;
+	int			width,match,nResize;
+	register int		i,g,nSyms;
+
+	nResize= 0;
+	for (nTotal=1,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	    width= XkbKeyGroupsWidth(xkb,i);
+	    if (width<type->num_levels)
+		continue;
+	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
+		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
+		    matchingKeys[nMatchingKeys++]= i;
+		    match= 1;
+		}
+	    }
+	    if ((!match)||(width>=new_num_lvls))
+		nTotal+= XkbKeyNumSyms(xkb,i);
+	    else {
+		nTotal+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
+		nResize++;
+	    }
+	}
+	if (nResize>0) {
+	    int nextMatch;
+	    xkb->map->size_syms= (nTotal*12)/10;
+	    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
+	    if (newSyms==NULL)
+		return BadAlloc;
+	    nextMatch= 0;
+	    nSyms= 1;
+	    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+		if (matchingKeys[nextMatch]==i) {
+		    KeySym *pOld;
+		    nextMatch++;
+		    width= XkbKeyGroupsWidth(xkb,i);
+		    pOld= XkbKeySymsPtr(xkb,i);
+		    for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
+			memcpy(&newSyms[nSyms+(new_num_lvls*g)],&pOld[width*g],
+							width*sizeof(KeySym));
+		    }
+		    xkb->map->key_sym_map[i].offset= nSyms;
+		    nSyms+= XkbKeyNumGroups(xkb,i)*new_num_lvls;
+		}
+		else {
+		    memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),
+					XkbKeyNumSyms(xkb,i)*sizeof(KeySym));
+		    xkb->map->key_sym_map[i].offset= nSyms;
+		    nSyms+= XkbKeyNumSyms(xkb,i);
+		}
+	    }
+	    type->num_levels= new_num_lvls;
+	    _XkbFree(xkb->map->syms);
+	    xkb->map->syms= newSyms;
+	    xkb->map->num_syms= nSyms;
+	    return Success;
+	}
+    }
+    else if (new_num_lvls<type->num_levels) {
+	int 		width,match;
+	register int	g,i;
+	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	    width= XkbKeyGroupsWidth(xkb,i);
+	    if (width<type->num_levels)
+		continue;
+	    for (match=0,g=XkbKeyNumGroups(xkb,i)-1;(g>=0)&&(!match);g--) {
+		if (XkbKeyKeyTypeIndex(xkb,i,g)==type_ndx) {
+		    matchingKeys[nMatchingKeys++]= i;
+		    match= 1;
+		}
+	    }
+	}
+    }
+    if (nMatchingKeys>0) {
+	int 		key,firstClear;
+	register int	i,g;
+	if (new_num_lvls>type->num_levels)
+	     firstClear= type->num_levels;
+	else firstClear= new_num_lvls;
+	for (i=0;i<nMatchingKeys;i++) {
+	    KeySym *	pSyms;
+	    int		width,nClear;
+
+	    key= matchingKeys[i];
+	    width= XkbKeyGroupsWidth(xkb,key);
+	    nClear= width-firstClear;
+	    pSyms= XkbKeySymsPtr(xkb,key);
+	    for (g=XkbKeyNumGroups(xkb,key)-1;g>=0;g--) {
+		if (XkbKeyKeyTypeIndex(xkb,key,g)==type_ndx) {
+		    if (nClear>0)
+			bzero(&pSyms[g*width+firstClear],nClear*sizeof(KeySym));
+		}
+	    }
+	}
+    }
+    type->num_levels= new_num_lvls;
+    return Success;
+}
+
+KeySym *
+XkbResizeKeySyms(XkbDescPtr xkb,int key,int needed)
+{
+register int i,nSyms,nKeySyms;
+unsigned nOldSyms;
+KeySym	*newSyms;
+
+    if (needed==0) {
+	xkb->map->key_sym_map[key].offset= 0;
+	return xkb->map->syms;
+    }
+    nOldSyms= XkbKeyNumSyms(xkb,key);
+    if (nOldSyms>=(unsigned)needed) {
+	return XkbKeySymsPtr(xkb,key);
+    }
+    if (xkb->map->size_syms-xkb->map->num_syms>=(unsigned)needed) {
+	if (nOldSyms>0) {
+	    memcpy(&xkb->map->syms[xkb->map->num_syms],XkbKeySymsPtr(xkb,key),
+						nOldSyms*sizeof(KeySym));
+	}
+	if ((needed-nOldSyms)>0) {
+	    bzero(&xkb->map->syms[xkb->map->num_syms+XkbKeyNumSyms(xkb,key)],
+					(needed-nOldSyms)*sizeof(KeySym));
+	}
+	xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
+	xkb->map->num_syms+= needed;
+	return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
+    }
+    xkb->map->size_syms+= (needed>32?needed:32);
+    newSyms = _XkbTypedCalloc(xkb->map->size_syms,KeySym);
+    if (newSyms==NULL)
+	return NULL;
+    newSyms[0]= NoSymbol;
+    nSyms = 1;
+    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
+	int nCopy;
+
+	nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
+	if ((nKeySyms==0)&&(i!=key))
+	    continue;
+	if (i==key)
+	    nKeySyms= needed;
+	if (nCopy!=0)
+	   memcpy(&newSyms[nSyms],XkbKeySymsPtr(xkb,i),nCopy*sizeof(KeySym));
+	if (nKeySyms>nCopy)
+	    bzero(&newSyms[nSyms+nCopy],(nKeySyms-nCopy)*sizeof(KeySym));
+	xkb->map->key_sym_map[i].offset = nSyms;
+	nSyms+= nKeySyms;
+    }
+    _XkbFree(xkb->map->syms);
+    xkb->map->syms = newSyms;
+    xkb->map->num_syms = nSyms;
+    return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
+}
+
+static unsigned
+_ExtendRange(	unsigned int 	old_flags,
+		unsigned int	flag,
+		KeyCode		newKC,
+		KeyCode *	old_min,
+		unsigned char *	old_num)
+{
+    if ((old_flags&flag)==0) {
+	old_flags|= flag;
+	*old_min= newKC;
+	*old_num= 1;
+    }
+    else {
+	int	last= (*old_min)+(*old_num)-1;
+	if (newKC<*old_min) {
+	    *old_min= newKC;
+	    *old_num= (last-newKC)+1;
+	}
+	else if (newKC>last) {
+	    *old_num= (newKC-(*old_min))+1;
+	}
+    }
+    return old_flags;
+}
+
+Status
+XkbChangeKeycodeRange(	XkbDescPtr	xkb,
+			int 		minKC,
+			int 		maxKC,
+			XkbChangesPtr	changes)
+{
+int	tmp;
+
+    if ((!xkb)||(minKC<XkbMinLegalKeyCode)||(maxKC>XkbMaxLegalKeyCode))
+	return BadValue;
+    if (minKC>maxKC)
+	return BadMatch;
+    if (minKC<xkb->min_key_code) {
+	if (changes)
+	    changes->map.min_key_code= minKC;
+	tmp= xkb->min_key_code-minKC;
+	if (xkb->map)  {
+	    if (xkb->map->key_sym_map) {
+		bzero((char *)&xkb->map->key_sym_map[minKC],
+					tmp*sizeof(XkbSymMapRec));
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    				XkbKeySymsMask,minKC,
+	    					&changes->map.first_key_sym,
+	    					&changes->map.num_key_syms);
+		}
+	    }
+	    if (xkb->map->modmap) {
+		bzero((char *)&xkb->map->modmap[minKC],tmp);
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    				XkbModifierMapMask,minKC,
+	    					&changes->map.first_modmap_key,
+	    					&changes->map.num_modmap_keys);
+		}
+	    }
+	}
+	if (xkb->server) {
+	    if (xkb->server->behaviors) {
+		bzero((char *)&xkb->server->behaviors[minKC],
+						tmp*sizeof(XkbBehavior));
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbKeyBehaviorsMask,minKC,
+    					&changes->map.first_key_behavior,
+    					&changes->map.num_key_behaviors);
+		}
+	    }
+	    if (xkb->server->key_acts) {
+		bzero((char *)&xkb->server->key_acts[minKC],
+						tmp*sizeof(unsigned short));
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbKeyActionsMask,minKC,
+    					&changes->map.first_key_act,
+    					&changes->map.num_key_acts);
+		}
+	    }
+	    if (xkb->server->vmodmap) {
+		bzero((char *)&xkb->server->vmodmap[minKC],
+						tmp*sizeof(unsigned short));
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbVirtualModMapMask,minKC,
+		    			&changes->map.first_modmap_key,
+    					&changes->map.num_vmodmap_keys);
+		}
+	    }
+	}
+	if ((xkb->names)&&(xkb->names->keys)) {
+	    bzero((char *)&xkb->names->keys[minKC],tmp*sizeof(XkbKeyNameRec));
+	    if (changes) {
+		changes->names.changed= _ExtendRange(changes->names.changed,
+					XkbKeyNamesMask,minKC,
+					&changes->names.first_key,
+    					&changes->names.num_keys);
+	    }
+	}
+	xkb->min_key_code= minKC;
+    }
+    if (maxKC>xkb->max_key_code) {
+	if (changes)
+	    changes->map.max_key_code= maxKC;
+	tmp= maxKC-xkb->max_key_code;
+	if (xkb->map)  {
+	    if (xkb->map->key_sym_map) {
+		XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
+
+		xkb->map->key_sym_map= _XkbTypedRealloc(xkb->map->key_sym_map,
+						(maxKC+1),XkbSymMapRec);
+		if (!xkb->map->key_sym_map) {
+		    _XkbFree(prev_key_sym_map);
+		    return BadAlloc;
+		}
+#ifdef NXAGENT_SERVER
+                bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code+1],
+                                        tmp*sizeof(XkbSymMapRec));
+#else
+		bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
+					tmp*sizeof(XkbSymMapRec));
+#endif
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    				XkbKeySymsMask,maxKC,
+	    					&changes->map.first_key_sym,
+	    					&changes->map.num_key_syms);
+		}
+	    }
+	    if (xkb->map->modmap) {
+		unsigned char *prev_modmap = xkb->map->modmap;
+
+		xkb->map->modmap= _XkbTypedRealloc(xkb->map->modmap,
+						(maxKC+1),unsigned char);
+		if (!xkb->map->modmap) {
+		    _XkbFree(prev_modmap);
+		    return BadAlloc;
+		}
+#ifdef NXAGENT_SERVER
+                bzero((char *)&xkb->map->modmap[xkb->max_key_code+1],tmp);
+#else
+		bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
+#endif
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    				XkbModifierMapMask,maxKC,
+	    					&changes->map.first_modmap_key,
+	    					&changes->map.num_modmap_keys);
+		}
+	    }
+	}
+	if (xkb->server) {
+	    if (xkb->server->behaviors) {
+		XkbBehavior *prev_behaviors = xkb->server->behaviors;
+
+		xkb->server->behaviors=_XkbTypedRealloc(xkb->server->behaviors,
+						(maxKC+1),XkbBehavior);
+		if (!xkb->server->behaviors) {
+		    _XkbFree(prev_behaviors);
+		    return BadAlloc;
+		}
+#ifdef NXAGENT_SERVER
+                bzero((char *)&xkb->server->behaviors[xkb->max_key_code+1],
+                                                tmp*sizeof(XkbBehavior));
+#else
+		bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
+						tmp*sizeof(XkbBehavior));
+#endif
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbKeyBehaviorsMask,maxKC,
+    					&changes->map.first_key_behavior,
+    					&changes->map.num_key_behaviors);
+		}
+	    }
+	    if (xkb->server->key_acts) {
+		unsigned short *prev_key_acts = xkb->server->key_acts;
+
+		xkb->server->key_acts= _XkbTypedRealloc(xkb->server->key_acts,
+						(maxKC+1),unsigned short);
+		if (!xkb->server->key_acts) {
+		    _XkbFree(prev_key_acts);
+		    return BadAlloc;
+		}
+#ifdef NXAGENT_SERVER
+                bzero((char *)&xkb->server->key_acts[xkb->max_key_code+1],
+                                                tmp*sizeof(unsigned short));
+#else
+		bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
+						tmp*sizeof(unsigned short));
+#endif
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbKeyActionsMask,maxKC,
+    					&changes->map.first_key_act,
+    					&changes->map.num_key_acts);
+		}
+	    }
+	    if (xkb->server->vmodmap) {
+		unsigned short *prev_vmodmap = xkb->server->vmodmap;
+
+		xkb->server->vmodmap= _XkbTypedRealloc(xkb->server->vmodmap,
+						(maxKC+1),unsigned short);
+		if (!xkb->server->vmodmap) {
+		    _XkbFree(prev_vmodmap);
+		    return BadAlloc;
+		}
+#ifdef NXAGENT_SERVER
+                bzero((char *)&xkb->server->vmodmap[xkb->max_key_code+1],
+                                                tmp*sizeof(unsigned short));
+#else
+		bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
+						tmp*sizeof(unsigned short));
+#endif
+		if (changes) {
+		    changes->map.changed= _ExtendRange(changes->map.changed,
+		    			XkbVirtualModMapMask,maxKC,
+		    			&changes->map.first_modmap_key,
+    					&changes->map.num_vmodmap_keys);
+		}
+	    }
+	}
+	if ((xkb->names)&&(xkb->names->keys)) {
+	    XkbKeyNameRec *prev_keys = xkb->names->keys;
+
+	    xkb->names->keys= _XkbTypedRealloc(xkb->names->keys,
+	    					(maxKC+1),XkbKeyNameRec);
+	    if (!xkb->names->keys) {
+		_XkbFree(prev_keys);
+		return BadAlloc;
+	    }
+#ifdef NXAGENT_SERVER
+            bzero((char *)&xkb->names->keys[xkb->max_key_code+1],
+                                                tmp*sizeof(XkbKeyNameRec));
+#else
+	    bzero((char *)&xkb->names->keys[xkb->max_key_code],
+	    					tmp*sizeof(XkbKeyNameRec));
+#endif
+	    if (changes) {
+		changes->names.changed= _ExtendRange(changes->names.changed,
+					XkbKeyNamesMask,maxKC,
+					&changes->names.first_key,
+    					&changes->names.num_keys);
+	    }
+	}
+	xkb->max_key_code= maxKC;
+    }
+    return Success;
+}
+
+XkbAction *
+XkbResizeKeyActions(XkbDescPtr xkb,int key,int needed)
+{
+register int i,nActs;
+XkbAction *newActs;
+
+    if (needed==0) {
+	xkb->server->key_acts[key]= 0;
+	return NULL;
+    }
+    if (XkbKeyHasActions(xkb,key)&&(XkbKeyNumSyms(xkb,key)>=(unsigned)needed))
+	return XkbKeyActionsPtr(xkb,key);
+    if (xkb->server->size_acts-xkb->server->num_acts>=(unsigned)needed) {
+	xkb->server->key_acts[key]= xkb->server->num_acts;
+	xkb->server->num_acts+= needed;
+	return &xkb->server->acts[xkb->server->key_acts[key]];
+    }
+    xkb->server->size_acts= xkb->server->num_acts+needed+8;
+    newActs = _XkbTypedCalloc(xkb->server->size_acts,XkbAction);
+    if (newActs==NULL)
+	return NULL;
+    newActs[0].type = XkbSA_NoAction;
+    nActs = 1;
+    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
+	int nKeyActs,nCopy;
+
+	if ((xkb->server->key_acts[i]==0)&&(i!=key))
+	    continue;
+
+	nCopy= nKeyActs= XkbKeyNumActions(xkb,i);
+	if (i==key) {
+	    nKeyActs= needed;
+	    if (needed<nCopy)
+		nCopy= needed;
+	}
+
+	if (nCopy>0)
+	    memcpy(&newActs[nActs],XkbKeyActionsPtr(xkb,i),
+						nCopy*sizeof(XkbAction));
+	if (nCopy<nKeyActs)
+	    bzero(&newActs[nActs+nCopy],(nKeyActs-nCopy)*sizeof(XkbAction));
+	xkb->server->key_acts[i]= nActs;
+	nActs+= nKeyActs;
+    }
+    _XkbFree(xkb->server->acts);
+    xkb->server->acts = newActs;
+    xkb->server->num_acts= nActs;
+    return &xkb->server->acts[xkb->server->key_acts[key]];
+}
+
+void
+XkbFreeClientMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
+{
+XkbClientMapPtr	map;
+
+    if ((xkb==NULL)||(xkb->map==NULL))
+	return;
+    if (freeMap)
+	what= XkbAllClientInfoMask;
+    map= xkb->map;
+    if (what&XkbKeyTypesMask) {
+	if (map->types!=NULL) {
+	    if (map->num_types>0) {
+		register int 	i;
+		XkbKeyTypePtr	type;
+		for (i=0,type=map->types;i<map->num_types;i++,type++) {
+		    if (type->map!=NULL) {
+			_XkbFree(type->map);
+			type->map= NULL;
+		    }
+		    if (type->preserve!=NULL) {
+			_XkbFree(type->preserve);
+			type->preserve= NULL;
+		    }
+		    type->map_count= 0;
+		    if (type->level_names!=NULL) {
+			_XkbFree(type->level_names);
+			type->level_names= NULL;
+		    }
+		}
+	    }
+	    _XkbFree(map->types);
+	    map->num_types= map->size_types= 0;
+	    map->types= NULL;
+	}
+    }
+    if (what&XkbKeySymsMask) {
+	if (map->key_sym_map!=NULL) {
+	    _XkbFree(map->key_sym_map);
+	    map->key_sym_map= NULL;
+	}
+	if (map->syms!=NULL) {
+	    _XkbFree(map->syms);
+	    map->size_syms= map->num_syms= 0;
+	    map->syms= NULL;
+	}
+    }
+    if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) {
+	_XkbFree(map->modmap);
+	map->modmap= NULL;
+    }
+    if (freeMap) {
+	_XkbFree(xkb->map);
+	xkb->map= NULL;
+    }
+    return;
+}
+
+void
+XkbFreeServerMap(XkbDescPtr xkb,unsigned what,Bool freeMap)
+{
+XkbServerMapPtr	map;
+
+    if ((xkb==NULL)||(xkb->server==NULL))
+	return;
+    if (freeMap)
+	what= XkbAllServerInfoMask;
+    map= xkb->server;
+    if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) {
+	_XkbFree(map->explicit);
+	map->explicit= NULL;
+    }
+    if (what&XkbKeyActionsMask) {
+	if (map->key_acts!=NULL) {
+	    _XkbFree(map->key_acts);
+	    map->key_acts= NULL;
+	}
+	if (map->acts!=NULL) {
+	    _XkbFree(map->acts);
+	    map->num_acts= map->size_acts= 0;
+	    map->acts= NULL;
+	}
+    }
+    if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) {
+	_XkbFree(map->behaviors);
+	map->behaviors= NULL;
+    }
+    if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) {
+	_XkbFree(map->vmodmap);
+	map->vmodmap= NULL;
+    }
+
+    if (freeMap) {
+	_XkbFree(xkb->server);
+	xkb->server= NULL;
+    }
+    return;
+}
diff --git a/nx-X11/programs/Xserver/xkb/XKBMisc.c b/nx-X11/programs/Xserver/xkb/XKBMisc.c
new file mode 100644
index 000000000..b3012dc4f
--- /dev/null
+++ b/nx-X11/programs/Xserver/xkb/XKBMisc.c
@@ -0,0 +1,975 @@
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be 
+used in advertising or publicity pertaining to distribution 
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability 
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#ifndef XKB_IN_SERVER
+
+#include <stdio.h>
+#include "Xlibint.h"
+#include <nx-X11/extensions/XKBproto.h>
+#include <nx-X11/keysym.h>
+#include "XKBlibint.h"
+
+#else 
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <nx-X11/keysym.h>
+#define	XKBSRV_NEED_FILE_FUNCS
+#include <nx-X11/extensions/XKBsrv.h>
+
+#endif /* XKB_IN_SERVER */
+
+/***====================================================================***/
+
+#define	mapSize(m)	(sizeof(m)/sizeof(XkbKTMapEntryRec))
+static  XkbKTMapEntryRec map2Level[]= { 
+  { True, ShiftMask, {1, ShiftMask, 0} }
+};
+
+static  XkbKTMapEntryRec mapAlpha[]= { 
+  { True, ShiftMask, { 1, ShiftMask, 0 } },
+  { True, LockMask,  { 0,  LockMask, 0 } }
+};
+
+static	XkbModsRec preAlpha[]= {
+	{        0,        0, 0 },
+	{ LockMask, LockMask, 0 }
+};
+
+#define	NL_VMOD_MASK	0
+static  XkbKTMapEntryRec mapKeypad[]= { 
+	{ True,	ShiftMask, { 1, ShiftMask,            0 } },
+	{ False,        0, { 1,         0, NL_VMOD_MASK } }
+};
+
+static	XkbKeyTypeRec	canonicalTypes[XkbNumRequiredTypes] = {
+	{ { 0, 0, 0 }, 
+	  1,	/* num_levels */
+	  0,	/* map_count */
+	  NULL,		NULL,
+	  None,		NULL
+	},
+	{ { ShiftMask, ShiftMask, 0 }, 
+	  2,	/* num_levels */
+	  mapSize(map2Level),	/* map_count */
+	  map2Level,	NULL,
+	  None,		NULL
+	},
+	{ { ShiftMask|LockMask, ShiftMask|LockMask, 0 }, 
+	  2,				/* num_levels */
+	  mapSize(mapAlpha),		/* map_count */
+	  mapAlpha,	preAlpha,
+	  None,		NULL
+	},
+	{ { ShiftMask, ShiftMask, NL_VMOD_MASK },
+	  2,				/* num_levels */
+	  mapSize(mapKeypad),		/* map_count */
+	  mapKeypad,	NULL,
+	  None,		NULL
+	}
+};
+
+Status
+XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod)
+{
+XkbClientMapPtr	map;
+XkbKeyTypePtr	from,to;
+Status		rtrn;
+
+    if (!xkb)
+	return BadMatch;
+    rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes);
+    if (rtrn!=Success)
+	return rtrn;
+    map= xkb->map;
+    if ((which&XkbAllRequiredTypes)==0)
+	return Success;
+    rtrn= Success;
+    from= canonicalTypes;
+    to= map->types;
+    if (which&XkbOneLevelMask)
+	rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]);
+    if ((which&XkbTwoLevelMask)&&(rtrn==Success))
+	rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]);
+    if ((which&XkbAlphabeticMask)&&(rtrn==Success))
+	rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]);
+    if ((which&XkbKeypadMask)&&(rtrn==Success)) {
+	XkbKeyTypePtr type;
+	rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]);
+	type= &to[XkbKeypadIndex];
+	if ((keypadVMod>=0)&&(keypadVMod<XkbNumVirtualMods)&&(rtrn==Success)) {
+	    type->mods.vmods= (1<<keypadVMod);
+	    type->map[0].active= True;
+	    type->map[0].mods.mask= ShiftMask;
+	    type->map[0].mods.real_mods= ShiftMask;
+	    type->map[0].mods.vmods= 0;
+	    type->map[0].level= 1;
+	    type->map[1].active= False;
+	    type->map[1].mods.mask= 0;
+	    type->map[1].mods.real_mods= 0;
+	    type->map[1].mods.vmods= (1<<keypadVMod);
+	    type->map[1].level= 1;
+	}
+    }
+    return Success;
+}
+
+/***====================================================================***/
+
+#define	CORE_SYM(i)	(i<map_width?core_syms[i]:NoSymbol)
+#define	XKB_OFFSET(g,l)	(((g)*groupsWidth)+(l))
+
+int
+XkbKeyTypesForCoreSymbols(	XkbDescPtr	xkb,
+				int		map_width,
+				KeySym *	core_syms,
+				unsigned int 	protected,
+    				int *		types_inout,
+				KeySym *	xkb_syms_rtrn)
+{
+register int	i;
+unsigned int	empty;
+int		nSyms[XkbNumKbdGroups];
+int		nGroups,tmp,groupsWidth;
+
+    /* Section 12.2 of the protocol describes this process in more detail */
+    /* Step 1:  find the # of symbols in the core mapping per group */
+    groupsWidth= 2;
+    for (i=0;i<XkbNumKbdGroups;i++) {
+	if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) {
+	    nSyms[i]= xkb->map->types[types_inout[i]].num_levels;
+	    if (nSyms[i]>groupsWidth)
+		groupsWidth= nSyms[i];
+	}
+	else {
+	    types_inout[i]= XkbTwoLevelIndex;	/* don't really know, yet */
+	    nSyms[i]= 2;
+	}
+    }
+    if (nSyms[XkbGroup1Index]<2)
+	nSyms[XkbGroup1Index]= 2;
+    if (nSyms[XkbGroup2Index]<2)
+	nSyms[XkbGroup2Index]= 2;
+    /* Step 2:	Copy the symbols from the core ordering to XKB ordering	*/
+    /*		symbols in the core are in the order:			*/
+    /*		G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*]	*/
+    xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0);
+    xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1);
+    for (i=2;i<nSyms[XkbGroup1Index];i++) {
+	xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i);
+    }
+    xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2);
+    xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3);
+    tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */
+    for (i=2;i<nSyms[XkbGroup2Index];i++) {
+	xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
+    }
+    tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
+    if ((tmp>=map_width)&&
+	 ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
+	nSyms[XkbGroup3Index]= 0;
+	nSyms[XkbGroup4Index]= 0;
+	nGroups= 2;
+    }
+    else {
+    	nGroups= 3;
+	for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
+	    xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
+	}
+	if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
+	    nGroups= 4;
+	    for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
+		xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
+	    }
+	}
+	else {
+	    nSyms[XkbGroup4Index]= 0;
+	}
+    }
+    /* steps 3&4: alphanumeric expansion,  assign canonical types */
+    empty= 0;
+    for (i=0;i<nGroups;i++) {
+	KeySym *syms;
+	syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
+	if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) {
+	    KeySym upper,lower;
+	    XConvertCase(syms[0],&lower,&upper);
+	    if (upper!=lower) {
+		xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower;
+		xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper;
+		if ((protected&(1<<i))==0)
+		    types_inout[i]= XkbAlphabeticIndex;
+	    }
+	    else if ((protected&(1<<i))==0) {
+		types_inout[i]= XkbOneLevelIndex;
+	/*	nSyms[i]=	1;*/
+	    }
+	}
+	if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) {
+	    if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1]))
+		types_inout[i]= XkbKeypadIndex;
+	    else {
+		KeySym upper,lower;
+		XConvertCase(syms[0],&lower,&upper);
+		if ((syms[0]==lower)&&(syms[1]==upper))
+		    types_inout[i]= XkbAlphabeticIndex;
+	    }
+	}
+	if (syms[0]==NoSymbol) {
+	    register int n;
+	    Bool	found;
+	    for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) {
+		found= (syms[n]!=NoSymbol);
+	    }
+	    if (!found)
+		empty|= (1<<i);
+	}
+    }
+    /* step 5: squoosh out empty groups */
+    if (empty) {
+	for (i=nGroups-1;i>=0;i--) {
+	    if (((empty&(1<<i))==0)||(protected&(1<<i)))
+		break;
+	    nGroups--;
+	}
+    }
+    if (nGroups<1)
+	return 0;
+
+    /* step 6: replicate group 1 into group two, if necessary */
+    if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) {
+	if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) {
+	    nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index];
+	    types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index];
+	    memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn,
+							2*sizeof(KeySym));
+	}
+	else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) {
+	    memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]],
+	    				(char *)xkb_syms_rtrn,
+					nSyms[XkbGroup1Index]*sizeof(KeySym));
+	}
+    }
+
+    /* step 7: check for all groups identical or all width 1 */
+    if (nGroups>1) {
+	Bool sameType,allOneLevel;
+	allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1);
+	for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) {
+	    sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index]));
+	    if (allOneLevel)
+		allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1);
+	}
+	if ((sameType)&&
+	    (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){
+	    register int s;
+	    Bool	identical;
+	    for (i=1,identical=True;identical&&(i<nGroups);i++) {
+		KeySym *syms;
+		syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
+		for (s=0;identical&&(s<nSyms[i]);s++) {
+		    if (syms[s]!=xkb_syms_rtrn[s])
+			identical= False;
+		}
+	    }
+	    if (identical)
+		nGroups= 1;
+	}
+	if (allOneLevel && (nGroups>1)) {
+	    KeySym *syms;
+	    syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
+	    nSyms[XkbGroup1Index]= 1;
+	    for (i=1;i<nGroups;i++) {
+		xkb_syms_rtrn[i]= syms[0];
+		syms+= nSyms[i];
+		nSyms[i]= 1;
+	    }
+	}
+    }
+    return nGroups;
+}
+
+static XkbSymInterpretPtr
+_XkbFindMatchingInterp(	XkbDescPtr	xkb,
+			KeySym 		sym,
+			unsigned int	real_mods,
+			unsigned int	level)
+{
+register unsigned	 i;
+XkbSymInterpretPtr	 interp,rtrn;
+CARD8			 mods;
+
+    rtrn= NULL;
+    interp= xkb->compat->sym_interpret;
+    for (i=0;i<xkb->compat->num_si;i++,interp++) {
+	if ((interp->sym==NoSymbol)||(sym==interp->sym)) {
+	    int match;
+	    if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0))
+		 mods= real_mods;
+	    else mods= 0;
+	    switch (interp->match&XkbSI_OpMask) {
+		case XkbSI_NoneOf:
+		    match= ((interp->mods&mods)==0);
+		    break;
+		case XkbSI_AnyOfOrNone:
+		    match= ((mods==0)||((interp->mods&mods)!=0));
+		    break;
+		case XkbSI_AnyOf:
+		    match= ((interp->mods&mods)!=0);
+		    break;
+		case XkbSI_AllOf:
+		    match= ((interp->mods&mods)==interp->mods);
+		    break;
+		case XkbSI_Exactly:
+		    match= (interp->mods==mods);
+		    break;
+		default:
+		    match= 0;
+		    break;
+	    }
+	    if (match) {
+		if (interp->sym!=NoSymbol) {
+		    return interp;
+		}
+		else if (rtrn==NULL) {
+		    rtrn= interp;
+		}
+	    }
+	}
+    }
+    return rtrn;
+}
+
+static void
+_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey)
+{
+KeyCode	last;
+
+    last= (*pFirst)+(*pNum);
+    if (newKey<*pFirst) {
+	*pFirst= newKey;
+	*pNum= (last-newKey)+1;
+    }
+    else if (newKey>last) {
+	*pNum= (last-*pFirst)+1;
+    }
+    return;
+}
+
+static void
+_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
+{
+unsigned	tmp;
+
+    switch (act->type) {
+	case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
+	    if (act->mods.flags&XkbSA_UseModMapMods)
+		act->mods.real_mods= act->mods.mask= mods;
+	    if ((tmp= XkbModActionVMods(&act->mods))!=0) {
+		XkbVirtualModsToReal(xkb,tmp,&tmp);
+		act->mods.mask|= tmp;
+	    }
+	    break;
+	case XkbSA_ISOLock:
+	    if (act->iso.flags&XkbSA_UseModMapMods)
+		act->iso.real_mods= act->iso.mask= mods;
+	    if ((tmp= XkbModActionVMods(&act->iso))!=0) {
+		XkbVirtualModsToReal(xkb,tmp,&tmp);
+		act->iso.mask|= tmp;
+	    }
+	    break;
+    }
+    return;
+}
+
+#define	IBUF_SIZE	8
+
+Bool
+XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)
+{
+KeySym *		syms;
+unsigned char 		explicit,mods;
+XkbSymInterpretPtr	*interps,ibuf[IBUF_SIZE]; 
+int			n,nSyms,found;
+unsigned		changed,tmp;
+
+    if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)||
+    			(!xkb->compat)||(!xkb->compat->sym_interpret)||
+			(key<xkb->min_key_code)||(key>xkb->max_key_code)) {
+	return False;
+    }
+    if (((!xkb->server)||(!xkb->server->key_acts))&&
+		(XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) {
+	return False;
+    }
+    changed= 0;	/* keeps track of what has changed in _this_ call */
+    explicit= xkb->server->explicit[key];
+    if (explicit&XkbExplicitInterpretMask) /* nothing to do */
+	return True;
+    mods= (xkb->map->modmap?xkb->map->modmap[key]:0);
+    nSyms= XkbKeyNumSyms(xkb,key);
+    syms= XkbKeySymsPtr(xkb,key);
+    if (nSyms>IBUF_SIZE) {
+	interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr);
+	if (interps==NULL) {
+	    interps= ibuf;
+	    nSyms= IBUF_SIZE;
+	}
+    }
+    else {
+	interps= ibuf;
+    }
+    found= 0;
+    for (n=0;n<nSyms;n++) {
+	unsigned level= (n%XkbKeyGroupsWidth(xkb,key));
+	interps[n]= NULL;
+	if (syms[n]!=NoSymbol) {
+	    interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level);
+	    if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction)
+		found++;
+	    else interps[n]= NULL;
+	}
+    }
+    /* 1/28/96 (ef) -- XXX! WORKING HERE */
+    if (!found) {
+	if (xkb->server->key_acts[key]!=0) {
+	    xkb->server->key_acts[key]= 0;
+	    changed|= XkbKeyActionsMask;
+	}
+    }
+    else {
+	XkbAction *pActs;
+	unsigned int	new_vmodmask;
+	changed|= XkbKeyActionsMask;
+	pActs= XkbResizeKeyActions(xkb,key,nSyms);
+	if (!pActs)
+	    return False;
+	new_vmodmask= 0;
+	for (n=0;n<nSyms;n++) {
+	    if (interps[n]) {
+		unsigned effMods;
+
+		pActs[n]= *((XkbAction *)&interps[n]->act);
+		if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) {
+		     effMods= mods;
+		     if (interps[n]->virtual_mod!=XkbNoModifier)
+			new_vmodmask|= (1<<interps[n]->virtual_mod);
+		}
+		else effMods= 0;
+		_XkbSetActionKeyMods(xkb,&pActs[n],effMods);
+	    }
+	    else pActs[n].type= XkbSA_NoAction;
+	}
+	if (((explicit&XkbExplicitVModMapMask)==0)&&
+				(xkb->server->vmodmap[key]!=new_vmodmask)) {
+	    changed|= XkbVirtualModMapMask;
+	    xkb->server->vmodmap[key]= new_vmodmask;
+	}
+	if (interps[0]) {
+	    if ((interps[0]->flags&XkbSI_LockingKey)&&
+				((explicit&XkbExplicitBehaviorMask)==0)) {
+		xkb->server->behaviors[key].type= XkbKB_Lock;
+		changed|= XkbKeyBehaviorsMask;
+	    }
+	    if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
+		CARD8 old;
+		old= xkb->ctrls->per_key_repeat[key/8];
+		if (interps[0]->flags&XkbSI_AutoRepeat)
+		     xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
+		else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8));
+		if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
+		    changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
+	    }
+	}
+    }
+    if ((!found)||(interps[0]==NULL)) {
+	if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
+	    CARD8 old;
+	    old= xkb->ctrls->per_key_repeat[key/8];
+#ifdef RETURN_SHOULD_REPEAT
+	    if (*XkbKeySymsPtr(xkb,key) != XK_Return)
+#endif
+		xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
+	    if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
+		changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
+	}
+	if (((explicit&XkbExplicitBehaviorMask)==0)&&
+		(xkb->server->behaviors[key].type==XkbKB_Lock)) {
+		xkb->server->behaviors[key].type= XkbKB_Default;
+		changed|= XkbKeyBehaviorsMask;
+	}
+    }
+    if (changes) {
+	XkbMapChangesPtr	mc;
+	mc= &changes->map;
+	tmp= (changed&mc->changed);
+	if (tmp&XkbKeyActionsMask)
+	    _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key);
+	else if (changed&XkbKeyActionsMask) {
+	    mc->changed|= XkbKeyActionsMask;
+	    mc->first_key_act= key;
+	    mc->num_key_acts= 1;
+	}
+	if (tmp&XkbKeyBehaviorsMask) {
+	    _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors,
+	    								key);
+	}
+	else if (changed&XkbKeyBehaviorsMask) {
+	    mc->changed|= XkbKeyBehaviorsMask;
+	    mc->first_key_behavior= key;
+	    mc->num_key_behaviors= 1;
+	}
+	if (tmp&XkbVirtualModMapMask)
+	    _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key);
+	else if (changed&XkbVirtualModMapMask) {
+	    mc->changed|= XkbVirtualModMapMask;
+	    mc->first_vmodmap_key= key;
+	    mc->num_vmodmap_keys= 1;
+	}
+	mc->changed|= changed;
+    }
+    if (interps!=ibuf)
+	_XkbFree(interps);
+    return True;
+}
+
+Bool
+XkbUpdateMapFromCore(	XkbDescPtr	xkb,
+			KeyCode		first_key,
+			int		num_keys,
+			int		map_width,
+			KeySym *	core_keysyms,
+			XkbChangesPtr	changes)
+{
+register int	key,last_key;
+KeySym *	syms;
+
+    syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width];
+    if (changes) {
+	if (changes->map.changed&XkbKeySymsMask) {
+	    _XkbAddKeyChange(&changes->map.first_key_sym,
+	    			&changes->map.num_key_syms,first_key);
+	    if (num_keys>1) {
+		_XkbAddKeyChange(&changes->map.first_key_sym,
+						&changes->map.num_key_syms,
+						first_key+num_keys-1);
+	    }
+	}
+	else {
+	    changes->map.changed|= XkbKeySymsMask;
+	    changes->map.first_key_sym= first_key;
+	    changes->map.num_key_syms= num_keys;
+	}
+    }
+    last_key= first_key+num_keys-1;
+    for (key=first_key;key<=last_key;key++,syms+= map_width) {
+	XkbMapChangesPtr	mc;
+	unsigned		explicit;
+	KeySym			tsyms[XkbMaxSymsPerKey];
+	int	 		types[XkbNumKbdGroups];
+	int			nG;
+
+	explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask;
+	types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
+	types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index);
+	types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index);
+	types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index);
+	nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms);
+	if (changes)
+	     mc= &changes->map;
+	else mc= NULL;
+	XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc);
+	memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms,
+					XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
+	XkbApplyCompatMapToKey(xkb,key,changes);
+    }
+
+    if ((xkb->server->vmods!=NULL)&&(xkb->map->modmap!=NULL)&&(changes)&&
+	(changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) {
+	unsigned char		newVMods[XkbNumVirtualMods];
+	register  unsigned 	bit,i;
+	unsigned		present;
+
+	bzero(newVMods,XkbNumVirtualMods);
+	present= 0;
+	for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
+	    if (xkb->server->vmodmap[key]==0)
+		continue;
+	    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+		if (bit&xkb->server->vmodmap[key]) {
+		    present|= bit;
+		    newVMods[i]|= xkb->map->modmap[key];
+		}
+	    }
+	}
+	for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+	    if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) {
+		changes->map.changed|= XkbVirtualModsMask;
+		changes->map.vmods|= bit;
+		xkb->server->vmods[i]= newVMods[i];
+	    }
+	}
+    }
+    if (changes && (changes->map.changed&XkbVirtualModsMask))
+	XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes);
+    return True;
+}
+
+Status
+XkbChangeTypesOfKey(	XkbDescPtr		 xkb,
+			int		 	 key,
+			int			 nGroups,
+			unsigned	 	 groups,
+			int	* 	 	 newTypesIn,
+			XkbMapChangesPtr	 changes)
+{
+XkbKeyTypePtr	pOldType,pNewType;
+register int	i;
+int		width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
+
+    if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
+	(!xkb->map->types)||((groups&XkbAllGroupsMask)==0)||
+	(nGroups>XkbNumKbdGroups)) {
+	return BadMatch;
+    }
+    if (nGroups==0) {
+	for (i=0;i<XkbNumKbdGroups;i++) {
+	    xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex;
+	}
+	i= xkb->map->key_sym_map[key].group_info;
+	i= XkbSetNumGroups(i,0);
+	xkb->map->key_sym_map[key].group_info= i;
+	XkbResizeKeySyms(xkb,key,0);
+	return Success;
+    }
+
+    nOldGroups= XkbKeyNumGroups(xkb,key);
+    oldWidth= XkbKeyGroupsWidth(xkb,key);
+    for (width=i=0;i<nGroups;i++) {
+	if (groups&(1<<i))
+	     newTypes[i]=  newTypesIn[i];
+	else if (i<nOldGroups)
+	     newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i);
+	else if (nOldGroups>0)
+	     newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
+	else newTypes[i]= XkbTwoLevelIndex;
+	if (newTypes[i]>xkb->map->num_types)
+	    return BadMatch;
+	pNewType= &xkb->map->types[newTypes[i]];
+	if (pNewType->num_levels>width)
+	    width= pNewType->num_levels;
+    }
+    if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups))
+	xkb->ctrls->num_groups= nGroups;
+    if ((width!=oldWidth)||(nGroups!=nOldGroups)) {
+	KeySym		oldSyms[XkbMaxSymsPerKey],*pSyms;
+	int		nCopy;
+
+	if (nOldGroups==0) {
+	    pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
+	    if (pSyms!=NULL) {
+		i= xkb->map->key_sym_map[key].group_info;
+		i= XkbSetNumGroups(i,nGroups);
+		xkb->map->key_sym_map[key].group_info= i;
+		xkb->map->key_sym_map[key].width= width;
+		for (i=0;i<nGroups;i++) {
+		    xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
+		}
+		return Success;
+	    }
+	    return BadAlloc;
+	}
+	pSyms= XkbKeySymsPtr(xkb,key);
+	memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
+	pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
+	if (pSyms==NULL)
+	    return BadAlloc;
+	bzero(pSyms,width*nGroups*sizeof(KeySym));
+	for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
+	    pOldType= XkbKeyKeyType(xkb,key,i);
+	    pNewType= &xkb->map->types[newTypes[i]];
+	    if (pNewType->num_levels>pOldType->num_levels)
+		 nCopy= pOldType->num_levels;
+	    else nCopy= pNewType->num_levels;
+	    memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym));
+	}
+	if (XkbKeyHasActions(xkb,key)) {
+	    XkbAction	oldActs[XkbMaxSymsPerKey],*pActs;
+	    pActs= XkbKeyActionsPtr(xkb,key);
+	    memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction));
+	    pActs= XkbResizeKeyActions(xkb,key,width*nGroups);
+	    if (pActs==NULL)
+		return BadAlloc;
+	    bzero(pActs,width*nGroups*sizeof(XkbAction));
+	    for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
+		pOldType= XkbKeyKeyType(xkb,key,i);
+		pNewType= &xkb->map->types[newTypes[i]];
+		if (pNewType->num_levels>pOldType->num_levels)
+		     nCopy= pOldType->num_levels;
+		else nCopy= pNewType->num_levels;
+		memcpy(&pActs[i*width],&oldActs[i*oldWidth],
+						nCopy*sizeof(XkbAction));
+	    }
+	}
+	i= xkb->map->key_sym_map[key].group_info;
+	i= XkbSetNumGroups(i,nGroups);
+	xkb->map->key_sym_map[key].group_info= i;
+	xkb->map->key_sym_map[key].width= width;
+    }
+    width= 0;
+    for (i=0;i<nGroups;i++) {
+	xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
+	if (xkb->map->types[newTypes[i]].num_levels>width)
+	    width= xkb->map->types[newTypes[i]].num_levels;
+    }
+    xkb->map->key_sym_map[key].width= width;
+    if (changes!=NULL) {
+	if (changes->changed&XkbKeySymsMask) {
+	    _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms,
+	    								key);
+	}
+	else {
+	    changes->changed|= XkbKeySymsMask;
+	    changes->first_key_sym= key;
+	    changes->num_key_syms= 1;
+	}
+    }
+    return Success;
+}
+
+/***====================================================================***/
+
+Bool
+XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn)
+{
+register int i,bit;
+register unsigned mask;
+
+    if (xkb==NULL)
+	return False;
+    if (virtual_mask==0) {
+	*mask_rtrn= 0;
+	return True;
+    }
+    if (xkb->server==NULL)
+	return False;
+    for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+	if (virtual_mask&bit)
+	    mask|= xkb->server->vmods[i];
+    }
+    *mask_rtrn= mask;
+    return True;
+}
+
+/***====================================================================***/
+
+Bool
+XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed)
+{
+unsigned int	tmp;
+
+    switch (act->type) {
+	case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
+	    if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) {
+		XkbVirtualModsToReal(xkb,tmp,&tmp);
+		act->mods.mask= act->mods.real_mods;
+		act->mods.mask|= tmp;
+		return True;
+	    }
+	    break;
+	case XkbSA_ISOLock:
+	    if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) {
+		XkbVirtualModsToReal(xkb,tmp,&tmp);
+		act->iso.mask= act->iso.real_mods;
+		act->iso.mask|= tmp;
+		return True;
+	    }
+	    break;
+    }
+    return False;
+}
+
+void
+XkbUpdateKeyTypeVirtualMods(	XkbDescPtr	xkb,
+				XkbKeyTypePtr	type,
+				unsigned int	changed,
+				XkbChangesPtr 	changes)
+{
+register unsigned int	i;
+unsigned int		mask = 0;
+
+    XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
+    type->mods.mask= type->mods.real_mods|mask;
+    if ((type->map_count>0)&&(type->mods.vmods!=0)) {
+	XkbKTMapEntryPtr entry;
+	for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
+	    if (entry->mods.vmods!=0) {
+		XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask);
+		entry->mods.mask=entry->mods.real_mods|mask;
+		/* entry is active if vmods are bound*/
+	    	entry->active= (mask!=0);
+	    }
+	    else entry->active= 1;
+	}
+    }
+    if (changes) {
+	int	type_ndx;
+	type_ndx= type-xkb->map->types;
+	if ((type_ndx<0)||(type_ndx>xkb->map->num_types))
+	    return;
+	if (changes->map.changed&XkbKeyTypesMask) {
+	    int last;
+	    last= changes->map.first_type+changes->map.num_types-1;
+	    if (type_ndx<changes->map.first_type) {
+		changes->map.first_type= type_ndx;
+		changes->map.num_types= (last-type_ndx)+1;
+	    }
+	    else if (type_ndx>last) {
+		changes->map.num_types= (type_ndx-changes->map.first_type)+1;
+	    }
+	}
+	else {
+	    changes->map.changed|= XkbKeyTypesMask;
+	    changes->map.first_type= type_ndx;
+	    changes->map.num_types= 1;
+	}
+    }
+    return;
+}
+
+Bool
+XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
+{
+register int	i;
+unsigned int	checkState = 0;
+
+    if ((!xkb) || (!xkb->map) || (changed==0))
+	return False;
+    for (i=0;i<xkb->map->num_types;i++) {
+	if (xkb->map->types[i].mods.vmods & changed)
+	XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
+    }
+    if (changed&xkb->ctrls->internal.vmods) {
+	unsigned int	newMask = 0;
+	XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
+	newMask|= xkb->ctrls->internal.real_mods;
+	if (xkb->ctrls->internal.mask!=newMask) {
+	    xkb->ctrls->internal.mask= newMask;
+	    if (changes) {
+		changes->ctrls.changed_ctrls|= XkbInternalModsMask;
+		checkState= True;
+	    }
+	}
+    }
+    if (changed&xkb->ctrls->ignore_lock.vmods) {
+	unsigned int	newMask = 0;
+	XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
+	newMask|= xkb->ctrls->ignore_lock.real_mods;
+	if (xkb->ctrls->ignore_lock.mask!=newMask) {
+	    xkb->ctrls->ignore_lock.mask= newMask;
+	    if (changes) {
+		changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask;
+		checkState= True;
+	    }
+	}
+    }
+    if (xkb->indicators!=NULL) {
+	XkbIndicatorMapPtr map;
+	map= &xkb->indicators->maps[0];
+	for (i=0;i<XkbNumIndicators;i++,map++) {
+	    if (map->mods.vmods&changed) {
+		unsigned int newMask = 0;
+		XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
+		newMask|= map->mods.real_mods;
+		if (newMask!=map->mods.mask) {
+		    map->mods.mask= newMask;
+		    if (changes) {
+			changes->indicators.map_changes|= (1<<i);
+			checkState= True;
+		    }
+		}
+	    }
+	}
+    }
+    if (xkb->compat!=NULL) {
+	XkbCompatMapPtr	compat;
+	compat= xkb->compat;
+	for (i=0;i<XkbNumKbdGroups;i++) {
+	    unsigned int newMask = 0;
+	    XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
+	    newMask|= compat->groups[i].real_mods;
+	    if (compat->groups[i].mask!=newMask) {
+		compat->groups[i].mask= newMask;
+		if (changes) {
+		    changes->compat.changed_groups|= (1<<i);
+		    checkState= True;
+		}
+	    }
+	}
+    }
+    if (xkb->map && xkb->server) {
+	int highChange = 0, lowChange = -1;
+	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	    if (XkbKeyHasActions(xkb,i)) {
+		register XkbAction *pAct;
+		register int n;
+
+		pAct= XkbKeyActionsPtr(xkb,i);
+		for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) {
+		    if ((pAct->type!=XkbSA_NoAction)&&
+			XkbUpdateActionVirtualMods(xkb,pAct,changed)) {
+			if (lowChange<0)
+			    lowChange= i;
+			highChange= i;
+		    }
+		}
+	    }
+	}
+	if (changes && (lowChange>0)) { /* something changed */
+	    if (changes->map.changed&XkbKeyActionsMask) {
+		int last;
+		if (changes->map.first_key_act<lowChange)
+		    lowChange= changes->map.first_key_act;
+		last= changes->map.first_key_act+changes->map.num_key_acts-1;
+		if (last>highChange)
+		    highChange= last;
+	    }
+	    changes->map.changed|= 	XkbKeyActionsMask;
+	    changes->map.first_key_act=	lowChange;
+	    changes->map.num_key_acts=	(highChange-lowChange)+1;
+	}
+    }
+    return checkState;
+}
-- 
cgit v1.2.3