xserver: Branch 'master'

Kevin E Martin kem at kemper.freedesktop.org
Fri Jul 28 14:17:41 PDT 2006


 xkb/Makefile.am |    4 
 xkb/xkbfmisc.c  |  435 +++++++++++++++++-
 xkb/xkbout.c    | 1051 ++++++++++++++++++++++++++++++++++++++++++++
 xkb/xkbtext.c   | 1325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xkb/xkmread.c   |   94 ---
 5 files changed, 2805 insertions(+), 104 deletions(-)

New commits:
diff-tree 654619d76c779606f2315782fc01d1410399fa3b (from 79016d4036786b091a9b9d1133a6cdfedd6c277d)
Author: Kevin E Martin <kem at freedesktop.org>
Date:   Fri Jul 28 17:16:32 2006 -0400

    Revert xkb changes that broke XkbGetKeyboard()

diff --git a/xkb/Makefile.am b/xkb/Makefile.am
index 5763ce8..996d527 100644
--- a/xkb/Makefile.am
+++ b/xkb/Makefile.am
@@ -30,8 +30,10 @@ DIX_SRCS = \
 XKBFILE_SRCS = \
         maprules.c \
         xkmread.c \
+        xkbtext.c \
         xkbfmisc.c \
-        xkberrs.c
+        xkberrs.c \
+        xkbout.c
 
 X11_SRCS = \
         XKBMisc.c \
diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c
index 2bec21b..4130bd9 100644
--- a/xkb/xkbfmisc.c
+++ b/xkb/xkbfmisc.c
@@ -48,16 +48,185 @@
 #include <X11/extensions/XKBgeom.h>
 #include "xkb.h"
 
+unsigned
+_XkbKSCheckCase(KeySym ks)
+{
+unsigned	set,rtrn;
+
+    set= (ks & (~0xff)) >> 8;
+    rtrn= 0;
+    switch (set) {
+	case 0:		/* latin 1 */
+	    if (((ks>=XK_A)&&(ks<=XK_Z))||
+		((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if (((ks>=XK_a)&&(ks<=XK_z))||
+		((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+	case 1:		/* latin 2 */
+	    if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
+		((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
+		((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+	case 2:		/* latin 3 */
+	    if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
+		((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
+		((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+	case 3:		/* latin 4 */
+	    if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
+	        (ks==XK_ENG)||
+		((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
+	        (ks==XK_eng)||
+		((ks>=XK_amacron)&&(ks<=XK_umacron))) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+	case 18:		/* latin 8 */
+	    if ((ks==XK_Babovedot)||
+                ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
+		((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
+	        (ks==XK_Mabovedot)||
+	        (ks==XK_Pabovedot)||
+	        (ks==XK_Sabovedot)||
+	        (ks==XK_Wdiaeresis)||
+		((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if ((ks==XK_babovedot)||
+	        (ks==XK_dabovedot)||
+	        (ks==XK_fabovedot)||
+	        (ks==XK_mabovedot)||
+                ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
+	        (ks==XK_ygrave)||
+		((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+	case 19:		/* latin 9 */
+	    if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
+		rtrn|= _XkbKSUpper;
+	    }
+	    if (ks==XK_oe) {
+		rtrn|= _XkbKSLower;
+	    }
+	    break;
+    }
+    return rtrn;
+}
+
+/***===================================================================***/
+
+Bool
+XkbLookupGroupAndLevel(	XkbDescPtr 	xkb,
+			int 		key,
+			int *		mods_inout,
+			int *		grp_inout,
+			int *		lvl_rtrn)
+{
+int		nG,eG;
+
+    if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout))
+	return False;
+
+    nG= XkbKeyNumGroups(xkb,key);
+    eG= *grp_inout;
+
+    if ( nG==0 ) {
+	*grp_inout= 0;
+	if (lvl_rtrn!=NULL)
+	    *lvl_rtrn= 0;
+	return False;
+    }
+    else if ( nG==1 ) {
+	eG= 0;
+    }
+    else if ( eG>=nG ) {
+	unsigned gI= XkbKeyGroupInfo(xkb,key);
+	switch (XkbOutOfRangeGroupAction(gI)) {
+	    default:
+		eG %= nG;
+		break;
+	    case XkbClampIntoRange:
+		eG = nG-1;
+		break;
+	    case XkbRedirectIntoRange:
+		eG = XkbOutOfRangeGroupNumber(gI);
+		if (eG>=nG)
+		    eG= 0;
+		break;
+	}
+    }
+    *grp_inout= eG;
+    if (mods_inout!=NULL) {
+	XkbKeyTypePtr	type;
+	int		preserve;
+
+	type = XkbKeyKeyType(xkb,key,eG);
+	if (lvl_rtrn!=NULL)
+	    *lvl_rtrn= 0;
+	preserve= 0;
+	if (type->map) { /* find the shift level */
+	    register int i;
+	    register XkbKTMapEntryPtr entry;
+	    for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
+		if ((entry->active)&&
+			(((*mods_inout)&type->mods.mask)==entry->mods.mask)){
+		    if (lvl_rtrn!=NULL)
+			*lvl_rtrn= entry->level;
+		    if (type->preserve)
+			preserve= type->preserve[i].mask;
+		    break;
+		}
+	    }
+	}
+	(*mods_inout)&= ~(type->mods.mask&(~preserve));
+    }
+    return True;
+}
+
 /***===================================================================***/
 
 static Bool
 XkbWriteSectionFromName(FILE *file,char *sectionName,char *name)
 {
     fprintf(file,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
-    ErrorF("    xkb_%-20s { include \"%s\" };\n",sectionName,name);
     return True;
 }
 
+#define	NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
+#define	COMPLETE(n)  ((n)&&(!NEED_DESC(n)))
+
+/* ARGSUSED */
+static void
+_AddIncl(	FILE *		file,
+		XkbFileInfo *	result,
+		Bool 		topLevel,
+		Bool 		showImplicit,
+		int 		index,
+		void *		priv)
+{
+    if ((priv)&&(strcmp((char *)priv,"%")!=0))
+	fprintf(file,"    include \"%s\"\n",(char *)priv);
+    return;
+}
+
 Bool
 XkbWriteXKBKeymapForNames(	FILE *			file,
 				XkbComponentNamesPtr	names,
@@ -66,29 +235,229 @@ XkbWriteXKBKeymapForNames(	FILE *			file
 				unsigned		want,
 				unsigned		need)
 {
-    if (!names || (!names->keycodes && !names->types && !names->compat &&
-                   !names->symbols && !names->geometry))
-        return False;
-
-    fprintf(file, "xkb_keymap \"%s\" {\n", names->keymap ? names->keymap :
-                                                           "default");
-
-    if (names->keycodes)
-	XkbWriteSectionFromName(file, "keycodes", names->keycodes);
-    if (names->types)
-	XkbWriteSectionFromName(file, "types", names->types);
-    if (names->compat)
-	XkbWriteSectionFromName(file, "compatibility", names->compat);
-    if (names->symbols)
-	XkbWriteSectionFromName(file, "symbols", names->symbols);
-    if (names->geometry)
-	XkbWriteSectionFromName(file, "geometry", names->geometry);
+char *		name,*tmp;
+unsigned	complete;
+XkbNamesPtr	old_names;
+int		multi_section;
+unsigned	wantNames,wantConfig,wantDflts;
+XkbFileInfo	finfo;
+
+    bzero(&finfo,sizeof(XkbFileInfo));
+
+    complete= 0;
+    if ((name=names->keymap)==NULL)	name= "default";
+    if (COMPLETE(names->keycodes))	complete|= XkmKeyNamesMask;
+    if (COMPLETE(names->types))		complete|= XkmTypesMask;
+    if (COMPLETE(names->compat))	complete|= XkmCompatMapMask;
+    if (COMPLETE(names->symbols))	complete|= XkmSymbolsMask;
+    if (COMPLETE(names->geometry))	complete|= XkmGeometryMask;
+    want|= (complete|need);
+    if (want&XkmSymbolsMask)
+	want|= XkmKeyNamesMask|XkmTypesMask;
+
+    if (want==0)
+	return False;
+
+    if (xkb!=NULL) {
+	 old_names= xkb->names;
+	 finfo.type= 0;
+	 finfo.defined= 0;
+	 finfo.xkb= xkb;
+	 if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL))
+	    return False;
+    }
+    else old_names= NULL;
+
+    wantConfig= want&(~complete);
+    if (xkb!=NULL) {
+	if (wantConfig&XkmTypesMask) {
+	    if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes))
+		wantConfig&= ~XkmTypesMask;
+	}
+	if (wantConfig&XkmCompatMapMask) {
+	    if ((!xkb->compat) || (xkb->compat->num_si<1))
+		wantConfig&= ~XkmCompatMapMask;
+	}
+	if (wantConfig&XkmSymbolsMask) {
+	    if ((!xkb->map) || (!xkb->map->key_sym_map))
+		wantConfig&= ~XkmSymbolsMask;
+	}
+	if (wantConfig&XkmIndicatorsMask) {
+	    if (!xkb->indicators)
+		wantConfig&= ~XkmIndicatorsMask;
+	}
+	if (wantConfig&XkmKeyNamesMask) {
+	    if ((!xkb->names)||(!xkb->names->keys))
+		wantConfig&= ~XkmKeyNamesMask;
+	}
+	if ((wantConfig&XkmGeometryMask)&&(!xkb->geom))
+	    wantConfig&= ~XkmGeometryMask;
+    }
+    else {
+	wantConfig= 0;
+    }
+    complete|= wantConfig;
+
+    wantDflts= 0;
+    wantNames= want&(~complete);
+    if ((xkb!=NULL) && (old_names!=NULL)) {
+	if (wantNames&XkmTypesMask) {
+	    if (old_names->types!=None) {
+		tmp= XkbAtomGetString(dpy,old_names->types);
+		names->types= _XkbDupString(tmp);
+	    }
+	    else {
+		wantDflts|= XkmTypesMask;
+	    }
+	    complete|= XkmTypesMask; 
+	}
+	if (wantNames&XkmCompatMapMask) {
+	    if (old_names->compat!=None) {
+		tmp= XkbAtomGetString(dpy,old_names->compat);
+		names->compat= _XkbDupString(tmp);
+	    }
+	    else wantDflts|= XkmCompatMapMask;
+	    complete|= XkmCompatMapMask; 
+	}
+	if (wantNames&XkmSymbolsMask) {
+	    if (old_names->symbols==None)
+		return False;
+	    tmp= XkbAtomGetString(dpy,old_names->symbols);
+	    names->symbols= _XkbDupString(tmp);
+	    complete|= XkmSymbolsMask; 
+	}
+	if (wantNames&XkmKeyNamesMask) {
+	   if (old_names->keycodes!=None) {
+		tmp= XkbAtomGetString(dpy,old_names->keycodes);
+		names->keycodes= _XkbDupString(tmp);
+	    }
+	    else wantDflts|= XkmKeyNamesMask;
+	    complete|= XkmKeyNamesMask;
+	}
+	if (wantNames&XkmGeometryMask) {
+	    if (old_names->geometry==None)
+		return False;
+	    tmp= XkbAtomGetString(dpy,old_names->geometry);
+	    names->geometry= _XkbDupString(tmp);
+	    complete|= XkmGeometryMask; 
+	    wantNames&= ~XkmGeometryMask;
+	}
+    }
+    if (complete&XkmCompatMapMask)
+	complete|= XkmIndicatorsMask|XkmVirtualModsMask;
+    else if (complete&(XkmSymbolsMask|XkmTypesMask))
+	complete|= XkmVirtualModsMask;
+    if (need & (~complete))
+	return False;
+    if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete)))
+	return False;
+
+    multi_section= 1;
+    if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
+	((complete&(~XkmKeymapLegal))==0)) {
+	fprintf(file,"xkb_keymap \"%s\" {\n",name);
+    }
+    else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
+	((complete&(~XkmSemanticsLegal))==0)) {
+	fprintf(file,"xkb_semantics \"%s\" {\n",name);
+    }
+    else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
+	((complete&(~XkmLayoutLegal))==0)) {
+	fprintf(file,"xkb_layout \"%s\" {\n",name);
+    }
+    else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
+	multi_section= 0;
+    }
+    else {
+	return False;
+    }
 
-    fprintf(file,"};\n");
+    wantNames= complete&(~(wantConfig|wantDflts));
+    name= names->keycodes;
+    if (wantConfig&XkmKeyNamesMask)
+	XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmKeyNamesMask)
+	fprintf(stderr,"Default symbols not implemented yet!\n");
+    else if (wantNames&XkmKeyNamesMask)
+	XkbWriteSectionFromName(file,"keycodes",name);
+
+    name= names->types;
+    if (wantConfig&XkmTypesMask)
+	XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmTypesMask)
+	fprintf(stderr,"Default types not implemented yet!\n");
+    else if (wantNames&XkmTypesMask)
+	XkbWriteSectionFromName(file,"types",name);
+
+    name= names->compat;
+    if (wantConfig&XkmCompatMapMask)
+	XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmCompatMapMask)
+	fprintf(stderr,"Default interps not implemented yet!\n");
+    else if (wantNames&XkmCompatMapMask)
+	XkbWriteSectionFromName(file,"compatibility",name);
+
+    name= names->symbols;
+    if (wantConfig&XkmSymbolsMask)
+	XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name);
+    else if (wantNames&XkmSymbolsMask)
+	XkbWriteSectionFromName(file,"symbols",name);
+
+    name= names->geometry;
+    if (wantConfig&XkmGeometryMask)
+	XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name);
+    else if (wantNames&XkmGeometryMask)
+	XkbWriteSectionFromName(file,"geometry",name);
 
+    if (multi_section)
+	fprintf(file,"};\n");
     return True;
 }
 
+/***====================================================================***/
+
+/*ARGSUSED*/
+Status
+XkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo)
+{
+    return BadImplementation;
+}
+
+/***====================================================================***/
+
+int
+XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases)
+{
+register int	i;
+
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys))
+	return 0;
+    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0)
+	    return i;
+    }
+    if (!use_aliases)
+	return 0;
+    if (xkb->geom && xkb->geom->key_aliases) {
+	XkbKeyAliasPtr	a;
+	a= xkb->geom->key_aliases;
+	for (i=0;i<xkb->geom->num_key_aliases;i++,a++) {
+	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
+		return XkbFindKeycodeByName(xkb,a->real,False);
+	}
+    }
+    if (xkb->names && xkb->names->key_aliases) {
+	XkbKeyAliasPtr	a;
+	a= xkb->names->key_aliases;
+	for (i=0;i<xkb->names->num_key_aliases;i++,a++) {
+	    if (strncmp(name,a->alias,XkbKeyNameLength)==0)
+		return XkbFindKeycodeByName(xkb,a->real,False);
+	}
+    }
+    return 0;
+}
+
+
 unsigned
 XkbConvertGetByNameComponents(Bool toXkm,unsigned orig)
 {
@@ -115,6 +484,34 @@ unsigned	rtrn;
     return rtrn;
 }
 
