xkbout.c revision 4cd6a3ae
18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
38c9fbc29Smrg
48c9fbc29Smrg Permission to use, copy, modify, and distribute this
58c9fbc29Smrg software and its documentation for any purpose and without
68c9fbc29Smrg fee is hereby granted, provided that the above copyright
78c9fbc29Smrg notice appear in all copies and that both that copyright
88c9fbc29Smrg notice and this permission notice appear in supporting
94cd6a3aeSmrg documentation, and that the name of Silicon Graphics not be
104cd6a3aeSmrg used in advertising or publicity pertaining to distribution
118c9fbc29Smrg of the software without specific prior written permission.
124cd6a3aeSmrg Silicon Graphics makes no representation about the suitability
138c9fbc29Smrg of this software for any purpose. It is provided "as is"
148c9fbc29Smrg without any express or implied warranty.
154cd6a3aeSmrg
164cd6a3aeSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
174cd6a3aeSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
188c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
194cd6a3aeSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
204cd6a3aeSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
214cd6a3aeSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
228c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
238c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
248c9fbc29Smrg
258c9fbc29Smrg ********************************************************/
268c9fbc29Smrg
278c9fbc29Smrg#ifdef HAVE_DIX_CONFIG_H
288c9fbc29Smrg#include <dix-config.h>
298c9fbc29Smrg#elif defined(HAVE_CONFIG_H)
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg
338c9fbc29Smrg#include <stdio.h>
348c9fbc29Smrg#include <ctype.h>
358c9fbc29Smrg#include <stdlib.h>
368c9fbc29Smrg#include <X11/Xfuncs.h>
378c9fbc29Smrg
388c9fbc29Smrg#ifndef XKB_IN_SERVER
398c9fbc29Smrg
408c9fbc29Smrg#include <X11/Xlib.h>
418c9fbc29Smrg#include <X11/XKBlib.h>
428c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
438c9fbc29Smrg
448c9fbc29Smrg#include "XKMformat.h"
458c9fbc29Smrg#include "XKBfileInt.h"
468c9fbc29Smrg
478c9fbc29Smrg#else
488c9fbc29Smrg
498c9fbc29Smrg#include <X11/X.h>
508c9fbc29Smrg#include <X11/keysym.h>
518c9fbc29Smrg#include <X11/Xproto.h>
528c9fbc29Smrg#include "misc.h"
538c9fbc29Smrg#include "inputstr.h"
548c9fbc29Smrg#include "dix.h"
558c9fbc29Smrg#include <X11/extensions/XKBstr.h>
568c9fbc29Smrg#define XKBSRV_NEED_FILE_FUNCS	1
578c9fbc29Smrg#include <X11/extensions/XKBsrv.h>
588c9fbc29Smrg
598c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
608c9fbc29Smrg#include <X11/extensions/XKBfile.h>
618c9fbc29Smrg
628c9fbc29Smrg#endif
638c9fbc29Smrg
648c9fbc29Smrg#define	VMOD_HIDE_VALUE	0
658c9fbc29Smrg#define	VMOD_SHOW_VALUE	1
668c9fbc29Smrg#define	VMOD_COMMENT_VALUE 2
678c9fbc29Smrg
688c9fbc29Smrgstatic Bool
698c9fbc29SmrgWriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue)
708c9fbc29Smrg{
718c9fbc29Smrgregister int 	i,nMods;
728c9fbc29SmrgAtom *		vmodNames;
738c9fbc29Smrg
748c9fbc29Smrg    if (xkb==NULL)
758c9fbc29Smrg	return False;
768c9fbc29Smrg    if (xkb->names!=NULL)
778c9fbc29Smrg	 vmodNames= xkb->names->vmods;
788c9fbc29Smrg    else vmodNames= NULL;
798c9fbc29Smrg
808c9fbc29Smrg    for (i=nMods=0;i<XkbNumVirtualMods;i++) {
818c9fbc29Smrg	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
828c9fbc29Smrg	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
838c9fbc29Smrg	    else		fprintf(file,",");
848c9fbc29Smrg	    fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile));
858c9fbc29Smrg	    if ((showValue!=VMOD_HIDE_VALUE)&&
868c9fbc29Smrg		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
878c9fbc29Smrg		if (showValue==VMOD_COMMENT_VALUE) {
888c9fbc29Smrg		    fprintf(file,"/* = %s */",
898c9fbc29Smrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
908c9fbc29Smrg		}
918c9fbc29Smrg		else  {
928c9fbc29Smrg		    fprintf(file,"= %s",
938c9fbc29Smrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
948c9fbc29Smrg		}
958c9fbc29Smrg	    }
968c9fbc29Smrg	    nMods++;
978c9fbc29Smrg	}
988c9fbc29Smrg    }
998c9fbc29Smrg    if (nMods>0)
1008c9fbc29Smrg	fprintf(file,";\n\n");
1018c9fbc29Smrg    return True;
1028c9fbc29Smrg}
1038c9fbc29Smrg
1048c9fbc29Smrg/***====================================================================***/
1058c9fbc29Smrg
1068c9fbc29Smrgstatic Bool
1078c9fbc29SmrgWriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action)
1088c9fbc29Smrg{
1098c9fbc29SmrgXkbDescPtr	xkb;
1108c9fbc29SmrgDisplay *	dpy;
1118c9fbc29Smrg
1128c9fbc29Smrg    xkb= result->xkb;
1138c9fbc29Smrg    dpy= xkb->dpy;
1148c9fbc29Smrg    fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile));
1158c9fbc29Smrg    return True;
1168c9fbc29Smrg}
1178c9fbc29Smrg
1188c9fbc29Smrg/***====================================================================***/
1198c9fbc29Smrg
1208c9fbc29SmrgBool
1218c9fbc29SmrgXkbWriteXKBKeycodes(	FILE *			file,
1228c9fbc29Smrg			XkbFileInfo *		result,
1238c9fbc29Smrg			Bool			topLevel,
1248c9fbc29Smrg			Bool			showImplicit,
1258c9fbc29Smrg			XkbFileAddOnFunc	addOn,
1268c9fbc29Smrg			void *			priv)
1278c9fbc29Smrg{
1288c9fbc29SmrgAtom			kcName;
1298c9fbc29Smrgregister unsigned 	i;
1308c9fbc29SmrgXkbDescPtr		xkb;
1318c9fbc29SmrgDisplay *		dpy;
1324cd6a3aeSmrgconst char *		alternate;
1338c9fbc29Smrg
1348c9fbc29Smrg    xkb= result->xkb;
1358c9fbc29Smrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
1368c9fbc29Smrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
1378c9fbc29Smrg	return False;
1388c9fbc29Smrg    }
1398c9fbc29Smrg    dpy= xkb->dpy;
1408c9fbc29Smrg    kcName= xkb->names->keycodes;
1418c9fbc29Smrg    if (kcName!=None)
1428c9fbc29Smrg	 fprintf(file,"xkb_keycodes \"%s\" {\n",
1438c9fbc29Smrg					XkbAtomText(dpy,kcName,XkbXKBFile));
1448c9fbc29Smrg    else fprintf(file,"xkb_keycodes {\n");
1458c9fbc29Smrg    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
1468c9fbc29Smrg    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
1478c9fbc29Smrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
1488c9fbc29Smrg	if (xkb->names->keys[i].name[0]!='\0') {
1498c9fbc29Smrg	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
1508c9fbc29Smrg		 alternate= "alternate ";
1518c9fbc29Smrg	    else alternate= "";
1528c9fbc29Smrg	    fprintf(file,"    %s%6s = %d;\n",alternate,
1538c9fbc29Smrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
1548c9fbc29Smrg			i);
1558c9fbc29Smrg	}
1568c9fbc29Smrg    }
1578c9fbc29Smrg    if (xkb->indicators!=NULL) {
1588c9fbc29Smrg	for (i=0;i<XkbNumIndicators;i++) {
1594cd6a3aeSmrg	    const char *type;
1608c9fbc29Smrg	    if (xkb->indicators->phys_indicators&(1<<i))
1618c9fbc29Smrg			type= "    ";
1628c9fbc29Smrg	    else	type= "    virtual ";
1638c9fbc29Smrg	    if (xkb->names->indicators[i]!=None) {
1648c9fbc29Smrg		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
1658c9fbc29Smrg			XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile));
1668c9fbc29Smrg	    }
1678c9fbc29Smrg	}
1688c9fbc29Smrg    }
1698c9fbc29Smrg    if (xkb->names->key_aliases!=NULL) {
1708c9fbc29Smrg	XkbKeyAliasPtr	pAl;
1718c9fbc29Smrg	pAl= xkb->names->key_aliases;
1728c9fbc29Smrg	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
1738c9fbc29Smrg	    fprintf(file,"    alias %6s = %6s;\n",
1748c9fbc29Smrg			XkbKeyNameText(pAl->alias,XkbXKBFile),
1758c9fbc29Smrg			XkbKeyNameText(pAl->real,XkbXKBFile));
1768c9fbc29Smrg	}
1778c9fbc29Smrg    }
1788c9fbc29Smrg    if (addOn)
1798c9fbc29Smrg	(*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv);
1808c9fbc29Smrg    fprintf(file,"};\n\n");
1818c9fbc29Smrg    return True;
1828c9fbc29Smrg}
1838c9fbc29Smrg
1848c9fbc29SmrgBool
1858c9fbc29SmrgXkbWriteXKBKeyTypes(	FILE *			file,
1868c9fbc29Smrg			XkbFileInfo *		result,
1878c9fbc29Smrg			Bool			topLevel,
1888c9fbc29Smrg			Bool			showImplicit,
1898c9fbc29Smrg			XkbFileAddOnFunc	addOn,
1908c9fbc29Smrg			void *			priv)
1918c9fbc29Smrg{
1928c9fbc29SmrgDisplay *		dpy;
1938c9fbc29Smrgregister unsigned	i,n;
1948c9fbc29SmrgXkbKeyTypePtr		type;
1958c9fbc29SmrgXkbKTMapEntryPtr	entry;
1968c9fbc29SmrgXkbDescPtr		xkb;
1978c9fbc29Smrg
1988c9fbc29Smrg    xkb= result->xkb;
1998c9fbc29Smrg    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
2008c9fbc29Smrg	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
2018c9fbc29Smrg	return False;
2028c9fbc29Smrg    }
2038c9fbc29Smrg    dpy= xkb->dpy;
2048c9fbc29Smrg    if (xkb->map->num_types<XkbNumRequiredTypes) {
2058c9fbc29Smrg	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
2068c9fbc29Smrg	return 0;
2078c9fbc29Smrg    }
2088c9fbc29Smrg    if ((xkb->names==NULL)||(xkb->names->types==None))
2098c9fbc29Smrg	 fprintf(file,"xkb_types {\n\n");
2108c9fbc29Smrg    else fprintf(file,"xkb_types \"%s\" {\n\n",
2118c9fbc29Smrg			XkbAtomText(dpy,xkb->names->types,XkbXKBFile));
2128c9fbc29Smrg    WriteXKBVModDecl(file,dpy,xkb,
2138c9fbc29Smrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
2148c9fbc29Smrg
2158c9fbc29Smrg    type= xkb->map->types;
2168c9fbc29Smrg    for (i=0;i<xkb->map->num_types;i++,type++) {
2178c9fbc29Smrg	fprintf(file,"    type \"%s\" {\n",
2188c9fbc29Smrg		XkbAtomText(dpy,type->name,XkbXKBFile));
2198c9fbc29Smrg	fprintf(file,"        modifiers= %s;\n",
2208c9fbc29Smrg	       XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods,
2218c9fbc29Smrg								XkbXKBFile));
2228c9fbc29Smrg	entry= type->map;
2238c9fbc29Smrg	for (n=0;n<type->map_count;n++,entry++) {
2244cd6a3aeSmrg	    char *str;
2258c9fbc29Smrg	    str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods,
2268c9fbc29Smrg								XkbXKBFile);
2278c9fbc29Smrg	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
2288c9fbc29Smrg	    if ((type->preserve)&&((type->preserve[n].real_mods)||
2298c9fbc29Smrg				   (type->preserve[n].vmods))) {
2308c9fbc29Smrg		fprintf(file,"        preserve[%s]= ",str);
2318c9fbc29Smrg		fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb,
2328c9fbc29Smrg					type->preserve[n].real_mods,
2338c9fbc29Smrg					type->preserve[n].vmods,
2348c9fbc29Smrg					XkbXKBFile));
2358c9fbc29Smrg	    }
2368c9fbc29Smrg	}
2378c9fbc29Smrg	if (type->level_names!=NULL) {
2388c9fbc29Smrg	    Atom *name= type->level_names;
2398c9fbc29Smrg	    for (n=0;n<type->num_levels;n++,name++) {
2408c9fbc29Smrg		if ((*name)==None)
2418c9fbc29Smrg		    continue;
2428c9fbc29Smrg		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
2438c9fbc29Smrg					XkbAtomText(dpy,*name,XkbXKBFile));
2448c9fbc29Smrg	    }
2458c9fbc29Smrg	}
2468c9fbc29Smrg	fprintf(file,"    };\n");
2478c9fbc29Smrg    }
2488c9fbc29Smrg    if (addOn)
2498c9fbc29Smrg	(*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv);
2508c9fbc29Smrg    fprintf(file,"};\n\n");
2518c9fbc29Smrg    return True;
2528c9fbc29Smrg}
2538c9fbc29Smrg
2548c9fbc29Smrgstatic Bool
2558c9fbc29SmrgWriteXKBIndicatorMap(	FILE *			file,
2568c9fbc29Smrg			XkbFileInfo *		result,
2578c9fbc29Smrg			Atom			name,
2588c9fbc29Smrg			XkbIndicatorMapPtr	led,
2598c9fbc29Smrg			XkbFileAddOnFunc	addOn,
2608c9fbc29Smrg			void *			priv)
2618c9fbc29Smrg{
2628c9fbc29SmrgXkbDescPtr	xkb;
2638c9fbc29Smrgchar *tmp;
2648c9fbc29Smrg
2658c9fbc29Smrg    xkb= result->xkb;
2668c9fbc29Smrg    tmp = XkbAtomGetString(xkb->dpy, name);
2678c9fbc29Smrg    fprintf(file,"    indicator \"%s\" {\n",tmp);
2688c9fbc29Smrg    _XkbFree(tmp);
2698c9fbc29Smrg    if (led->flags&XkbIM_NoExplicit)
2708c9fbc29Smrg	fprintf(file,"        !allowExplicit;\n");
2718c9fbc29Smrg    if (led->flags&XkbIM_LEDDrivesKB)
2728c9fbc29Smrg	fprintf(file,"        indicatorDrivesKeyboard;\n");
2738c9fbc29Smrg    if (led->which_groups!=0) {
2748c9fbc29Smrg	if (led->which_groups!=XkbIM_UseEffective) {
2758c9fbc29Smrg	    fprintf(file,"        whichGroupState= %s;\n",
2768c9fbc29Smrg			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
2778c9fbc29Smrg	}
2788c9fbc29Smrg	fprintf(file,"        groups= 0x%02x;\n",led->groups);
2798c9fbc29Smrg    }
2808c9fbc29Smrg    if (led->which_mods!=0) {
2818c9fbc29Smrg	if (led->which_mods!=XkbIM_UseEffective) {
2828c9fbc29Smrg	    fprintf(file,"        whichModState= %s;\n",
2838c9fbc29Smrg			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
2848c9fbc29Smrg	}
2858c9fbc29Smrg	fprintf(file,"        modifiers= %s;\n",
2868c9fbc29Smrg			XkbVModMaskText(xkb->dpy,xkb,
2878c9fbc29Smrg					led->mods.real_mods,led->mods.vmods,
2888c9fbc29Smrg					XkbXKBFile));
2898c9fbc29Smrg    }
2908c9fbc29Smrg    if (led->ctrls!=0) {
2918c9fbc29Smrg	fprintf(file,"        controls= %s;\n",
2928c9fbc29Smrg			XkbControlsMaskText(led->ctrls,XkbXKBFile));
2938c9fbc29Smrg    }
2948c9fbc29Smrg    if (addOn)
2958c9fbc29Smrg	(*addOn)(file,result,False,True,XkmIndicatorsIndex,priv);
2968c9fbc29Smrg    fprintf(file,"    };\n");
2978c9fbc29Smrg    return True;
2988c9fbc29Smrg}
2998c9fbc29Smrg
3008c9fbc29SmrgBool
3018c9fbc29SmrgXkbWriteXKBCompatMap(	FILE *			file,
3028c9fbc29Smrg			XkbFileInfo *		result,
3038c9fbc29Smrg			Bool			topLevel,
3048c9fbc29Smrg			Bool			showImplicit,
3058c9fbc29Smrg			XkbFileAddOnFunc	addOn,
3068c9fbc29Smrg			void *			priv)
3078c9fbc29Smrg{
3088c9fbc29SmrgDisplay *		dpy;
3098c9fbc29Smrgregister unsigned	i;
3108c9fbc29SmrgXkbSymInterpretPtr	interp;
3118c9fbc29SmrgXkbDescPtr		xkb;
3128c9fbc29Smrg
3138c9fbc29Smrg    xkb= result->xkb;
3148c9fbc29Smrg    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
3158c9fbc29Smrg	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
3168c9fbc29Smrg	return False;
3178c9fbc29Smrg    }
3188c9fbc29Smrg    dpy= xkb->dpy;
3198c9fbc29Smrg    if ((xkb->names==NULL)||(xkb->names->compat==None))
3208c9fbc29Smrg	 fprintf(file,"xkb_compatibility {\n\n");
3218c9fbc29Smrg    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
3228c9fbc29Smrg			XkbAtomText(dpy,xkb->names->compat,XkbXKBFile));
3238c9fbc29Smrg    WriteXKBVModDecl(file,dpy,xkb,
3248c9fbc29Smrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
3258c9fbc29Smrg
3268c9fbc29Smrg    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
3278c9fbc29Smrg    fprintf(file,"    interpret.repeat= False;\n");
3288c9fbc29Smrg    fprintf(file,"    interpret.locking= False;\n");
3298c9fbc29Smrg    interp= xkb->compat->sym_interpret;
3308c9fbc29Smrg    for (i=0;i<xkb->compat->num_si;i++,interp++) {
3314cd6a3aeSmrg	fprintf(file,"    interpret %s+%s(%s) {\n",
3328c9fbc29Smrg				((interp->sym==NoSymbol)?"Any":
3338c9fbc29Smrg					XkbKeysymText(interp->sym,XkbXKBFile)),
3348c9fbc29Smrg				XkbSIMatchText(interp->match,XkbXKBFile),
3358c9fbc29Smrg				XkbModMaskText(interp->mods,XkbXKBFile));
3368c9fbc29Smrg	if (interp->virtual_mod!=XkbNoModifier) {
3378c9fbc29Smrg	    fprintf(file,"        virtualModifier= %s;\n",
3388c9fbc29Smrg		XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile));
3398c9fbc29Smrg	}
3408c9fbc29Smrg	if (interp->match&XkbSI_LevelOneOnly)
3418c9fbc29Smrg	    fprintf(file,"        useModMapMods=level1;\n");
3428c9fbc29Smrg	if (interp->flags&XkbSI_LockingKey)
3438c9fbc29Smrg	    fprintf(file,"        locking= True;\n");
3448c9fbc29Smrg	if (interp->flags&XkbSI_AutoRepeat)
3458c9fbc29Smrg	    fprintf(file,"        repeat= True;\n");
3468c9fbc29Smrg	fprintf(file,"        action= ");
3478c9fbc29Smrg	WriteXKBAction(file,result,&interp->act);
3488c9fbc29Smrg	fprintf(file,";\n");
3498c9fbc29Smrg	fprintf(file,"    };\n");
3508c9fbc29Smrg    }
3518c9fbc29Smrg    for (i=0;i<XkbNumKbdGroups;i++) {
3528c9fbc29Smrg	XkbModsPtr	gc;
3538c9fbc29Smrg
3548c9fbc29Smrg	gc= &xkb->compat->groups[i];
3558c9fbc29Smrg	if ((gc->real_mods==0)&&(gc->vmods==0))
3568c9fbc29Smrg	    continue;
3578c9fbc29Smrg	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb,
3588c9fbc29Smrg							gc->real_mods,gc->vmods,
3598c9fbc29Smrg							XkbXKBFile));
3608c9fbc29Smrg    }
3618c9fbc29Smrg    if (xkb->indicators) {
3628c9fbc29Smrg	for (i=0;i<XkbNumIndicators;i++) {
3638c9fbc29Smrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
3648c9fbc29Smrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
3658c9fbc29Smrg		(map->which_mods!=0)||
3668c9fbc29Smrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
3678c9fbc29Smrg		(map->ctrls!=0)) {
3688c9fbc29Smrg		WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map,
3698c9fbc29Smrg								addOn,priv);
3708c9fbc29Smrg	    }
3718c9fbc29Smrg	}
3728c9fbc29Smrg    }
3738c9fbc29Smrg    if (addOn)
3748c9fbc29Smrg	(*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv);
3758c9fbc29Smrg    fprintf(file,"};\n\n");
3768c9fbc29Smrg    return True;
3778c9fbc29Smrg}
3788c9fbc29Smrg
3798c9fbc29SmrgBool
3808c9fbc29SmrgXkbWriteXKBSymbols(	FILE *			file,
3818c9fbc29Smrg			XkbFileInfo *		result,
3828c9fbc29Smrg			Bool			topLevel,
3838c9fbc29Smrg			Bool			showImplicit,
3848c9fbc29Smrg			XkbFileAddOnFunc	addOn,
3858c9fbc29Smrg			void *			priv)
3868c9fbc29Smrg{
3878c9fbc29SmrgDisplay *		dpy;
3888c9fbc29Smrgregister unsigned	i,tmp;
3898c9fbc29SmrgXkbDescPtr		xkb;
3908c9fbc29SmrgXkbClientMapPtr		map;
3918c9fbc29SmrgXkbServerMapPtr		srv;
3928c9fbc29SmrgBool			showActions;
3938c9fbc29Smrg
3948c9fbc29Smrg    xkb= result->xkb;
3958c9fbc29Smrg
3968c9fbc29Smrg    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
3978c9fbc29Smrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
3988c9fbc29Smrg	return False;
3998c9fbc29Smrg    }
4008c9fbc29Smrg    if ((!xkb->names)||(!xkb->names->keys)) {
4018c9fbc29Smrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
4028c9fbc29Smrg	return False;
4038c9fbc29Smrg    }
4048c9fbc29Smrg
4058c9fbc29Smrg    map= xkb->map;
4068c9fbc29Smrg    srv= xkb->server;
4078c9fbc29Smrg    dpy= xkb->dpy;
4088c9fbc29Smrg
4098c9fbc29Smrg    if ((xkb->names==NULL)||(xkb->names->symbols==None))
4108c9fbc29Smrg	 fprintf(file,"xkb_symbols {\n\n");
4118c9fbc29Smrg    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
4128c9fbc29Smrg			XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile));
4138c9fbc29Smrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
4148c9fbc29Smrg	if (xkb->names->groups[i]!=None) {
4158c9fbc29Smrg	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
4168c9fbc29Smrg			XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile));
4178c9fbc29Smrg	    tmp++;
4188c9fbc29Smrg	}
4198c9fbc29Smrg    }
4208c9fbc29Smrg    if (tmp>0)
4218c9fbc29Smrg	fprintf(file,"\n");
4228c9fbc29Smrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
4238c9fbc29Smrg	Bool	simple;
4248c9fbc29Smrg	if ((int)XkbKeyNumSyms(xkb,i)<1)
4258c9fbc29Smrg	    continue;
4268c9fbc29Smrg	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
4278c9fbc29Smrg	    continue;
4288c9fbc29Smrg	simple= True;
4298c9fbc29Smrg	fprintf(file,"    key %6s {",
4308c9fbc29Smrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
4318c9fbc29Smrg	if (srv->explicit) {
4328c9fbc29Smrg	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
4338c9fbc29Smrg	   						(showImplicit)) {
4348c9fbc29Smrg		int 	typeNdx,g;
4358c9fbc29Smrg		Bool	multi;
4364cd6a3aeSmrg		const char *	comment="  ";
4378c9fbc29Smrg
4388c9fbc29Smrg		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
4398c9fbc29Smrg		    comment= "//";
4408c9fbc29Smrg		multi= False;
4418c9fbc29Smrg		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
4428c9fbc29Smrg		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
4438c9fbc29Smrg		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
4448c9fbc29Smrg			multi= True;
4458c9fbc29Smrg		}
4468c9fbc29Smrg		if (multi) {
4478c9fbc29Smrg		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
4488c9fbc29Smrg			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
4498c9fbc29Smrg			if (srv->explicit[i]&(1<<g)) {
4508c9fbc29Smrg			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
4518c9fbc29Smrg			    	comment,g+1,
4528c9fbc29Smrg				XkbAtomText(dpy,map->types[typeNdx].name,
4538c9fbc29Smrg			    	XkbXKBFile));
4548c9fbc29Smrg			}
4558c9fbc29Smrg			else if (showImplicit) {
4568c9fbc29Smrg			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
4578c9fbc29Smrg				XkbAtomText(dpy,map->types[typeNdx].name,
4588c9fbc29Smrg			    	XkbXKBFile));
4598c9fbc29Smrg			}
4608c9fbc29Smrg		    }
4618c9fbc29Smrg		}
4628c9fbc29Smrg		else {
4638c9fbc29Smrg		    fprintf(file,"\n%s      type= \"%s\",",comment,
4648c9fbc29Smrg				XkbAtomText(dpy,map->types[typeNdx].name,
4658c9fbc29Smrg			    	XkbXKBFile));
4668c9fbc29Smrg		}
4678c9fbc29Smrg		simple= False;
4688c9fbc29Smrg	    }
4698c9fbc29Smrg	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
4708c9fbc29Smrg		    					  (xkb->ctrls!=NULL)) {
4718c9fbc29Smrg		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
4728c9fbc29Smrg		     fprintf(file,"\n        repeat= Yes,");
4738c9fbc29Smrg		else fprintf(file,"\n        repeat= No,");
4748c9fbc29Smrg		simple= False;
4758c9fbc29Smrg	    }
4768c9fbc29Smrg	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
4778c9fbc29Smrg					(xkb->server->vmodmap[i]!=0)) {
4788c9fbc29Smrg		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
4798c9fbc29Smrg		    fprintf(file,"\n        virtualMods= %s,",
4808c9fbc29Smrg				XkbVModMaskText(dpy,xkb,0,
4818c9fbc29Smrg						xkb->server->vmodmap[i],
4828c9fbc29Smrg						XkbXKBFile));
4838c9fbc29Smrg		}
4848c9fbc29Smrg		else if (showImplicit) {
4858c9fbc29Smrg		    fprintf(file,"\n//      virtualMods= %s,",
4868c9fbc29Smrg				XkbVModMaskText(dpy,xkb,0,
4878c9fbc29Smrg						xkb->server->vmodmap[i],
4888c9fbc29Smrg						XkbXKBFile));
4898c9fbc29Smrg		}
4908c9fbc29Smrg	    }
4918c9fbc29Smrg	}
4928c9fbc29Smrg	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
4938c9fbc29Smrg	    case XkbClampIntoRange:
4948c9fbc29Smrg		fprintf(file,"\n        groupsClamp,");
4958c9fbc29Smrg		break;
4968c9fbc29Smrg	    case XkbRedirectIntoRange:
4978c9fbc29Smrg		fprintf(file,"\n        groupsRedirect= Group%d,",
4988c9fbc29Smrg			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
4998c9fbc29Smrg		break;
5008c9fbc29Smrg	}
5018c9fbc29Smrg	if (srv->behaviors!=NULL) {
5028c9fbc29Smrg	    unsigned type;
5038c9fbc29Smrg	    type= srv->behaviors[i].type&XkbKB_OpMask;
5048c9fbc29Smrg
5058c9fbc29Smrg	    if (type!=XkbKB_Default) {
5068c9fbc29Smrg		simple= False;
5078c9fbc29Smrg		fprintf(file,"\n        %s,",
5088c9fbc29Smrg			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
5098c9fbc29Smrg	    }
5108c9fbc29Smrg	}
5118c9fbc29Smrg	if ((srv->explicit==NULL) || showImplicit ||
5128c9fbc29Smrg	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
5138c9fbc29Smrg	     showActions= XkbKeyHasActions(xkb,i);
5148c9fbc29Smrg	else showActions= False;
5154cd6a3aeSmrg
5168c9fbc29Smrg	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
5178c9fbc29Smrg	    simple= False;
5188c9fbc29Smrg	if (simple) {
5198c9fbc29Smrg	    KeySym *syms;
5208c9fbc29Smrg	    unsigned s;
5218c9fbc29Smrg
5228c9fbc29Smrg	    syms= XkbKeySymsPtr(xkb,i);
5238c9fbc29Smrg	    fprintf(file,"         [ ");
5248c9fbc29Smrg	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
5258c9fbc29Smrg		if (s!=0)
5268c9fbc29Smrg		    fprintf(file,", ");
5278c9fbc29Smrg		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
5288c9fbc29Smrg	    }
5298c9fbc29Smrg	    fprintf(file," ] };\n");
5308c9fbc29Smrg	}
5318c9fbc29Smrg	else {
5328c9fbc29Smrg	    unsigned g,s;
5338c9fbc29Smrg	    KeySym *syms;
5348c9fbc29Smrg	    XkbAction *acts;
5358c9fbc29Smrg	    syms= XkbKeySymsPtr(xkb,i);
5368c9fbc29Smrg	    acts= XkbKeyActionsPtr(xkb,i);
5378c9fbc29Smrg	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
5388c9fbc29Smrg		if (g!=0)
5398c9fbc29Smrg		    fprintf(file,",");
5408c9fbc29Smrg		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
5418c9fbc29Smrg		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
5428c9fbc29Smrg		    if (s!=0)
5438c9fbc29Smrg			fprintf(file,", ");
5448c9fbc29Smrg		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
5458c9fbc29Smrg		}
5468c9fbc29Smrg		fprintf(file," ]");
5478c9fbc29Smrg		syms+= XkbKeyGroupsWidth(xkb,i);
5488c9fbc29Smrg		if (showActions) {
5498c9fbc29Smrg		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
5508c9fbc29Smrg		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
5518c9fbc29Smrg			if (s!=0)
5528c9fbc29Smrg			    fprintf(file,", ");
5538c9fbc29Smrg			WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]);
5548c9fbc29Smrg		    }
5558c9fbc29Smrg		    fprintf(file," ]");
5568c9fbc29Smrg		    acts+= XkbKeyGroupsWidth(xkb,i);
5578c9fbc29Smrg		}
5588c9fbc29Smrg	    }
5598c9fbc29Smrg	    fprintf(file,"\n    };\n");
5608c9fbc29Smrg	}
5618c9fbc29Smrg    }
5628c9fbc29Smrg    if (map && map->modmap) {
5638c9fbc29Smrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5648c9fbc29Smrg	    if (map->modmap[i]!=0) {
5658c9fbc29Smrg		register int n,bit;
5668c9fbc29Smrg		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
5678c9fbc29Smrg		    if (map->modmap[i]&bit) {
5688c9fbc29Smrg			char buf[5];
5698c9fbc29Smrg			memcpy(buf,xkb->names->keys[i].name,4);
5708c9fbc29Smrg			buf[4]= '\0';
5718c9fbc29Smrg			fprintf(file,"    modifier_map %s { <%s> };\n",
5728c9fbc29Smrg					XkbModIndexText(n,XkbXKBFile),buf);
5738c9fbc29Smrg		    }
5748c9fbc29Smrg		}
5758c9fbc29Smrg	    }
5768c9fbc29Smrg	}
5778c9fbc29Smrg    }
5788c9fbc29Smrg    if (addOn)
5798c9fbc29Smrg	(*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv);
5808c9fbc29Smrg    fprintf(file,"};\n\n");
5818c9fbc29Smrg    return True;
5828c9fbc29Smrg}
5838c9fbc29Smrg
5848c9fbc29Smrgstatic Bool
5858c9fbc29SmrgWriteXKBOutline(	FILE *		file,
5868c9fbc29Smrg			XkbShapePtr	shape,
5878c9fbc29Smrg			XkbOutlinePtr	outline,
5888c9fbc29Smrg			int		lastRadius,
5898c9fbc29Smrg			int		first,
5908c9fbc29Smrg			int		indent)
5918c9fbc29Smrg{
5928c9fbc29Smrgregister int	i;
5938c9fbc29SmrgXkbPointPtr	pt;
5948c9fbc29Smrgchar *		iStr;
5958c9fbc29Smrg
5968c9fbc29Smrg    fprintf(file,"%s",iStr= XkbIndentText(first));
5978c9fbc29Smrg    if (first!=indent)
5988c9fbc29Smrg	iStr= XkbIndentText(indent);
5998c9fbc29Smrg    if (outline->corner_radius!=lastRadius) {
6008c9fbc29Smrg	fprintf(file,"corner= %s,",
6018c9fbc29Smrg			XkbGeomFPText(outline->corner_radius,XkbMessage));
6028c9fbc29Smrg	if (shape!=NULL) {
6038c9fbc29Smrg	    fprintf(file,"\n%s",iStr);
6048c9fbc29Smrg	}
6058c9fbc29Smrg    }
6068c9fbc29Smrg    if (shape) {
6078c9fbc29Smrg	if (outline==shape->approx)
6088c9fbc29Smrg	    fprintf(file,"approx= ");
6098c9fbc29Smrg	else if (outline==shape->primary)
6108c9fbc29Smrg	    fprintf(file,"primary= ");
6118c9fbc29Smrg    }
6128c9fbc29Smrg    fprintf(file,"{");
6138c9fbc29Smrg    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
6148c9fbc29Smrg	if (i==0)		fprintf(file," ");
6158c9fbc29Smrg	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
6168c9fbc29Smrg	else			fprintf(file,", ");
6178c9fbc29Smrg	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
6188c9fbc29Smrg				  XkbGeomFPText(pt->y,XkbXKBFile));
6198c9fbc29Smrg    }
6208c9fbc29Smrg    fprintf(file," }");
6218c9fbc29Smrg    return True;
6228c9fbc29Smrg}
6238c9fbc29Smrg
6248c9fbc29Smrgstatic Bool
6258c9fbc29SmrgWriteXKBDoodad(	FILE *		file,
6268c9fbc29Smrg		Display *	dpy,
6278c9fbc29Smrg		unsigned	indent,
6288c9fbc29Smrg		XkbGeometryPtr	geom,
6298c9fbc29Smrg		XkbDoodadPtr	doodad)
6308c9fbc29Smrg{
6318c9fbc29Smrgregister char *	i_str;
6328c9fbc29SmrgXkbShapePtr	shape;
6338c9fbc29SmrgXkbColorPtr	color;
6348c9fbc29Smrg
6358c9fbc29Smrg    i_str= XkbIndentText(indent);
6368c9fbc29Smrg    fprintf(file,"%s%s \"%s\" {\n",i_str,
6378c9fbc29Smrg				XkbDoodadTypeText(doodad->any.type,XkbMessage),
6388c9fbc29Smrg				XkbAtomText(dpy,doodad->any.name,XkbMessage));
6398c9fbc29Smrg    fprintf(file,"%s    top=      %s;\n",i_str,
6408c9fbc29Smrg				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
6418c9fbc29Smrg    fprintf(file,"%s    left=     %s;\n",i_str,
6428c9fbc29Smrg				XkbGeomFPText(doodad->any.left,XkbXKBFile));
6438c9fbc29Smrg    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
6448c9fbc29Smrg    switch (doodad->any.type) {
6458c9fbc29Smrg	case XkbOutlineDoodad:
6468c9fbc29Smrg	case XkbSolidDoodad:
6478c9fbc29Smrg	    if (doodad->shape.angle!=0) {
6488c9fbc29Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
6498c9fbc29Smrg			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
6508c9fbc29Smrg	    }
6518c9fbc29Smrg	    if (doodad->shape.color_ndx!=0) {
6528c9fbc29Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
6538c9fbc29Smrg			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
6548c9fbc29Smrg	    }
6558c9fbc29Smrg	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
6568c9fbc29Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6578c9fbc29Smrg			    XkbAtomText(dpy,shape->name,XkbXKBFile));
6588c9fbc29Smrg	    break;
6598c9fbc29Smrg	case XkbTextDoodad:
6608c9fbc29Smrg	    if (doodad->text.angle!=0) {
6618c9fbc29Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
6628c9fbc29Smrg			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
6638c9fbc29Smrg	    }
6648c9fbc29Smrg	    if (doodad->text.width!=0) {
6658c9fbc29Smrg		fprintf(file,"%s    width=  %s;\n",i_str,
6668c9fbc29Smrg			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
6678c9fbc29Smrg
6688c9fbc29Smrg	    }
6698c9fbc29Smrg	    if (doodad->text.height!=0) {
6708c9fbc29Smrg		fprintf(file,"%s    height=  %s;\n",i_str,
6718c9fbc29Smrg			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
6728c9fbc29Smrg
6738c9fbc29Smrg	    }
6748c9fbc29Smrg	    if (doodad->text.color_ndx!=0) {
6758c9fbc29Smrg		color= XkbTextDoodadColor(geom,&doodad->text);
6768c9fbc29Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
6778c9fbc29Smrg			     XkbStringText(color->spec,XkbXKBFile));
6788c9fbc29Smrg	    }
6798c9fbc29Smrg	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
6808c9fbc29Smrg	    		     XkbStringText(doodad->text.font,XkbXKBFile));
6818c9fbc29Smrg	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
6828c9fbc29Smrg	    		    XkbStringText(doodad->text.text,XkbXKBFile));
6838c9fbc29Smrg	    break;
6848c9fbc29Smrg	case XkbIndicatorDoodad:
6858c9fbc29Smrg	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
6868c9fbc29Smrg	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
6878c9fbc29Smrg	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
6888c9fbc29Smrg	    		    XkbStringText(color->spec,XkbXKBFile));
6898c9fbc29Smrg	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
6908c9fbc29Smrg	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
6918c9fbc29Smrg	    		    XkbStringText(color->spec,XkbXKBFile));
6928c9fbc29Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6938c9fbc29Smrg			     XkbAtomText(dpy,shape->name,XkbXKBFile));
6948c9fbc29Smrg	    break;
6958c9fbc29Smrg	case XkbLogoDoodad:
6968c9fbc29Smrg	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
6978c9fbc29Smrg			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
6988c9fbc29Smrg	    if (doodad->shape.angle!=0) {
6998c9fbc29Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
7008c9fbc29Smrg			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
7018c9fbc29Smrg	    }
7028c9fbc29Smrg	    if (doodad->shape.color_ndx!=0) {
7038c9fbc29Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
7048c9fbc29Smrg			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
7058c9fbc29Smrg	    }
7068c9fbc29Smrg	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
7078c9fbc29Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
7088c9fbc29Smrg			    XkbAtomText(dpy,shape->name,XkbXKBFile));
7098c9fbc29Smrg	    break;
7108c9fbc29Smrg    }
7118c9fbc29Smrg    fprintf(file,"%s};\n",i_str);
7128c9fbc29Smrg    return True;
7138c9fbc29Smrg}
7148c9fbc29Smrg
7158c9fbc29Smrg/*ARGSUSED*/
7168c9fbc29Smrgstatic Bool
7178c9fbc29SmrgWriteXKBOverlay(	FILE *		file,
7188c9fbc29Smrg			Display *	dpy,
7198c9fbc29Smrg			unsigned	indent,
7208c9fbc29Smrg			XkbGeometryPtr	geom,
7218c9fbc29Smrg			XkbOverlayPtr	ol)
7228c9fbc29Smrg{
7238c9fbc29Smrgregister char *		i_str;
7248c9fbc29Smrgint			r,k,nOut;
7258c9fbc29SmrgXkbOverlayRowPtr	row;
7268c9fbc29SmrgXkbOverlayKeyPtr	key;
7278c9fbc29Smrg
7288c9fbc29Smrg    i_str= XkbIndentText(indent);
7298c9fbc29Smrg    if (ol->name!=None) {
7308c9fbc29Smrg	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
7318c9fbc29Smrg    					XkbAtomText(dpy,ol->name,XkbMessage));
7328c9fbc29Smrg    }
7338c9fbc29Smrg    else fprintf(file,"%soverlay {\n",i_str);
7348c9fbc29Smrg    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
7358c9fbc29Smrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
7368c9fbc29Smrg	    char *over,*under;
7378c9fbc29Smrg	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
7388c9fbc29Smrg	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
7398c9fbc29Smrg	    if (nOut==0)
7408c9fbc29Smrg		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
7418c9fbc29Smrg	    else if ((nOut%4)==0)
7428c9fbc29Smrg		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
7438c9fbc29Smrg	    else fprintf(file,", %6s=%6s",under,over);
7448c9fbc29Smrg	    nOut++;
7458c9fbc29Smrg	}
7468c9fbc29Smrg    }
7478c9fbc29Smrg    fprintf(file,"\n%s};\n",i_str);
7488c9fbc29Smrg    return True;
7498c9fbc29Smrg}
7508c9fbc29Smrg
7518c9fbc29Smrgstatic Bool
7528c9fbc29SmrgWriteXKBSection(	FILE *		file,
7538c9fbc29Smrg			Display *	dpy,
7548c9fbc29Smrg			XkbSectionPtr 	s,
7558c9fbc29Smrg			XkbGeometryPtr	geom)
7568c9fbc29Smrg{
7578c9fbc29Smrgregister int	i;
7588c9fbc29SmrgXkbRowPtr	row;
7598c9fbc29Smrgint		dfltKeyColor = 0;
7608c9fbc29Smrg
7618c9fbc29Smrg    fprintf(file,"    section \"%s\" {\n",
7628c9fbc29Smrg				XkbAtomText(dpy,s->name,XkbXKBFile));
7638c9fbc29Smrg    if (s->rows&&(s->rows->num_keys>0)) {
7648c9fbc29Smrg	dfltKeyColor= s->rows->keys[0].color_ndx;
7658c9fbc29Smrg	fprintf(file,"        key.color= \"%s\";\n",
7668c9fbc29Smrg		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
7678c9fbc29Smrg    }
7688c9fbc29Smrg    fprintf(file,"        priority=  %d;\n",s->priority);
7698c9fbc29Smrg    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
7708c9fbc29Smrg    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
7718c9fbc29Smrg    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
7728c9fbc29Smrg    fprintf(file,"        height=    %s;\n",
7738c9fbc29Smrg					XkbGeomFPText(s->height,XkbXKBFile));
7748c9fbc29Smrg    if (s->angle!=0) {
7758c9fbc29Smrg	fprintf(file,"        angle=  %s;\n",
7768c9fbc29Smrg					XkbGeomFPText(s->angle,XkbXKBFile));
7778c9fbc29Smrg    }
7788c9fbc29Smrg    for (i=0,row=s->rows;row&&i<s->num_rows;i++,row++) {
7798c9fbc29Smrg	fprintf(file,"        row {\n");
7808c9fbc29Smrg	fprintf(file,"            top=  %s;\n",
7818c9fbc29Smrg					XkbGeomFPText(row->top,XkbXKBFile));
7828c9fbc29Smrg	fprintf(file,"            left= %s;\n",
7838c9fbc29Smrg					XkbGeomFPText(row->left,XkbXKBFile));
7848c9fbc29Smrg	if (row->vertical)
7858c9fbc29Smrg	    fprintf(file,"            vertical;\n");
7868c9fbc29Smrg	if (row->num_keys>0) {
7878c9fbc29Smrg	    register int 	k;
7888c9fbc29Smrg	    register XkbKeyPtr	key;
7898c9fbc29Smrg	    int			forceNL=0;
7908c9fbc29Smrg	    int			nThisLine= 0;
7918c9fbc29Smrg	    fprintf(file,"            keys {\n");
7928c9fbc29Smrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
7938c9fbc29Smrg		XkbShapePtr	shape;
7948c9fbc29Smrg		if (key->color_ndx!=dfltKeyColor)
7958c9fbc29Smrg		    forceNL= 1;
7968c9fbc29Smrg		if (k==0) {
7978c9fbc29Smrg		     fprintf(file,"                ");
7988c9fbc29Smrg		     nThisLine= 0;
7998c9fbc29Smrg		}
8008c9fbc29Smrg		else if (((nThisLine%2)==1)||(forceNL)) {
8018c9fbc29Smrg		     fprintf(file,",\n                ");
8028c9fbc29Smrg		     forceNL= nThisLine= 0;
8038c9fbc29Smrg		}
8048c9fbc29Smrg		else {
8058c9fbc29Smrg		     fprintf(file,", ");
8068c9fbc29Smrg		     nThisLine++;
8078c9fbc29Smrg		}
8088c9fbc29Smrg		shape= XkbKeyShape(geom,key);
8098c9fbc29Smrg		fprintf(file,"{ %6s, \"%s\", %3s",
8108c9fbc29Smrg		      XkbKeyNameText(key->name.name,XkbXKBFile),
8118c9fbc29Smrg		      XkbAtomText(dpy,shape->name,XkbXKBFile),
8128c9fbc29Smrg		      XkbGeomFPText(key->gap,XkbXKBFile));
8138c9fbc29Smrg		if (key->color_ndx!=dfltKeyColor) {
8148c9fbc29Smrg		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
8158c9fbc29Smrg		    forceNL= 1;
8168c9fbc29Smrg		}
8178c9fbc29Smrg		fprintf(file," }");
8188c9fbc29Smrg	    }
8198c9fbc29Smrg	    fprintf(file,"\n            };\n");
8208c9fbc29Smrg	}
8218c9fbc29Smrg	fprintf(file,"        };\n");
8228c9fbc29Smrg    }
8238c9fbc29Smrg    if (s->doodads!=NULL) {
8248c9fbc29Smrg	XkbDoodadPtr	doodad;
8258c9fbc29Smrg	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
8268c9fbc29Smrg	    WriteXKBDoodad(file,dpy,8,geom,doodad);
8278c9fbc29Smrg	}
8288c9fbc29Smrg    }
8298c9fbc29Smrg    if (s->overlays!=NULL) {
8308c9fbc29Smrg	XkbOverlayPtr	ol;
8318c9fbc29Smrg	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
8328c9fbc29Smrg	    WriteXKBOverlay(file,dpy,8,geom,ol);
8338c9fbc29Smrg	}
8348c9fbc29Smrg    }
8358c9fbc29Smrg    fprintf(file,"    }; // End of \"%s\" section\n\n",
8368c9fbc29Smrg				XkbAtomText(dpy,s->name,XkbXKBFile));
8378c9fbc29Smrg    return True;
8388c9fbc29Smrg}
8398c9fbc29Smrg
8408c9fbc29SmrgBool
8418c9fbc29SmrgXkbWriteXKBGeometry(	FILE *			file,
8428c9fbc29Smrg			XkbFileInfo *		result,
8438c9fbc29Smrg			Bool			topLevel,
8448c9fbc29Smrg			Bool			showImplicit,
8458c9fbc29Smrg			XkbFileAddOnFunc	addOn,
8468c9fbc29Smrg			void *			priv)
8478c9fbc29Smrg{
8488c9fbc29SmrgDisplay *		dpy;
8498c9fbc29Smrgregister unsigned	i,n;
8508c9fbc29SmrgXkbDescPtr		xkb;
8518c9fbc29SmrgXkbGeometryPtr		geom;
8528c9fbc29Smrg
8538c9fbc29Smrg    xkb= result->xkb;
8548c9fbc29Smrg    if ((!xkb)||(!xkb->geom)) {
8558c9fbc29Smrg	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
8568c9fbc29Smrg 	return False;
8578c9fbc29Smrg    }
8588c9fbc29Smrg    dpy= xkb->dpy;
8598c9fbc29Smrg    geom= xkb->geom;
8608c9fbc29Smrg    if (geom->name==None)
8618c9fbc29Smrg	 fprintf(file,"xkb_geometry {\n\n");
8628c9fbc29Smrg    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
8638c9fbc29Smrg				XkbAtomText(dpy,geom->name,XkbXKBFile));
8648c9fbc29Smrg    fprintf(file,"    width=       %s;\n",
8658c9fbc29Smrg				XkbGeomFPText(geom->width_mm,XkbXKBFile));
8668c9fbc29Smrg    fprintf(file,"    height=      %s;\n\n",
8678c9fbc29Smrg				XkbGeomFPText(geom->height_mm,XkbXKBFile));
8688c9fbc29Smrg
8698c9fbc29Smrg    if (geom->key_aliases!=NULL) {
8708c9fbc29Smrg	XkbKeyAliasPtr	pAl;
8718c9fbc29Smrg	pAl= geom->key_aliases;
8728c9fbc29Smrg	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
8738c9fbc29Smrg	    fprintf(file,"    alias %6s = %6s;\n",
8748c9fbc29Smrg				XkbKeyNameText(pAl->alias,XkbXKBFile),
8758c9fbc29Smrg				XkbKeyNameText(pAl->real,XkbXKBFile));
8768c9fbc29Smrg	}
8778c9fbc29Smrg	fprintf(file,"\n");
8788c9fbc29Smrg    }
8798c9fbc29Smrg
8808c9fbc29Smrg    if (geom->base_color!=NULL)
8818c9fbc29Smrg	fprintf(file,"    baseColor=   \"%s\";\n",
8828c9fbc29Smrg			XkbStringText(geom->base_color->spec,XkbXKBFile));
8838c9fbc29Smrg    if (geom->label_color!=NULL)
8848c9fbc29Smrg	fprintf(file,"    labelColor=  \"%s\";\n",
8858c9fbc29Smrg			XkbStringText(geom->label_color->spec,XkbXKBFile));
8868c9fbc29Smrg    if (geom->label_font!=NULL)
8878c9fbc29Smrg	fprintf(file,"    xfont=       \"%s\";\n",
8888c9fbc29Smrg			XkbStringText(geom->label_font,XkbXKBFile));
8898c9fbc29Smrg    if ((geom->num_colors>0)&&(showImplicit)) {
8908c9fbc29Smrg	XkbColorPtr	color;
8918c9fbc29Smrg	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
8928c9fbc29Smrg		fprintf(file,"//     color[%d]= \"%s\"\n",i,
8938c9fbc29Smrg				XkbStringText(color->spec,XkbXKBFile));
8948c9fbc29Smrg	}
8958c9fbc29Smrg	fprintf(file,"\n");
8968c9fbc29Smrg    }
8978c9fbc29Smrg    if (geom->num_properties>0) {
8988c9fbc29Smrg	XkbPropertyPtr	prop;
8998c9fbc29Smrg	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
9008c9fbc29Smrg	    fprintf(file,"    %s= \"%s\";\n",prop->name,
9018c9fbc29Smrg    				XkbStringText(prop->value,XkbXKBFile));
9028c9fbc29Smrg	}
9038c9fbc29Smrg	fprintf(file,"\n");
9048c9fbc29Smrg    }
9058c9fbc29Smrg    if (geom->num_shapes>0) {
9068c9fbc29Smrg	XkbShapePtr	shape;
9078c9fbc29Smrg	XkbOutlinePtr	outline;
9088c9fbc29Smrg	int		lastR;
9098c9fbc29Smrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
9108c9fbc29Smrg	    lastR=0;
9118c9fbc29Smrg	    fprintf(file,"    shape \"%s\" {",
9128c9fbc29Smrg				   XkbAtomText(dpy,shape->name,XkbXKBFile));
9138c9fbc29Smrg	    outline= shape->outlines;
9148c9fbc29Smrg	    if (shape->num_outlines>1) {
9158c9fbc29Smrg		for (n=0;n<shape->num_outlines;n++,outline++) {
9168c9fbc29Smrg		    if (n==0)	fprintf(file,"\n");
9178c9fbc29Smrg		    else	fprintf(file,",\n");
9188c9fbc29Smrg		    WriteXKBOutline(file,shape,outline,lastR,8,8);
9198c9fbc29Smrg		    lastR= outline->corner_radius;
9208c9fbc29Smrg		}
9218c9fbc29Smrg		fprintf(file,"\n    };\n");
9228c9fbc29Smrg	    }
9238c9fbc29Smrg	    else {
9248c9fbc29Smrg		WriteXKBOutline(file,NULL,outline,lastR,1,8);
9258c9fbc29Smrg		fprintf(file," };\n");
9268c9fbc29Smrg	    }
9278c9fbc29Smrg	}
9288c9fbc29Smrg    }
9298c9fbc29Smrg    if (geom->num_sections>0) {
9308c9fbc29Smrg	XkbSectionPtr	section;
9318c9fbc29Smrg	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
9328c9fbc29Smrg	    WriteXKBSection(file,dpy,section,geom);
9338c9fbc29Smrg	}
9348c9fbc29Smrg    }
9358c9fbc29Smrg    if (geom->num_doodads>0) {
9368c9fbc29Smrg	XkbDoodadPtr	doodad;
9378c9fbc29Smrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
9388c9fbc29Smrg	    WriteXKBDoodad(file,dpy,4,geom,doodad);
9398c9fbc29Smrg	}
9408c9fbc29Smrg    }
9418c9fbc29Smrg    if (addOn)
9428c9fbc29Smrg	(*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv);
9438c9fbc29Smrg    fprintf(file,"};\n\n");
9448c9fbc29Smrg    return True;
9458c9fbc29Smrg}
9468c9fbc29Smrg
9478c9fbc29Smrg/*ARGSUSED*/
9488c9fbc29SmrgBool
9498c9fbc29SmrgXkbWriteXKBSemantics(	FILE *			file,
9508c9fbc29Smrg			XkbFileInfo *		result,
9518c9fbc29Smrg			Bool			topLevel,
9528c9fbc29Smrg			Bool			showImplicit,
9538c9fbc29Smrg			XkbFileAddOnFunc	addOn,
9548c9fbc29Smrg			void *			priv)
9558c9fbc29Smrg{
9568c9fbc29SmrgBool		ok;
9578c9fbc29Smrg
9588c9fbc29Smrg    fprintf(file,"xkb_semantics {\n");
9598c9fbc29Smrg    ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv);
9608c9fbc29Smrg    ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv);
9618c9fbc29Smrg    fprintf(file,"};\n");
9628c9fbc29Smrg    return ok;
9638c9fbc29Smrg}
9648c9fbc29Smrg
9658c9fbc29Smrg/*ARGSUSED*/
9668c9fbc29SmrgBool
9678c9fbc29SmrgXkbWriteXKBLayout(	FILE *			file,
9688c9fbc29Smrg			XkbFileInfo *		result,
9698c9fbc29Smrg			Bool			topLevel,
9708c9fbc29Smrg			Bool			showImplicit,
9718c9fbc29Smrg			XkbFileAddOnFunc	addOn,
9728c9fbc29Smrg			void *			priv)
9738c9fbc29Smrg{
9748c9fbc29SmrgBool		ok;
9758c9fbc29SmrgXkbDescPtr	xkb;
9768c9fbc29Smrg
9778c9fbc29Smrg    xkb= result->xkb;
9788c9fbc29Smrg    fprintf(file,"xkb_layout {\n");
9798c9fbc29Smrg    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
9808c9fbc29Smrg    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
9818c9fbc29Smrg    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
9828c9fbc29Smrg    if (xkb->geom)
9838c9fbc29Smrg	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
9848c9fbc29Smrg    fprintf(file,"};\n");
9858c9fbc29Smrg    return ok;
9868c9fbc29Smrg}
9878c9fbc29Smrg
9888c9fbc29Smrg/*ARGSUSED*/
9898c9fbc29SmrgBool
9908c9fbc29SmrgXkbWriteXKBKeymap(	FILE *			file,
9918c9fbc29Smrg			XkbFileInfo *		result,
9928c9fbc29Smrg			Bool			topLevel,
9938c9fbc29Smrg			Bool			showImplicit,
9948c9fbc29Smrg			XkbFileAddOnFunc	addOn,
9958c9fbc29Smrg			void *			priv)
9968c9fbc29Smrg{
9978c9fbc29SmrgBool		ok;
9988c9fbc29SmrgXkbDescPtr	xkb;
9998c9fbc29Smrg
10008c9fbc29Smrg    xkb= result->xkb;
10018c9fbc29Smrg    fprintf(file,"xkb_keymap {\n");
10028c9fbc29Smrg    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
10038c9fbc29Smrg    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
10048c9fbc29Smrg    ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv);
10058c9fbc29Smrg    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
10068c9fbc29Smrg    if (xkb->geom)
10078c9fbc29Smrg	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
10088c9fbc29Smrg    fprintf(file,"};\n");
10098c9fbc29Smrg    return ok;
10108c9fbc29Smrg}
10118c9fbc29Smrg
10128c9fbc29SmrgBool
10138c9fbc29SmrgXkbWriteXKBFile(	FILE *			out,
10148c9fbc29Smrg			XkbFileInfo *		result,
10158c9fbc29Smrg			Bool			showImplicit,
10168c9fbc29Smrg			XkbFileAddOnFunc	addOn,
10178c9fbc29Smrg			void *			priv)
10188c9fbc29Smrg{
10198c9fbc29SmrgBool	 		ok = False;
10208c9fbc29SmrgBool			(*func)(
10218c9fbc29Smrg    FILE *		/* file */,
10228c9fbc29Smrg    XkbFileInfo *	/* result */,
10238c9fbc29Smrg    Bool		/* topLevel */,
10248c9fbc29Smrg    Bool		/* showImplicit */,
10258c9fbc29Smrg    XkbFileAddOnFunc	/* addOn */,
10268c9fbc29Smrg    void *		/* priv */
10278c9fbc29Smrg) = NULL;
10288c9fbc29Smrg
10298c9fbc29Smrg    switch (result->type) {
10308c9fbc29Smrg	case XkmSemanticsFile:
10318c9fbc29Smrg	    func= XkbWriteXKBSemantics;
10328c9fbc29Smrg	    break;
10338c9fbc29Smrg	case XkmLayoutFile:
10348c9fbc29Smrg	    func= XkbWriteXKBLayout;
10358c9fbc29Smrg	    break;
10368c9fbc29Smrg	case XkmKeymapFile:
10378c9fbc29Smrg	    func= XkbWriteXKBKeymap;
10388c9fbc29Smrg	    break;
10398c9fbc29Smrg	case XkmTypesIndex:
10408c9fbc29Smrg	    func= XkbWriteXKBKeyTypes;
10418c9fbc29Smrg	    break;
10428c9fbc29Smrg	case XkmCompatMapIndex:
10438c9fbc29Smrg	    func= XkbWriteXKBCompatMap;
10448c9fbc29Smrg	    break;
10458c9fbc29Smrg	case XkmSymbolsIndex:
10468c9fbc29Smrg	    func= XkbWriteXKBSymbols;
10478c9fbc29Smrg	    break;
10488c9fbc29Smrg	case XkmKeyNamesIndex:
10498c9fbc29Smrg	    func= XkbWriteXKBKeycodes;
10508c9fbc29Smrg	    break;
10518c9fbc29Smrg	case XkmGeometryFile:
10528c9fbc29Smrg	case XkmGeometryIndex:
10538c9fbc29Smrg	    func= XkbWriteXKBGeometry;
10548c9fbc29Smrg	    break;
10558c9fbc29Smrg	case XkmVirtualModsIndex:
10568c9fbc29Smrg	case XkmIndicatorsIndex:
10578c9fbc29Smrg	    _XkbLibError(_XkbErrBadImplementation,
10588c9fbc29Smrg	    		XkbConfigText(result->type,XkbMessage),0);
10598c9fbc29Smrg	    return False;
10608c9fbc29Smrg    }
10618c9fbc29Smrg    if (out==NULL) {
10628c9fbc29Smrg	_XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0);
10638c9fbc29Smrg	ok= False;
10648c9fbc29Smrg    }
10658c9fbc29Smrg    else if (func) {
10668c9fbc29Smrg	ok= (*func)(out,result,True,showImplicit,addOn,priv);
10678c9fbc29Smrg    }
10688c9fbc29Smrg    return ok;
10698c9fbc29Smrg}
1070