+unsigned
+XkbConvertXkbComponents(Bool toXkm,unsigned orig)
+{
+unsigned	rtrn;
+
+    rtrn= 0;
+    if (toXkm) {
+	if (orig&XkbClientMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
+	if (orig&XkbServerMapMask)	rtrn|= XkmTypesMask|XkmSymbolsMask;
+	if (orig&XkbCompatMapMask)	rtrn|= XkmCompatMapMask;
+	if (orig&XkbIndicatorMapMask)	rtrn|= XkmIndicatorsMask;
+	if (orig&XkbNamesMask)		rtrn|= XkmKeyNamesMask;
+	if (orig&XkbGeometryMask)	rtrn|= XkmGeometryMask;
+    }
+    else {
+	if (orig!=0)			rtrn|= XkbNamesMask;
+	if (orig&XkmTypesMask)		rtrn|= XkbClientMapMask;
+	if (orig&XkmCompatMapMask)
+		rtrn|= XkbCompatMapMask|XkbIndicatorMapMask;
+	if (orig&XkmSymbolsMask)	rtrn|=XkbClientMapMask|XkbServerMapMask;
+	if (orig&XkmIndicatorsMask)	rtrn|= XkbIndicatorMapMask;
+	if (orig&XkmKeyNamesMask)	
+		rtrn|= XkbNamesMask|XkbIndicatorMapMask;
+	if (orig&XkmGeometryMask)	rtrn|= XkbGeometryMask;
+    }
+    return rtrn;
+}
+
 Bool
 XkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing)
 {
diff --git a/xkb/xkbout.c b/xkb/xkbout.c
new file mode 100644
index 0000000..31cd4fa
--- /dev/null
+++ b/xkb/xkbout.c
@@ -0,0 +1,1051 @@
+/* $Xorg: xkbout.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 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.
+
+ ********************************************************/
+/* $XFree86: xc/lib/xkbfile/xkbout.c,v 3.9 2001/10/28 03:32:47 tsi Exp $ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xfuncs.h>
+
+#include <X11/X.h>
+#define	NEED_EVENTS
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS	1
+#include <X11/extensions/XKBsrv.h>
+
+#include <X11/extensions/XKBgeom.h>
+#include <X11/extensions/XKBfile.h>
+
+#define	VMOD_HIDE_VALUE	0
+#define	VMOD_SHOW_VALUE	1
+#define	VMOD_COMMENT_VALUE 2
+
+static Bool
+WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue)
+{
+register int 	i,nMods;
+Atom *		vmodNames;
+
+    if (xkb==NULL)
+	return False;
+    if (xkb->names!=NULL)
+	 vmodNames= xkb->names->vmods;
+    else vmodNames= NULL;
+
+    for (i=nMods=0;i<XkbNumVirtualMods;i++) {
+	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
+	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
+	    else		fprintf(file,",");
+	    fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile));
+	    if ((showValue!=VMOD_HIDE_VALUE)&&
+		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
+		if (showValue==VMOD_COMMENT_VALUE) {
+		    fprintf(file,"/* = %s */",
+			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
+		}
+		else  {
+		    fprintf(file,"= %s",
+			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
+		}
+	    }
+	    nMods++;
+	}
+    }
+    if (nMods>0)
+	fprintf(file,";\n\n");
+    return True;
+}
+
+/***====================================================================***/
+
+static Bool
+WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action)
+{
+XkbDescPtr	xkb;
+Display *	dpy;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile));
+    return True;
+}
+
+/***====================================================================***/
+
+Bool
+XkbWriteXKBKeycodes(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Atom			kcName;
+register unsigned 	i;
+XkbDescPtr		xkb;
+Display *		dpy;
+char *			alternate;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
+	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
+	return False;
+    }
+    kcName= xkb->names->keycodes;
+    if (kcName!=None)
+	 fprintf(file,"xkb_keycodes \"%s\" {\n",
+					XkbAtomText(dpy,kcName,XkbXKBFile));
+    else fprintf(file,"xkb_keycodes {\n");
+    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
+    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
+    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	if (xkb->names->keys[i].name[0]!='\0') {
+	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
+		 alternate= "alternate ";
+	    else alternate= "";
+	    fprintf(file,"    %s%6s = %d;\n",alternate,
+			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
+			i);
+	}
+    }
+    if (xkb->indicators!=NULL) {
+	for (i=0;i<XkbNumIndicators;i++) {
+	    char *type;
+	    if (xkb->indicators->phys_indicators&(1<<i))
+			type= "    ";
+	    else	type= "    virtual ";
+	    if (xkb->names->indicators[i]!=None) {
+		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
+			XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile));
+	    }
+	}
+    }
+    if (xkb->names->key_aliases!=NULL) {
+	XkbKeyAliasPtr	pAl;
+	pAl= xkb->names->key_aliases;
+	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
+	    fprintf(file,"    alias %6s = %6s;\n",
+			XkbKeyNameText(pAl->alias,XkbXKBFile),
+			XkbKeyNameText(pAl->real,XkbXKBFile));
+	}
+    }
+    if (addOn)
+	(*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBKeyTypes(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Display *		dpy;
+register unsigned	i,n;
+XkbKeyTypePtr		type;
+XkbKTMapEntryPtr	entry;
+XkbDescPtr		xkb;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
+	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
+	return False;
+    }
+    if (xkb->map->num_types<XkbNumRequiredTypes) {
+	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
+	return 0;
+    }
+    if ((xkb->names==NULL)||(xkb->names->types==None))
+	 fprintf(file,"xkb_types {\n\n");
+    else fprintf(file,"xkb_types \"%s\" {\n\n",
+			XkbAtomText(dpy,xkb->names->types,XkbXKBFile));
+    WriteXKBVModDecl(file,dpy,xkb,
+			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
+
+    type= xkb->map->types;
+    for (i=0;i<xkb->map->num_types;i++,type++) {
+	fprintf(file,"    type \"%s\" {\n",
+		XkbAtomText(dpy,type->name,XkbXKBFile));
+	fprintf(file,"        modifiers= %s;\n",
+	       XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods,
+								XkbXKBFile));
+	entry= type->map;
+	for (n=0;n<type->map_count;n++,entry++) {
+	    char *str;	
+	    str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods,
+								XkbXKBFile);
+	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
+	    if ((type->preserve)&&((type->preserve[n].real_mods)||
+				   (type->preserve[n].vmods))) {
+		fprintf(file,"        preserve[%s]= ",str);
+		fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb,
+					type->preserve[n].real_mods,
+					type->preserve[n].vmods,
+					XkbXKBFile));
+	    }
+	}
+	if (type->level_names!=NULL) {
+	    Atom *name= type->level_names;
+	    for (n=0;n<type->num_levels;n++,name++) {
+		if ((*name)==None)
+		    continue;
+		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
+					XkbAtomText(dpy,*name,XkbXKBFile));
+	    }
+	}
+	fprintf(file,"    };\n");
+    }
+    if (addOn)
+	(*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteXKBIndicatorMap(	FILE *			file,
+			XkbFileInfo *		result,
+			Atom			name,
+			XkbIndicatorMapPtr	led,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+XkbDescPtr	xkb;
+
+    xkb= result->xkb;
+    fprintf(file,"    indicator \"%s\" {\n",XkbAtomGetString(xkb->dpy,name));
+    if (led->flags&XkbIM_NoExplicit)
+	fprintf(file,"        !allowExplicit;\n");
+    if (led->flags&XkbIM_LEDDrivesKB)
+	fprintf(file,"        indicatorDrivesKeyboard;\n");
+    if (led->which_groups!=0) {
+	if (led->which_groups!=XkbIM_UseEffective) {
+	    fprintf(file,"        whichGroupState= %s;\n",
+			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
+	}
+	fprintf(file,"        groups= 0x%02x;\n",led->groups);
+    }
+    if (led->which_mods!=0) {
+	if (led->which_mods!=XkbIM_UseEffective) {
+	    fprintf(file,"        whichModState= %s;\n",
+			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
+	}
+	fprintf(file,"        modifiers= %s;\n",
+			XkbVModMaskText(xkb->dpy,xkb,
+					led->mods.real_mods,led->mods.vmods,
+					XkbXKBFile));
+    }
+    if (led->ctrls!=0) {
+	fprintf(file,"        controls= %s;\n",
+			XkbControlsMaskText(led->ctrls,XkbXKBFile));
+    }
+    if (addOn)
+	(*addOn)(file,result,False,True,XkmIndicatorsIndex,priv);
+    fprintf(file,"    };\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBCompatMap(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Display *		dpy;
+register unsigned	i;
+XkbSymInterpretPtr	interp;
+XkbDescPtr		xkb;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
+	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
+	return False;
+    }
+    if ((xkb->names==NULL)||(xkb->names->compat==None))
+	 fprintf(file,"xkb_compatibility {\n\n");
+    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
+			XkbAtomText(dpy,xkb->names->compat,XkbXKBFile));
+    WriteXKBVModDecl(file,dpy,xkb,
+			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
+
+    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
+    fprintf(file,"    interpret.repeat= False;\n");
+    fprintf(file,"    interpret.locking= False;\n");
+    interp= xkb->compat->sym_interpret;
+    for (i=0;i<xkb->compat->num_si;i++,interp++) {
+	fprintf(file,"    interpret %s+%s(%s) {\n",	
+				((interp->sym==NoSymbol)?"Any":
+					XkbKeysymText(interp->sym,XkbXKBFile)),
+				XkbSIMatchText(interp->match,XkbXKBFile),
+				XkbModMaskText(interp->mods,XkbXKBFile));
+	if (interp->virtual_mod!=XkbNoModifier) {
+	    fprintf(file,"        virtualModifier= %s;\n",
+		XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile));
+	}
+	if (interp->match&XkbSI_LevelOneOnly)
+	    fprintf(file,"        useModMapMods=level1;\n");
+	if (interp->flags&XkbSI_LockingKey)
+	    fprintf(file,"        locking= True;\n");
+	if (interp->flags&XkbSI_AutoRepeat)
+	    fprintf(file,"        repeat= True;\n");
+	fprintf(file,"        action= ");
+	WriteXKBAction(file,result,&interp->act);
+	fprintf(file,";\n");
+	fprintf(file,"    };\n");
+    }
+    for (i=0;i<XkbNumKbdGroups;i++) {
+	XkbModsPtr	gc;
+
+	gc= &xkb->compat->groups[i];
+	if ((gc->real_mods==0)&&(gc->vmods==0))
+	    continue;
+	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb,
+							gc->real_mods,gc->vmods,
+							XkbXKBFile));
+    }
+    if (xkb->indicators) {
+	for (i=0;i<XkbNumIndicators;i++) {
+	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
+		(map->which_mods!=0)||
+		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
+		(map->ctrls!=0)) {
+		WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map,
+								addOn,priv);
+	    }
+	}
+    }
+    if (addOn)
+	(*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBSymbols(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Display *		dpy;
+register unsigned	i,tmp;
+XkbDescPtr		xkb;
+XkbClientMapPtr		map;
+XkbServerMapPtr		srv;
+Bool			showActions;
+
+    xkb= result->xkb;
+    map= xkb->map;
+    srv= xkb->server;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) {
+	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
+	return False;
+    }
+    if ((!xkb->names)||(!xkb->names->keys)) {
+	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
+	return False;
+    }
+    if ((xkb->names==NULL)||(xkb->names->symbols==None))
+	 fprintf(file,"xkb_symbols {\n\n");
+    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
+			XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile));
+    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
+	if (xkb->names->groups[i]!=None) {
+	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
+			XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile));
+	    tmp++;
+	}
+    }
+    if (tmp>0)
+	fprintf(file,"\n");
+    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	Bool	simple;
+	if ((int)XkbKeyNumSyms(xkb,i)<1)
+	    continue;
+	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
+	    continue;
+	simple= True;
+	fprintf(file,"    key %6s {",
+			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
+	if (srv->explicit) {
+	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
+	   						(showImplicit)) {
+		int 	typeNdx,g;
+		Bool	multi;
+		char *	comment="  ";
+
+		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
+		    comment= "//";
+		multi= False;
+		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
+		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
+		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
+			multi= True;
+		}
+		if (multi) {
+		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
+			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
+			if (srv->explicit[i]&(1<<g)) {
+			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
+			    	comment,g+1,
+				XkbAtomText(dpy,map->types[typeNdx].name,
+			    	XkbXKBFile));
+			}
+			else if (showImplicit) {
+			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
+				XkbAtomText(dpy,map->types[typeNdx].name,
+			    	XkbXKBFile));
+			}
+		    }
+		}
+		else {
+		    fprintf(file,"\n%s      type= \"%s\",",comment,
+				XkbAtomText(dpy,map->types[typeNdx].name,
+			    	XkbXKBFile));
+		}
+		simple= False;
+	    }
+	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
+		    					  (xkb->ctrls!=NULL)) {
+		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
+		     fprintf(file,"\n        repeat= Yes,");
+		else fprintf(file,"\n        repeat= No,");
+		simple= False;
+	    }
+	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
+					(xkb->server->vmodmap[i]!=0)) {
+		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
+		    fprintf(file,"\n        virtualMods= %s,",
+				XkbVModMaskText(dpy,xkb,0,
+						xkb->server->vmodmap[i],
+						XkbXKBFile));
+		}
+		else if (showImplicit) {
+		    fprintf(file,"\n//      virtualMods= %s,",
+				XkbVModMaskText(dpy,xkb,0,
+						xkb->server->vmodmap[i],
+						XkbXKBFile));
+		}
+	    }
+	}
+	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
+	    case XkbClampIntoRange:
+		fprintf(file,"\n        groupsClamp,");
+		break;
+	    case XkbRedirectIntoRange:
+		fprintf(file,"\n        groupsRedirect= Group%d,",
+			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
+		break;
+	}
+	if (srv->behaviors!=NULL) {
+	    unsigned type;
+	    type= srv->behaviors[i].type&XkbKB_OpMask;
+
+	    if (type!=XkbKB_Default) {
+		simple= False;
+		fprintf(file,"\n        %s,",
+			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
+	    }
+	}
+	if ((srv->explicit==NULL) || showImplicit ||
+	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
+	     showActions= XkbKeyHasActions(xkb,i);
+	else showActions= False;
+	
+	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
+	    simple= False;
+	if (simple) {
+	    KeySym *syms;
+	    unsigned s;
+
+	    syms= XkbKeySymsPtr(xkb,i);
+	    fprintf(file,"         [ ");
+	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
+		if (s!=0)
+		    fprintf(file,", ");
+		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
+	    }
+	    fprintf(file," ] };\n");
+	}
+	else {
+	    unsigned g,s;
+	    KeySym *syms;
+	    XkbAction *acts;
+	    syms= XkbKeySymsPtr(xkb,i);
+	    acts= XkbKeyActionsPtr(xkb,i);
+	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
+		if (g!=0)
+		    fprintf(file,",");
+		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
+		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
+		    if (s!=0)
+			fprintf(file,", ");
+		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
+		}
+		fprintf(file," ]");
+		syms+= XkbKeyGroupsWidth(xkb,i);
+		if (showActions) {
+		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
+		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
+			if (s!=0)
+			    fprintf(file,", ");
+			WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]);
+		    }
+		    fprintf(file," ]");
+		    acts+= XkbKeyGroupsWidth(xkb,i);
+		}
+	    }
+	    fprintf(file,"\n    };\n");
+	}
+    }
+    if (map && map->modmap) {
+	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+	    if (map->modmap[i]!=0) {
+		register int n,bit;
+		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
+		    if (map->modmap[i]&bit) {
+			char buf[5];
+			memcpy(buf,xkb->names->keys[i].name,4);
+			buf[4]= '\0';
+			fprintf(file,"    modifier_map %s { <%s> };\n",
+					XkbModIndexText(n,XkbXKBFile),buf);
+		    }
+		}
+	    }
+	}
+    }
+    if (addOn)
+	(*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteXKBOutline(	FILE *		file,
+			XkbShapePtr	shape,
+			XkbOutlinePtr	outline,
+			int		lastRadius,
+			int		first,
+			int		indent)
+{
+register int	i;
+XkbPointPtr	pt;
+char *		iStr;
+
+    fprintf(file,"%s",iStr= XkbIndentText(first));
+    if (first!=indent)
+	iStr= XkbIndentText(indent);
+    if (outline->corner_radius!=lastRadius) {
+	fprintf(file,"corner= %s,",
+			XkbGeomFPText(outline->corner_radius,XkbMessage));
+	if (shape!=NULL) {
+	    fprintf(file,"\n%s",iStr);
+	}
+    }
+    if (shape) {
+	if (outline==shape->approx)
+	    fprintf(file,"approx= ");
+	else if (outline==shape->primary)
+	    fprintf(file,"primary= ");
+    }
+    fprintf(file,"{");
+    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
+	if (i==0)		fprintf(file," ");
+	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
+	else			fprintf(file,", ");
+	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
+				  XkbGeomFPText(pt->y,XkbXKBFile));
+    }
+    fprintf(file," }");
+    return True;
+}
+
+static Bool
+WriteXKBDoodad(	FILE *		file,
+		Display *	dpy,
+		unsigned	indent,
+		XkbGeometryPtr	geom,
+		XkbDoodadPtr	doodad)
+{
+register char *	i_str;
+XkbShapePtr	shape;
+XkbColorPtr	color;
+
+    i_str= XkbIndentText(indent);
+    fprintf(file,"%s%s \"%s\" {\n",i_str,
+				XkbDoodadTypeText(doodad->any.type,XkbMessage),
+				XkbAtomText(dpy,doodad->any.name,XkbMessage));
+    fprintf(file,"%s    top=      %s;\n",i_str,
+				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
+    fprintf(file,"%s    left=     %s;\n",i_str,
+				XkbGeomFPText(doodad->any.left,XkbXKBFile));
+    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
+    switch (doodad->any.type) {
+	case XkbOutlineDoodad:
+	case XkbSolidDoodad:
+	    if (doodad->shape.angle!=0) {
+		fprintf(file,"%s    angle=  %s;\n",i_str,
+			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
+	    }
+	    if (doodad->shape.color_ndx!=0) {
+		fprintf(file,"%s    color= \"%s\";\n",i_str,
+			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
+	    }
+	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
+	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+			    XkbAtomText(dpy,shape->name,XkbXKBFile));
+	    break;
+	case XkbTextDoodad:
+	    if (doodad->text.angle!=0) {
+		fprintf(file,"%s    angle=  %s;\n",i_str,
+			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
+	    }
+	    if (doodad->text.width!=0) {
+		fprintf(file,"%s    width=  %s;\n",i_str,
+			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
+
+	    }
+	    if (doodad->text.height!=0) {
+		fprintf(file,"%s    height=  %s;\n",i_str,
+			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
+
+	    }
+	    if (doodad->text.color_ndx!=0) {
+		color= XkbTextDoodadColor(geom,&doodad->text);
+		fprintf(file,"%s    color= \"%s\";\n",i_str,
+			     XkbStringText(color->spec,XkbXKBFile));
+	    }
+	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
+	    		     XkbStringText(doodad->text.font,XkbXKBFile));
+	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
+	    		    XkbStringText(doodad->text.text,XkbXKBFile));
+	    break;
+	case XkbIndicatorDoodad:
+	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
+	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
+	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
+	    		    XkbStringText(color->spec,XkbXKBFile));
+	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
+	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
+	    		    XkbStringText(color->spec,XkbXKBFile));
+	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+			     XkbAtomText(dpy,shape->name,XkbXKBFile));
+	    break;
+	case XkbLogoDoodad:
+	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
+			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
+	    if (doodad->shape.angle!=0) {
+		fprintf(file,"%s    angle=  %s;\n",i_str,
+			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
+	    }
+	    if (doodad->shape.color_ndx!=0) {
+		fprintf(file,"%s    color= \"%s\";\n",i_str,
+			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
+	    }
+	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
+	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
+			    XkbAtomText(dpy,shape->name,XkbXKBFile));
+	    break;
+    }
+    fprintf(file,"%s};\n",i_str);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+WriteXKBOverlay(	FILE *		file,
+			Display *	dpy,
+			unsigned	indent,
+			XkbGeometryPtr	geom,
+			XkbOverlayPtr	ol)
+{
+register char *		i_str;
+int			r,k,nOut;
+XkbOverlayRowPtr	row;
+XkbOverlayKeyPtr	key;
+
+    i_str= XkbIndentText(indent);
+    if (ol->name!=None) {
+	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
+    					XkbAtomText(dpy,ol->name,XkbMessage));
+    }
+    else fprintf(file,"%soverlay {\n",i_str);
+    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
+	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+	    char *over,*under;
+	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
+	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
+	    if (nOut==0)
+		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
+	    else if ((nOut%4)==0)
+		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
+	    else fprintf(file,", %6s=%6s",under,over);
+	    nOut++;
+	}
+    }
+    fprintf(file,"\n%s};\n",i_str);
+    return True;
+}
+
+static Bool
+WriteXKBSection(	FILE *		file,
+			Display *	dpy,
+			XkbSectionPtr 	s,
+			XkbGeometryPtr	geom)
+{
+register int	i;
+XkbRowPtr	row;
+int		dfltKeyColor = 0;
+
+    fprintf(file,"    section \"%s\" {\n",
+				XkbAtomText(dpy,s->name,XkbXKBFile));
+    if (s->rows&&(s->rows->num_keys>0)) {
+	dfltKeyColor= s->rows->keys[0].color_ndx;
+	fprintf(file,"        key.color= \"%s\";\n",
+		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
+    }
+    fprintf(file,"        priority=  %d;\n",s->priority);
+    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
+    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
+    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
+    fprintf(file,"        height=    %s;\n",
+					XkbGeomFPText(s->height,XkbXKBFile));
+    if (s->angle!=0) {
+	fprintf(file,"        angle=  %s;\n",
+					XkbGeomFPText(s->angle,XkbXKBFile));
+    }
+    for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
+	fprintf(file,"        row {\n");
+	fprintf(file,"            top=  %s;\n",
+					XkbGeomFPText(row->top,XkbXKBFile));
+	fprintf(file,"            left= %s;\n",
+					XkbGeomFPText(row->left,XkbXKBFile));
+	if (row->vertical)
+	    fprintf(file,"            vertical;\n");
+	if (row->num_keys>0) {
+	    register int 	k;
+	    register XkbKeyPtr	key;
+	    int			forceNL=0;
+	    int			nThisLine= 0;
+	    fprintf(file,"            keys {\n");
+	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+		XkbShapePtr	shape;
+		if (key->color_ndx!=dfltKeyColor)
+		    forceNL= 1;
+		if (k==0) {
+		     fprintf(file,"                ");
+		     nThisLine= 0;
+		}
+		else if (((nThisLine%2)==1)||(forceNL)) {
+		     fprintf(file,",\n                ");
+		     forceNL= nThisLine= 0;
+		}
+		else {
+		     fprintf(file,", ");
+		     nThisLine++;
+		}
+		shape= XkbKeyShape(geom,key);
+		fprintf(file,"{ %6s, \"%s\", %3s",
+		      XkbKeyNameText(key->name.name,XkbXKBFile),
+		      XkbAtomText(dpy,shape->name,XkbXKBFile),
+		      XkbGeomFPText(key->gap,XkbXKBFile));
+		if (key->color_ndx!=dfltKeyColor) {
+		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
+		    forceNL= 1;
+		}
+		fprintf(file," }");
+	    }
+	    fprintf(file,"\n            };\n");
+	}
+	fprintf(file,"        };\n");
+    }
+    if (s->doodads!=NULL) {
+	XkbDoodadPtr	doodad;
+	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
+	    WriteXKBDoodad(file,dpy,8,geom,doodad);
+	}
+    }
+    if (s->overlays!=NULL) {
+	XkbOverlayPtr	ol;
+	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
+	    WriteXKBOverlay(file,dpy,8,geom,ol);
+	}
+    }
+    fprintf(file,"    }; // End of \"%s\" section\n\n",
+				XkbAtomText(dpy,s->name,XkbXKBFile));
+    return True;
+}
+
+Bool
+XkbWriteXKBGeometry(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Display *		dpy;
+register unsigned	i,n;
+XkbDescPtr		xkb;
+XkbGeometryPtr		geom;
+
+    xkb= result->xkb;
+    if ((!xkb)||(!xkb->geom)) {
+	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
+ 	return False;
+    }
+    dpy= xkb->dpy;
+    geom= xkb->geom;
+    if (geom->name==None)
+	 fprintf(file,"xkb_geometry {\n\n");
+    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
+				XkbAtomText(dpy,geom->name,XkbXKBFile));
+    fprintf(file,"    width=       %s;\n",
+				XkbGeomFPText(geom->width_mm,XkbXKBFile));
+    fprintf(file,"    height=      %s;\n\n",
+				XkbGeomFPText(geom->height_mm,XkbXKBFile));
+
+    if (geom->key_aliases!=NULL) {
+	XkbKeyAliasPtr	pAl;
+	pAl= geom->key_aliases;
+	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
+	    fprintf(file,"    alias %6s = %6s;\n",
+				XkbKeyNameText(pAl->alias,XkbXKBFile),
+				XkbKeyNameText(pAl->real,XkbXKBFile));
+	}
+	fprintf(file,"\n");
+    }
+
+    if (geom->base_color!=NULL)
+	fprintf(file,"    baseColor=   \"%s\";\n",
+			XkbStringText(geom->base_color->spec,XkbXKBFile));
+    if (geom->label_color!=NULL)
+	fprintf(file,"    labelColor=  \"%s\";\n",
+			XkbStringText(geom->label_color->spec,XkbXKBFile));
+    if (geom->label_font!=NULL)
+	fprintf(file,"    xfont=       \"%s\";\n",
+			XkbStringText(geom->label_font,XkbXKBFile));
+    if ((geom->num_colors>0)&&(showImplicit)) {
+	XkbColorPtr	color;
+	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
+		fprintf(file,"//     color[%d]= \"%s\"\n",i,
+				XkbStringText(color->spec,XkbXKBFile));
+	}
+	fprintf(file,"\n");
+    }
+    if (geom->num_properties>0) {
+	XkbPropertyPtr	prop;
+	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
+	    fprintf(file,"    %s= \"%s\";\n",prop->name,
+    				XkbStringText(prop->value,XkbXKBFile));
+	}
+	fprintf(file,"\n");
+    }
+    if (geom->num_shapes>0) {
+	XkbShapePtr	shape;
+	XkbOutlinePtr	outline;
+	int		lastR;
+	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
+	    lastR=0;
+	    fprintf(file,"    shape \"%s\" {",
+				   XkbAtomText(dpy,shape->name,XkbXKBFile));
+	    outline= shape->outlines;
+	    if (shape->num_outlines>1) {
+		for (n=0;n<shape->num_outlines;n++,outline++) {
+		    if (n==0)	fprintf(file,"\n");
+		    else	fprintf(file,",\n");
+		    WriteXKBOutline(file,shape,outline,lastR,8,8);
+		    lastR= outline->corner_radius;
+		}
+		fprintf(file,"\n    };\n");
+	    }
+	    else {
+		WriteXKBOutline(file,NULL,outline,lastR,1,8);
+		fprintf(file," };\n");
+	    }
+	}
+    }
+    if (geom->num_sections>0) {
+	XkbSectionPtr	section;
+	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
+	    WriteXKBSection(file,dpy,section,geom);
+	}
+    }
+    if (geom->num_doodads>0) {
+	XkbDoodadPtr	doodad;
+	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
+	    WriteXKBDoodad(file,dpy,4,geom,doodad);
+	}
+    }
+    if (addOn)
+	(*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBSemantics(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Bool		ok;
+
+    fprintf(file,"xkb_semantics {\n");
+    ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv);
+    ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBLayout(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Bool		ok;
+XkbDescPtr	xkb;
+
+    xkb= result->xkb;
+    fprintf(file,"xkb_layout {\n");
+    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
+    if (xkb->geom)
+	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBKeymap(	FILE *			file,
+			XkbFileInfo *		result,
+			Bool			topLevel,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Bool		ok;
+XkbDescPtr	xkb;
+
+    xkb= result->xkb;
+    fprintf(file,"xkb_keymap {\n");
+    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
+    if (xkb->geom)
+	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+Bool
+XkbWriteXKBFile(	FILE *			out,
+			XkbFileInfo *		result,
+			Bool			showImplicit,
+			XkbFileAddOnFunc	addOn,
+			void *			priv)
+{
+Bool	 		ok = False;
+Bool			(*func)(
+    FILE *		/* file */,
+    XkbFileInfo *	/* result */,
+    Bool		/* topLevel */,
+    Bool		/* showImplicit */,
+    XkbFileAddOnFunc	/* addOn */,
+    void *		/* priv */
+) = NULL;
+
+    switch (result->type) {
+	case XkmSemanticsFile:
+	    func= XkbWriteXKBSemantics;
+	    break;
+	case XkmLayoutFile:
+	    func= XkbWriteXKBLayout;
+	    break;
+	case XkmKeymapFile:
+	    func= XkbWriteXKBKeymap;
+	    break;
+	case XkmTypesIndex:
+	    func= XkbWriteXKBKeyTypes;
+	    break;
+	case XkmCompatMapIndex:
+	    func= XkbWriteXKBCompatMap;
+	    break;
+	case XkmSymbolsIndex:
+	    func= XkbWriteXKBSymbols;
+	    break;
+	case XkmKeyNamesIndex:
+	    func= XkbWriteXKBKeycodes;
+	    break;
+	case XkmGeometryFile:
+	case XkmGeometryIndex:
+	    func= XkbWriteXKBGeometry;
+	    break;
+	case XkmVirtualModsIndex:
+	case XkmIndicatorsIndex:
+	    _XkbLibError(_XkbErrBadImplementation,
+	    		XkbConfigText(result->type,XkbMessage),0);
+	    return False;
+    }
+    if (out==NULL) {
+	_XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0);
+	ok= False;
+    }
+    else if (func) {
+	ok= (*func)(out,result,True,showImplicit,addOn,priv);
+    }
+    return ok;
+}
diff --git a/xkb/xkbtext.c b/xkb/xkbtext.c
new file mode 100644
index 0000000..defd45a
--- /dev/null
+++ b/xkb/xkbtext.c
@@ -0,0 +1,1325 @@
+/* $Xorg: xkbtext.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */
+/************************************************************
+ Copyright (c) 1994 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.
+
+ ********************************************************/
+/* $XFree86: xc/lib/xkbfile/xkbtext.c,v 3.11 2002/12/21 18:49:02 paulo Exp $ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xos.h>
+
+#include <X11/X.h>
+#define	NEED_EVENTS
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS	1
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBgeom.h>
+
+/***====================================================================***/
+
+#define	BUFFER_SIZE	512
+
+static char textBuffer[BUFFER_SIZE];
+static int  tbNext= 0;
+
+static char *
+tbGetBuffer(unsigned size)
+{
+char *rtrn;
+
+    if (size>=BUFFER_SIZE)
+	return NULL;
+    if ((BUFFER_SIZE-tbNext)<=size)
+	tbNext= 0;
+    rtrn= &textBuffer[tbNext];
+    tbNext+= size;
+    return rtrn;
+}
+
+/***====================================================================***/
+
+char *
+XkbAtomText(Display *dpy,Atom atm,unsigned format)
+{
+char	*rtrn,*tmp;
+
+    tmp= XkbAtomGetString(dpy,atm);
+    if (tmp!=NULL) {
+	int	len;
+	len= strlen(tmp)+1;
+	if (len>BUFFER_SIZE)
+	    len= BUFFER_SIZE-2;
+	rtrn= tbGetBuffer(len);
+	strncpy(rtrn,tmp,len);
+	rtrn[len]= '\0';
+    }
+    else {
+	rtrn= tbGetBuffer(1);
+	rtrn[0]= '\0';
+    }
+    if (format==XkbCFile) {
+	for (tmp=rtrn;*tmp!='\0';tmp++) {
+	    if ((tmp==rtrn)&&(!isalpha(*tmp)))
+		*tmp= '_';
+	    else if (!isalnum(*tmp))
+		*tmp= '_';
+	}
+    }
+    return XkbStringText(rtrn,format);
+}
+
+/***====================================================================***/
+
+char *
+XkbVModIndexText(Display *dpy,XkbDescPtr xkb,unsigned ndx,unsigned format)
+{
+register int len;
+register Atom *vmodNames;
+char *rtrn,*tmp;
+char  numBuf[20];
+
+    if (xkb && xkb->names)
+	 vmodNames= xkb->names->vmods;
+    else vmodNames= NULL;
+
+    tmp= NULL;
+    if (ndx>=XkbNumVirtualMods)
+	 tmp= "illegal";
+    else if (vmodNames&&(vmodNames[ndx]!=None))
+	 tmp= XkbAtomGetString(dpy,vmodNames[ndx]);
+    if (tmp==NULL)
+	sprintf(tmp=numBuf,"%d",ndx);
+
+    len= strlen(tmp)+1;
+    if (format==XkbCFile)
+	len+= 4;
+    if (len>=BUFFER_SIZE)
+	len= BUFFER_SIZE-1;
+    rtrn= tbGetBuffer(len);
+    if (format==XkbCFile) {
+	 strcpy(rtrn,"vmod_");
+	 strncpy(&rtrn[5],tmp,len-4);
+    }
+    else strncpy(rtrn,tmp,len);
+    return rtrn;
+}
+
+char *
+XkbVModMaskText(	Display *	dpy,
+			XkbDescPtr	xkb,
+			unsigned	modMask,
+			unsigned	mask,
+			unsigned	format)
+{
+register int i,bit;
+int	 len;
+char *mm,*rtrn;
+char *str,buf[BUFFER_SIZE];
+
+    if ((modMask==0)&&(mask==0)) {
+	rtrn= tbGetBuffer(5);
+	if (format==XkbCFile)
+	     sprintf(rtrn,"0");
+	else sprintf(rtrn,"none");
+	return rtrn;
+    }
+    if (modMask!=0)
+	 mm= XkbModMaskText(modMask,format);
+    else mm= NULL;
+
+    str= buf;
+    buf[0]= '\0';
+    if (mask) {
+	char *tmp;
+	for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+	    if (mask&bit) {
+		tmp= XkbVModIndexText(dpy,xkb,i,format);
+		len= strlen(tmp)+1+(str==buf?0:1);
+		if (format==XkbCFile)
+		    len+= 4;
+		if ((str-(buf+len))<=BUFFER_SIZE) {
+		    if (str!=buf) {
+			if (format==XkbCFile)	*str++= '|';
+			else			*str++= '+';
+			len--;
+		    }
+		}
+		if (format==XkbCFile)
+		     sprintf(str,"%sMask",tmp);
+		else strcpy(str,tmp);
+		str= &str[len-1];
+	    }
+	}
+	str= buf;
+    }
+    else str= NULL;
+    if (mm)	
+	len= strlen(mm);
+    else	len= 0;
+    if (str)
+	len+= strlen(str)+(mm==NULL?0:1);
+    if (len>=BUFFER_SIZE)
+	len= BUFFER_SIZE-1;
+    rtrn= tbGetBuffer(len+1);
+    rtrn[0]= '\0';
+
+    if (mm!=NULL) {
+	i= strlen(mm);
+	if (i>len)
+	    i= len;
+	strcpy(rtrn,mm);
+    }
+    else {
+	i=0;
+    }
+    if (str!=NULL) {
+	if (mm!=NULL) {
+	    if (format==XkbCFile)	strcat(rtrn,"|");
+	    else			strcat(rtrn,"+");
+	}
+	strncat(rtrn,str,len-i);
+    }
+    rtrn[len]= '\0';
+    return rtrn;
+}
+
+static char *modNames[XkbNumModifiers] = {
+    "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
+};
+
+char *
+XkbModIndexText(unsigned ndx,unsigned format)
+{
+char *	rtrn;
+char	buf[100];
+
+    if (format==XkbCFile) {
+	if (ndx<XkbNumModifiers)
+	     sprintf(buf,"%sMapIndex",modNames[ndx]);
+	else if (ndx==XkbNoModifier)
+	     sprintf(buf,"XkbNoModifier");
+	else sprintf(buf,"0x%02x",ndx);
+    }
+    else {
+	if (ndx<XkbNumModifiers)
+	     strcpy(buf,modNames[ndx]);
+	else if (ndx==XkbNoModifier)
+	     strcpy(buf,"none");
+	else sprintf(buf,"ILLEGAL_%02x",ndx);
+    }
+    rtrn= tbGetBuffer(strlen(buf)+1);
+    strcpy(rtrn,buf);
+    return rtrn;
+}
+
+char *
+XkbModMaskText(unsigned mask,unsigned format)
+{
+register int i,bit;
+char buf[64],*rtrn;
+
+    if ((mask&0xff)==0xff) {
+	if (format==XkbCFile) 		strcpy(buf,"0xff");
+	else				strcpy(buf,"all");
+    }
+    else if ((mask&0xff)==0) {
+	if (format==XkbCFile)		strcpy(buf,"0");
+	else				strcpy(buf,"none");
+    }
+    else {
+	char *str= buf;
+	buf[0]= '\0';
+	for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) {
+	    if (mask&bit) {
+		if (str!=buf) {
+		    if (format==XkbCFile)	*str++= '|';
+		    else			*str++= '+';
+		}
+		strcpy(str,modNames[i]);
+		str= &str[strlen(str)];
+		if (format==XkbCFile) {
+		    strcpy(str,"Mask");
+		    str+= 4;
+		}
+	    }
+	}
+    }
+    rtrn= tbGetBuffer(strlen(buf)+1);
+    strcpy(rtrn,buf);
+    return rtrn;
+}
+
+/***====================================================================***/
+
+/*ARGSUSED*/
+char *
+XkbConfigText(unsigned config,unsigned format)
+{
+static char *buf;
+
+    buf= tbGetBuffer(32);
+    switch (config) {
+	case XkmSemanticsFile:
+	    strcpy(buf,"Semantics");
+	    break;
+	case XkmLayoutFile:
+	    strcpy(buf,"Layout");
+	    break;
+	case XkmKeymapFile:
+	    strcpy(buf,"Keymap");
+	    break;
+	case XkmGeometryFile:
+	case XkmGeometryIndex:
+	    strcpy(buf,"Geometry");
+	    break;
+	case XkmTypesIndex:
+	    strcpy(buf,"Types");
+	    break;
+	case XkmCompatMapIndex:
+	    strcpy(buf,"CompatMap");
+	    break;
+	case XkmSymbolsIndex:
+	    strcpy(buf,"Symbols");
+	    break;
+	case XkmIndicatorsIndex:
+	    strcpy(buf,"Indicators");
+	    break;
+	case XkmKeyNamesIndex:
+	    strcpy(buf,"KeyNames");
+	    break;
+	case XkmVirtualModsIndex:
+	    strcpy(buf,"VirtualMods");
+	    break;
+	default:
+	    sprintf(buf,"unknown(%d)",config);
+	    break;
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbKeysymText(KeySym sym,unsigned format)
+{
+static char buf[32],*rtrn;
+
+    if (sym==NoSymbol)
+	 strcpy(rtrn=buf,"NoSymbol");
+    else sprintf(rtrn=buf, "0x%lx", (long)sym);
+    return rtrn;
+}
+
+char *
+XkbKeyNameText(char *name,unsigned format)
+{
+char *buf;
+
+    if (format==XkbCFile) {
+	buf= tbGetBuffer(5);
+	memcpy(buf,name,4);
+	buf[4]= '\0';
+    }
+    else {
+	int len;
+	buf= tbGetBuffer(7);
+	buf[0]= '<';
+	memcpy(&buf[1],name,4);
+	buf[5]= '\0';
+	len= strlen(buf);
+	buf[len++]= '>';
+	buf[len]= '\0';
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+static char *siMatchText[5] = {
+	"NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
+};
+
+char *
+XkbSIMatchText(unsigned type,unsigned format)
+{
+static char buf[40];
+char *rtrn;
+
+    switch (type&XkbSI_OpMask) {
+	case XkbSI_NoneOf:	rtrn= siMatchText[0]; break;
+	case XkbSI_AnyOfOrNone:	rtrn= siMatchText[1]; break;
+	case XkbSI_AnyOf:	rtrn= siMatchText[2]; break;
+	case XkbSI_AllOf:	rtrn= siMatchText[3]; break;
+	case XkbSI_Exactly:	rtrn= siMatchText[4]; break;
+	default:		sprintf(buf,"0x%x",type&XkbSI_OpMask);
+				return buf;
+    }
+    if (format==XkbCFile) {
+	if (type&XkbSI_LevelOneOnly)
+	     sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn);
+	else sprintf(buf,"XkbSI_%s",rtrn);
+	rtrn= buf;
+    }
+    return rtrn;
+}
+
+/***====================================================================***/
+
+static char *imWhichNames[]= {
+	"base",
+	"latched",
+	"locked",
+	"effective",
+	"compat"
+};
+
+char *
+XkbIMWhichStateMaskText(unsigned use_which,unsigned format)
+{
+int		len;
+unsigned	i,bit,tmp;
+char *		buf;
+
+    if (use_which==0) {
+	buf= tbGetBuffer(2);
+	strcpy(buf,"0");
+	return buf;
+    }
+    tmp= use_which&XkbIM_UseAnyMods;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+	if (tmp&bit) {
+	    tmp&= ~bit;
+	    len+= strlen(imWhichNames[i])+1;
+	    if (format==XkbCFile)
+		len+= 9;
+	}
+    }
+    buf= tbGetBuffer(len+1);
+    tmp= use_which&XkbIM_UseAnyMods;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+	if (tmp&bit) {
+	    tmp&= ~bit;
+	    if (format==XkbCFile) {
+		if (len!=0)
+		    buf[len++]= '|';
+		sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]);
+		buf[len+9]= toupper(buf[len+9]);
+	    }
+	    else {
+		if (len!=0)
+		    buf[len++]= '+';
+		sprintf(&buf[len],"%s",imWhichNames[i]);
+	    }
+	    len+= strlen(&buf[len]);
+	}
+    }
+    return buf;
+}
+
+char *
+XkbAccessXDetailText(unsigned state,unsigned format)
+{
+char *buf,*prefix;
+
+    buf= tbGetBuffer(32);
+    if (format==XkbMessage)	prefix= "";
+    else			prefix= "XkbAXN_";
+    switch (state){
+	case XkbAXN_SKPress:	sprintf(buf,"%sSKPress",prefix); break;
+	case XkbAXN_SKAccept:	sprintf(buf,"%sSKAccept",prefix); break;
+	case XkbAXN_SKRelease:	sprintf(buf,"%sSKRelease",prefix); break;
+	case XkbAXN_SKReject:	sprintf(buf,"%sSKReject",prefix); break;
+	case XkbAXN_BKAccept:	sprintf(buf,"%sBKAccept",prefix); break;
+	case XkbAXN_BKReject:	sprintf(buf,"%sBKReject",prefix); break;
+	case XkbAXN_AXKWarning:	sprintf(buf,"%sAXKWarning",prefix); break;
+	default:		sprintf(buf,"ILLEGAL"); break;
+    }
+    return buf;
+}
+
+static char *nknNames[] = {
+	"keycodes", "geometry", "deviceID"
+};
+#define	NUM_NKN	(sizeof(nknNames)/sizeof(char *))
+
+char *
+XkbNKNDetailMaskText(unsigned detail,unsigned format)
+{
+char *buf,*prefix,*suffix;
+register int 		i;
+register unsigned	bit;
+int			len,plen,slen;
+
+
+    if ((detail&XkbAllNewKeyboardEventsMask)==0) {
+	char *tmp = "";
+	if (format==XkbCFile)			tmp= "0";
+	else if (format==XkbMessage)		tmp= "none";
+	buf=  tbGetBuffer(strlen(tmp)+1);
+	strcpy(buf,tmp);
+	return buf;
+    }
+    else if ((detail&XkbAllNewKeyboardEventsMask)==XkbAllNewKeyboardEventsMask){
+	char *	tmp;
+	if (format==XkbCFile)		tmp= "XkbAllNewKeyboardEventsMask";
+	else 				tmp= "all";
+	buf=  tbGetBuffer(strlen(tmp)+1);
+	strcpy(buf,tmp);
+	return buf;
+    }
+    if (format==XkbMessage) {
+	prefix= "";
+	suffix= "";
+	slen= plen= 0;
+    }
+    else {
+	prefix= "XkbNKN_";
+	plen= 7;
+	if (format==XkbCFile)
+	     suffix= "Mask";
+	else suffix= "";
+	slen= strlen(suffix);
+    }
+    for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) {
+	if (detail&bit) {
+	    if (len!=0)	len+= 1;	/* room for '+' or '|' */
+	    len+= plen+slen+strlen(nknNames[i]);
+	}
+    }
+    buf= tbGetBuffer(len+1);
+    buf[0]= '\0';
+    for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) {
+	if (detail&bit) {
+	    if (len!=0) {
+		if (format==XkbCFile)	buf[len++]= '|';
+		else			buf[len++]= '+';
+	    }
+	    if (plen) {
+		strcpy(&buf[len],prefix);
+		len+= plen;
+	    }
+	    strcpy(&buf[len],nknNames[i]);
+	    len+= strlen(nknNames[i]);
+	    if (slen) {
+		strcpy(&buf[len],suffix);
+		len+= slen;
+	    }
+	}
+    }
+    buf[len++]= '\0';
+    return buf;
+}
+
+static char *ctrlNames[] = {
+	"repeatKeys",
+	"slowKeys",
+	"bounceKeys",
+	"stickyKeys",
+	"mouseKeys",
+	"mouseKeysAccel",
+	"accessXKeys",
+	"accessXTimeout",
+	"accessXFeedback",
+	"audibleBell",
+	"overlay1",
+	"overlay2",
+	"ignoreGroupLock"
+};
+
+char *
+XkbControlsMaskText(unsigned ctrls,unsigned format)
+{
+int		len;
+unsigned	i,bit,tmp;
+char *		buf;
+
+    if (ctrls==0) {
+	buf= tbGetBuffer(5);
+	if (format==XkbCFile)
+	     strcpy(buf,"0");
+	else strcpy(buf,"none");
+	return buf;
+    }
+    tmp= ctrls&XkbAllBooleanCtrlsMask;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+	if (tmp&bit) {
+	    tmp&= ~bit;
+	    len+= strlen(ctrlNames[i])+1;
+	    if (format==XkbCFile)
+		len+= 7;
+	}
+    }
+    buf= tbGetBuffer(len+1);
+    tmp= ctrls&XkbAllBooleanCtrlsMask;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+	if (tmp&bit) {
+	    tmp&= ~bit;
+	    if (format==XkbCFile) {
+		if (len!=0)
+		    buf[len++]= '|';
+		sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]);
+		buf[len+3]= toupper(buf[len+3]);
+	    }
+	    else {
+		if (len!=0)
+		    buf[len++]= '+';
+		sprintf(&buf[len],"%s",ctrlNames[i]);
+	    }
+	    len+= strlen(&buf[len]);
+	}
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbStringText(char *str,unsigned format)
+{
+char *	buf;
+register char *in,*out;
+int	len;
+Bool	ok;
+
+    if (str==NULL) {
+	buf= tbGetBuffer(2);
+	buf[0]='\0';
+	return buf;
+    }
+    else if (format==XkbXKMFile)
+	return str;
+    for (ok= True,len=0,in=str;*in!='\0';in++,len++) {
+	if (!isprint(*in)) {
+	    ok= False;
+	    switch (*in) {
+		case '\n': case '\t': case '\v':
+		case '\b': case '\r': case '\f':
+		    len++;
+		    break;
+		default:
+		    len+= 4;
+		    break;
+	    }
+	}
+    }
+    if (ok)
+	return str;
+    buf= tbGetBuffer(len+1);
+    for (in=str,out=buf;*in!='\0';in++) {
+	if (isprint(*in))
+	    *out++= *in;
+	else {
+	    *out++= '\\';
+	    if (*in=='\n')	*out++= 'n';
+	    else if (*in=='\t')	*out++= 't';
+	    else if (*in=='\v')	*out++= 'v';
+	    else if (*in=='\b')	*out++= 'b';
+	    else if (*in=='\r')	*out++= 'r';
+	    else if (*in=='\f')	*out++= 'f';
+	    else if ((*in=='\033')&&(format==XkbXKMFile)) {
+		*out++= 'e';
+	    }
+	    else {
+		*out++= '0';
+		sprintf(out,"%o",*in);
+		while (*out!='\0')
+		    out++;
+	    }
+	}
+    }
+    *out++= '\0';
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbGeomFPText(int val,unsigned format)
+{
+int	whole,frac;
+char *	buf;
+
+    buf= tbGetBuffer(12);
+    if (format==XkbCFile) {
+	sprintf(buf,"%d",val);
+    }
+    else {
+	whole= val/XkbGeomPtsPerMM;
+	frac= val%XkbGeomPtsPerMM;
+	if (frac!=0)
+	     sprintf(buf,"%d.%d",whole,frac);
+	else sprintf(buf,"%d",whole);
+    }
+    return buf;
+}
+
+char *
+XkbDoodadTypeText(unsigned type,unsigned format)
+{
+char *	buf;
+    if (format==XkbCFile) {
+	buf= tbGetBuffer(24);
+	if (type==XkbOutlineDoodad)	   strcpy(buf,"XkbOutlineDoodad");
+	else if (type==XkbSolidDoodad)	   strcpy(buf,"XkbSolidDoodad");
+	else if (type==XkbTextDoodad)	   strcpy(buf,"XkbTextDoodad");
+	else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad");
+	else if (type==XkbLogoDoodad)	   strcpy(buf,"XkbLogoDoodad");
+	else				   sprintf(buf,"UnknownDoodad%d",type);
+    }
+    else {
+	buf= tbGetBuffer(12);
+	if (type==XkbOutlineDoodad)	   strcpy(buf,"outline");
+	else if (type==XkbSolidDoodad)	   strcpy(buf,"solid");
+	else if (type==XkbTextDoodad)	   strcpy(buf,"text");
+	else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator");
+	else if (type==XkbLogoDoodad)	   strcpy(buf,"logo");
+	else				   sprintf(buf,"unknown%d",type);
+    }
+    return buf;
+}
+
+static char *actionTypeNames[XkbSA_NumActions]= {
+    "NoAction", 
+    "SetMods",      "LatchMods",    "LockMods", 
+    "SetGroup",     "LatchGroup",   "LockGroup",
+    "MovePtr",
+    "PtrBtn",       "LockPtrBtn",
+    "SetPtrDflt",
+    "ISOLock",
+    "Terminate",    "SwitchScreen", 
+    "SetControls",  "LockControls",
+    "ActionMessage",
+    "RedirectKey",
+    "DeviceBtn",    "LockDeviceBtn"
+};
+
+char *
+XkbActionTypeText(unsigned type,unsigned format)
+{
+static char buf[32];
+char *rtrn;
+
+    if (type<=XkbSA_LastAction) {
+	rtrn= actionTypeNames[type];
+	if (format==XkbCFile) {
+	    sprintf(buf,"XkbSA_%s",rtrn);
+	    return buf;
+	}
+	return rtrn;
+    }
+    sprintf(buf,"Private");
+    return buf;
+}
+
+/***====================================================================***/
+
+static int
+TryCopyStr(char *to,char *from,int *pLeft)
+{
+register int len;
+    if (*pLeft>0) {
+	len= strlen(from);
+	if (len<((*pLeft)-3)) {
+	    strcat(to,from);
+	    *pLeft-= len;
+	    return True;
+	}
+    }
+    *pLeft= -1;
+    return False;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyNoActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int*sz)
+{
+    return True;
+}
+
+static Bool
+CopyModActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int* sz)
+{
+XkbModAction *	act;
+unsigned	tmp;
+
+    act= &action->mods;
+    tmp= XkbModActionVMods(act);
+    TryCopyStr(buf,"modifiers=",sz);
+    if (act->flags&XkbSA_UseModMapMods)
+	  TryCopyStr(buf,"modMapMods",sz);
+    else if (act->real_mods || tmp) {
+	 TryCopyStr(buf,
+		     XkbVModMaskText(dpy,xkb,act->real_mods,tmp,XkbXKBFile),
+		     sz);
+    }
+    else TryCopyStr(buf,"none",sz);
+    if (act->type==XkbSA_LockMods)
+	return True;
+    if (act->flags&XkbSA_ClearLocks)
+	TryCopyStr(buf,",clearLocks",sz);
+    if (act->flags&XkbSA_LatchToLock)
+	TryCopyStr(buf,",latchToLock",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyGroupActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbGroupAction *	act;
+char			tbuf[32];
+
+    act= &action->group;
+    TryCopyStr(buf,"group=",sz);
+    if (act->flags&XkbSA_GroupAbsolute)
+	 sprintf(tbuf,"%d",XkbSAGroup(act)+1);
+    else if (XkbSAGroup(act)<0)
+	 sprintf(tbuf,"%d",XkbSAGroup(act));
+    else sprintf(tbuf,"+%d",XkbSAGroup(act));
+    TryCopyStr(buf,tbuf,sz);
+    if (act->type==XkbSA_LockGroup)
+	return True;
+    if (act->flags&XkbSA_ClearLocks)
+	TryCopyStr(buf,",clearLocks",sz);
+    if (act->flags&XkbSA_LatchToLock)
+	TryCopyStr(buf,",latchToLock",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyMovePtrArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbPtrAction *	act;
+int		x,y;
+char		tbuf[32];
+
+    act= &action->ptr;
+    x= XkbPtrActionX(act);
+    y= XkbPtrActionY(act);
+    if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0))
+	 sprintf(tbuf,"x=%d",x);
+    else sprintf(tbuf,"x=+%d",x);
+    TryCopyStr(buf,tbuf,sz);
+
+    if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0))
+	 sprintf(tbuf,",y=%d",y);
+    else sprintf(tbuf,",y=+%d",y);
+    TryCopyStr(buf,tbuf,sz);
+    if (act->flags&XkbSA_NoAcceleration)
+	TryCopyStr(buf,",!accel",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyPtrBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbPtrBtnAction *	act;
+char			tbuf[32];
+
+    act= &action->btn;
+    TryCopyStr(buf,"button=",sz);
+    if ((act->button>0)&&(act->button<6)) {
+	 sprintf(tbuf,"%d",act->button);
+	 TryCopyStr(buf,tbuf,sz);
+    }
+    else TryCopyStr(buf,"default",sz);
+    if (act->count>0) {
+	sprintf(tbuf,",count=%d",act->count);
+	TryCopyStr(buf,tbuf,sz);
+    }
+    if (action->type==XkbSA_LockPtrBtn) {
+	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
+	    case XkbSA_LockNoLock:
+		sprintf(tbuf,",affect=unlock"); break;
+	    case XkbSA_LockNoUnlock:
+		sprintf(tbuf,",affect=lock"); break;
+	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
+		sprintf(tbuf,",affect=neither"); break;
+	    default:
+		sprintf(tbuf,",affect=both"); break;
+	}
+	TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySetPtrDfltArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbPtrDfltAction *	act;
+char			tbuf[32];
+
+    act= &action->dflt;
+    if (act->affect==XkbSA_AffectDfltBtn) {
+	TryCopyStr(buf,"affect=button,button=",sz);
+	if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0))
+	     sprintf(tbuf,"%d",XkbSAPtrDfltValue(act));
+	else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act));
+	TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+static Bool
+CopyISOLockArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbISOAction *	act;
+char		tbuf[64];
+
+    act= &action->iso;
+    if (act->flags&XkbSA_ISODfltIsGroup) {
+	TryCopyStr(tbuf,"group=",sz);
+	if (act->flags&XkbSA_GroupAbsolute)
+	     sprintf(tbuf,"%d",XkbSAGroup(act)+1);
+	else if (XkbSAGroup(act)<0)
+	     sprintf(tbuf,"%d",XkbSAGroup(act));
+	else sprintf(tbuf,"+%d",XkbSAGroup(act));
+	TryCopyStr(buf,tbuf,sz);
+    }
+    else {
+	unsigned tmp;
+	tmp= XkbModActionVMods(act);
+	TryCopyStr(buf,"modifiers=",sz);
+	if (act->flags&XkbSA_UseModMapMods)
+	     TryCopyStr(buf,"modMapMods",sz);
+	else if (act->real_mods || tmp) {
+	    if (act->real_mods) {
+		TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz);
+		if (tmp)
+		    TryCopyStr(buf,"+",sz);
+	    }
+	    if (tmp)
+		TryCopyStr(buf,XkbVModMaskText(dpy,xkb,0,tmp,XkbXKBFile),sz);
+	}
+	else TryCopyStr(buf,"none",sz);
+    }
+    TryCopyStr(buf,",affect=",sz);
+    if ((act->affect&XkbSA_ISOAffectMask)==0)
+	TryCopyStr(buf,"all",sz);
+    else {
+	int nOut= 0;
+	if ((act->affect&XkbSA_ISONoAffectMods)==0) {
+	    TryCopyStr(buf,"mods",sz);
+	    nOut++;
+	}
+	if ((act->affect&XkbSA_ISONoAffectGroup)==0) {
+	    sprintf(tbuf,"%sgroups",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if ((act->affect&XkbSA_ISONoAffectPtr)==0) {
+	    sprintf(tbuf,"%spointer",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if ((act->affect&XkbSA_ISONoAffectCtrls)==0) {
+	    sprintf(tbuf,"%scontrols",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySwitchScreenArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbSwitchScreenAction *	act;
+char			tbuf[32];
+
+    act= &action->screen;
+    if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0))
+	 sprintf(tbuf,"screen=%d",XkbSAScreen(act));
+    else sprintf(tbuf,"screen=+%d",XkbSAScreen(act));
+    TryCopyStr(buf,tbuf,sz);
+    if (act->flags&XkbSA_SwitchApplication)
+	 TryCopyStr(buf,",!same",sz);
+    else TryCopyStr(buf,",same",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySetLockControlsArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,
+							char *buf,int *sz)
+{
+XkbCtrlsAction *	act;
+unsigned		tmp;
+char			tbuf[32];
+
+    act= &action->ctrls;
+    tmp= XkbActionCtrls(act);
+    TryCopyStr(buf,"controls=",sz);
+    if (tmp==0)
+	TryCopyStr(buf,"none",sz);
+    else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask)
+	TryCopyStr(buf,"all",sz);
+    else {
+	int nOut= 0;
+	if (tmp&XkbRepeatKeysMask) {
+	    sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbSlowKeysMask) {
+	    sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbBounceKeysMask) {
+	    sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbStickyKeysMask) {
+	    sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbMouseKeysMask) {
+	    sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbMouseKeysAccelMask) {
+	    sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbAccessXKeysMask) {
+	    sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbAccessXTimeoutMask) {
+	    sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbAccessXFeedbackMask) {
+	    sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbAudibleBellMask) {
+	    sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbOverlay1Mask) {
+	    sprintf(tbuf,"%sOverlay1",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbOverlay2Mask) {
+	    sprintf(tbuf,"%sOverlay2",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+	if (tmp&XkbIgnoreGroupLockMask) {
+	    sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":""));
+	    TryCopyStr(buf,tbuf,sz);
+	    nOut++;
+	}
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyActionMessageArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbMessageAction *	act;
+unsigned		all;
+char			tbuf[32];
+
+    act= &action->msg;
+    all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease;
+    TryCopyStr(buf,"report=",sz);
+    if ((act->flags&all)==0)
+	TryCopyStr(buf,"none",sz);
+    else if ((act->flags&all)==all)
+	TryCopyStr(buf,"all",sz);
+    else if (act->flags&XkbSA_MessageOnPress)
+	 TryCopyStr(buf,"KeyPress",sz);
+    else TryCopyStr(buf,"KeyRelease",sz);
+    sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz);
+    return True;
+}
+
+static Bool
+CopyRedirectKeyArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbRedirectKeyAction *	act;
+char			tbuf[32],*tmp;
+unsigned		kc;
+unsigned		vmods,vmods_mask;
+
+    act= &action->redirect;
+    kc= act->new_key;
+    vmods= XkbSARedirectVMods(act);
+    vmods_mask= XkbSARedirectVModsMask(act);
+    if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) &&
+				(xkb->names->keys[kc].name[0]!='\0')) {
+	char *kn;
+	kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
+	sprintf(tbuf,"key=%s",kn);
+    }
+    else sprintf(tbuf,"key=%d",kc);
+    TryCopyStr(buf,tbuf,sz);
+    if ((act->mods_mask==0)&&(vmods_mask==0))
+	return True;
+    if ((act->mods_mask==XkbAllModifiersMask)&&
+	(vmods_mask==XkbAllVirtualModsMask)) {
+	tmp= XkbVModMaskText(dpy,xkb,act->mods,vmods,XkbXKBFile);
+	TryCopyStr(buf,",mods=",sz);
+	TryCopyStr(buf,tmp,sz);
+    }
+    else {
+	if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) {
+	    tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&act->mods,
+					 vmods_mask&vmods,XkbXKBFile);
+	    TryCopyStr(buf,",mods= ",sz);
+	    TryCopyStr(buf,tmp,sz);
+	}
+	if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) {
+	    tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&(~act->mods),
+					 vmods_mask&(~vmods),XkbXKBFile);
+	    TryCopyStr(buf,",clearMods= ",sz);
+	    TryCopyStr(buf,tmp,sz);
+	}
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyDeviceBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+								int *sz)
+{
+XkbDeviceBtnAction *	act;
+char			tbuf[32];
+
+    act= &action->devbtn;
+    sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz);
+    TryCopyStr(buf,",button=",sz);
+    sprintf(tbuf,"%d",act->button);
+    TryCopyStr(buf,tbuf,sz);
+    if (act->count>0) {
+	sprintf(tbuf,",count=%d",act->count);
+	TryCopyStr(buf,tbuf,sz);
+    }
+    if (action->type==XkbSA_LockDeviceBtn) {
+	switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
+	    case XkbSA_LockNoLock:
+		sprintf(tbuf,",affect=unlock"); break;
+	    case XkbSA_LockNoUnlock:
+		sprintf(tbuf,",affect=lock"); break;
+	    case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
+		sprintf(tbuf,",affect=neither"); break;
+	    default:
+		sprintf(tbuf,",affect=both"); break;
+	}
+	TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyOtherArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbAnyAction *	act;
+char		tbuf[32];
+
+    act= &action->any;
+    sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz);
+    return True;
+}
+
+typedef	Bool	(*actionCopy)(
+	Display *	/* dpy */,
+	XkbDescPtr 	/* xkb */,
+	XkbAction *	/* action */,
+	char *		/* buf */,
+	int*		/* sz */
+);
+static actionCopy	copyActionArgs[XkbSA_NumActions] = {
+	CopyNoActionArgs		/* NoAction	*/,
+	CopyModActionArgs		/* SetMods	*/,
+	CopyModActionArgs		/* LatchMods	*/,
+	CopyModActionArgs		/* LockMods	*/,
+	CopyGroupActionArgs		/* SetGroup	*/,
+	CopyGroupActionArgs		/* LatchGroup	*/,
+	CopyGroupActionArgs		/* LockGroup	*/,
+	CopyMovePtrArgs			/* MovePtr	*/,
+	CopyPtrBtnArgs			/* PtrBtn	*/,
+	CopyPtrBtnArgs			/* LockPtrBtn	*/,
+	CopySetPtrDfltArgs		/* SetPtrDflt	*/,
+	CopyISOLockArgs			/* ISOLock	*/,
+	CopyNoActionArgs		/* Terminate	*/,
+	CopySwitchScreenArgs		/* SwitchScreen	*/,
+	CopySetLockControlsArgs		/* SetControls	*/,
+	CopySetLockControlsArgs		/* LockControls	*/,
+	CopyActionMessageArgs		/* ActionMessage*/,
+	CopyRedirectKeyArgs		/* RedirectKey	*/,
+	CopyDeviceBtnArgs		/* DeviceBtn	*/,
+	CopyDeviceBtnArgs		/* LockDeviceBtn*/
+};
+
+#define	ACTION_SZ	256
+
+char *
+XkbActionText(Display *dpy,XkbDescPtr xkb,XkbAction *action,unsigned format)
+{
+char	buf[ACTION_SZ],*tmp;
+int	sz;
+
+    if (format==XkbCFile) {
+	sprintf(buf,
+	    "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
+	    XkbActionTypeText(action->type,XkbCFile),
+	    action->any.data[0],action->any.data[1],action->any.data[2],
+	    action->any.data[3],action->any.data[4],action->any.data[5],
+	    action->any.data[6]);
+    }
+    else {
+	sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile));
+	sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */
+	if (action->type<(unsigned)XkbSA_NumActions)
+	     (*copyActionArgs[action->type])(dpy,xkb,action,buf,&sz);
+	else CopyOtherArgs(dpy,xkb,action,buf,&sz);
+	TryCopyStr(buf,")",&sz);
+    }
+    tmp= tbGetBuffer(strlen(buf)+1);
+    if (tmp!=NULL)
+	strcpy(tmp,buf);
+    return tmp;
+}
+
+char *
+XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format)
+{
+char	buf[256],*tmp;
+
+    if (format==XkbCFile) {
+	if (behavior->type==XkbKB_Default)
+	     sprintf(buf,"{   0,    0 }");
+	else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data);
+    }
+    else {
+	unsigned 	type,permanent;
+	type= behavior->type&XkbKB_OpMask;
+	permanent=((behavior->type&XkbKB_Permanent)!=0);
+
+	if (type==XkbKB_Lock) {
+	    sprintf(buf,"lock= %s",(permanent?"Permanent":"True"));
+	}
+	else if (type==XkbKB_RadioGroup) {
+	    int 	g;
+	    char	*tmp;
+	    g= ((behavior->data)&(~XkbKB_RGAllowNone))+1;
+	    if (XkbKB_RGAllowNone&behavior->data) {
+		sprintf(buf,"allowNone,");
+		tmp= &buf[strlen(buf)];
+	    }
+	    else tmp= buf;
+	    if (permanent)
+		 sprintf(tmp,"permanentRadioGroup= %d",g);
+	    else sprintf(tmp,"radioGroup= %d",g);
+	}
+	else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) {
+	    int ndx,kc;
+	    char *kn;
+
+	    ndx= ((type==XkbKB_Overlay1)?1:2);
+	    kc= behavior->data;
+	    if ((xkb)&&(xkb->names)&&(xkb->names->keys))
+		kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
+	    else {
+		static char tbuf[8];
+		sprintf(tbuf,"%d",kc);
+		kn= tbuf;
+	    }
+	    if (permanent)
+		 sprintf(buf,"permanentOverlay%d= %s",ndx,kn);
+	    else sprintf(buf,"overlay%d= %s",ndx,kn);
+	}
+    }
+    tmp= tbGetBuffer(strlen(buf)+1);
+    if (tmp!=NULL)
+	strcpy(tmp,buf);
+    return tmp;
+}
+
+/***====================================================================***/
+
+char *
+XkbIndentText(unsigned size)
+{
+static char buf[32];
+register int i;
+
+    if (size>31)
+	size= 31;
+
+    for (i=0;i<size;i++) {
+	buf[i]= ' ';
+    }
+    buf[size]= '\0';
+    return buf;
+}
diff --git a/xkb/xkmread.c b/xkb/xkmread.c
index 5441243..fec8687 100644
--- a/xkb/xkmread.c
+++ b/xkb/xkmread.c
@@ -167,89 +167,6 @@ int	count,nRead=0;
     return nRead;
 }
 
-unsigned
-_XkbKSCheckCase(KeySym ks)
-{
-unsigned	set,rtrn;
-
-    set= (ks & (~0xff)) >> 8;
-    rtrn= 0;
-    switch (set) {
-	case 0:		/* latin 1 */
-	    if (((ks>=XK_A)&&(ks<=XK_Z))||
-		((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if (((ks>=XK_a)&&(ks<=XK_z))||
-		((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-	case 1:		/* latin 2 */
-	    if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
-		((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
-		((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-	case 2:		/* latin 3 */
-	    if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
-		((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
-		((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-	case 3:		/* latin 4 */
-	    if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
-	        (ks==XK_ENG)||
-		((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
-	        (ks==XK_eng)||
-		((ks>=XK_amacron)&&(ks<=XK_umacron))) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-	case 18:		/* latin 8 */
-	    if ((ks==XK_Babovedot)||
-                ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
-		((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
-	        (ks==XK_Mabovedot)||
-	        (ks==XK_Pabovedot)||
-	        (ks==XK_Sabovedot)||
-	        (ks==XK_Wdiaeresis)||
-		((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if ((ks==XK_babovedot)||
-	        (ks==XK_dabovedot)||
-	        (ks==XK_fabovedot)||
-	        (ks==XK_mabovedot)||
-                ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
-	        (ks==XK_ygrave)||
-		((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-	case 19:		/* latin 9 */
-	    if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
-		rtrn|= _XkbKSUpper;
-	    }
-	    if (ks==XK_oe) {
-		rtrn|= _XkbKSLower;
-	    }
-	    break;
-    }
-    return rtrn;
-}
-
 /***====================================================================***/
 
 static int
@@ -1251,10 +1168,14 @@ int			nRead;
 		*loaded_rtrn|= XkmGeometryMask;
 	    break;
 	default:
+	    _XkbLibError(_XkbErrBadImplementation,
+	    			XkbConfigText(tmpTOC.type,XkbMessage),0);
 	    nRead= 0;
 	    break;
     }
     if (nRead!=tmpTOC.size) {
+	_XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
+						nRead-tmpTOC.size);
 	return 0;
     }
     return (nRead>=0);
@@ -1288,6 +1209,8 @@ char 		name[100];
 		return _XkbDupString(name);
 	    break;
 	default:
+	    _XkbLibError(_XkbErrBadImplementation,
+				XkbConfigText(tmpTOC.type,XkbMessage),0);
 	    break;
     }
     return NULL;
@@ -1353,6 +1276,8 @@ unsigned		which= need|want;
 		tmp= ReadXkmGeometry(file,result);
 		break;
 	    default:
+		_XkbLibError(_XkbErrBadImplementation,
+				XkbConfigText(tmpTOC.type,XkbMessage),0);
 		tmp= 0;
 		break;
 	}
@@ -1362,7 +1287,8 @@ unsigned		which= need|want;
 	    result->defined|= (1<<toc[i].type);
 	}
 	if (nRead!=tmpTOC.size) {
-            return 0;
+	    _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
+	    						nRead-tmpTOC.size);
 	}
     }
     return which;



More information about the xorg-commit mailing list