xkbout.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrg Permission to use, copy, modify, and distribute this
505b261ecSmrg software and its documentation for any purpose and without
605b261ecSmrg fee is hereby granted, provided that the above copyright
705b261ecSmrg notice appear in all copies and that both that copyright
805b261ecSmrg notice and this permission notice appear in supporting
905b261ecSmrg documentation, and that the name of Silicon Graphics not be
1005b261ecSmrg used in advertising or publicity pertaining to distribution
1105b261ecSmrg of the software without specific prior written permission.
1205b261ecSmrg Silicon Graphics makes no representation about the suitability
1305b261ecSmrg of this software for any purpose. It is provided "as is"
1405b261ecSmrg without any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg ********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <ctype.h>
3305b261ecSmrg#include <stdlib.h>
3405b261ecSmrg#include <X11/Xfuncs.h>
3505b261ecSmrg
3605b261ecSmrg#include <X11/X.h>
3705b261ecSmrg#define	NEED_EVENTS
3805b261ecSmrg#include <X11/keysym.h>
3905b261ecSmrg#include <X11/Xproto.h>
4005b261ecSmrg#include "misc.h"
4105b261ecSmrg#include "inputstr.h"
4205b261ecSmrg#include "dix.h"
4305b261ecSmrg#include <X11/extensions/XKBstr.h>
4405b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS	1
4505b261ecSmrg#include <xkbsrv.h>
4605b261ecSmrg
4705b261ecSmrg#include <X11/extensions/XKBgeom.h>
4805b261ecSmrg#include <X11/extensions/XKBfile.h>
4905b261ecSmrg
5005b261ecSmrg#define	VMOD_HIDE_VALUE	0
5105b261ecSmrg#define	VMOD_SHOW_VALUE	1
5205b261ecSmrg#define	VMOD_COMMENT_VALUE 2
5305b261ecSmrg
5405b261ecSmrgstatic Bool
5505b261ecSmrgWriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue)
5605b261ecSmrg{
5705b261ecSmrgregister int 	i,nMods;
5805b261ecSmrgAtom *		vmodNames;
5905b261ecSmrg
6005b261ecSmrg    if (xkb==NULL)
6105b261ecSmrg	return False;
6205b261ecSmrg    if (xkb->names!=NULL)
6305b261ecSmrg	 vmodNames= xkb->names->vmods;
6405b261ecSmrg    else vmodNames= NULL;
6505b261ecSmrg
6605b261ecSmrg    for (i=nMods=0;i<XkbNumVirtualMods;i++) {
6705b261ecSmrg	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
6805b261ecSmrg	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
6905b261ecSmrg	    else		fprintf(file,",");
7005b261ecSmrg	    fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile));
7105b261ecSmrg	    if ((showValue!=VMOD_HIDE_VALUE)&&
7205b261ecSmrg		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
7305b261ecSmrg		if (showValue==VMOD_COMMENT_VALUE) {
7405b261ecSmrg		    fprintf(file,"/* = %s */",
7505b261ecSmrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
7605b261ecSmrg		}
7705b261ecSmrg		else  {
7805b261ecSmrg		    fprintf(file,"= %s",
7905b261ecSmrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
8005b261ecSmrg		}
8105b261ecSmrg	    }
8205b261ecSmrg	    nMods++;
8305b261ecSmrg	}
8405b261ecSmrg    }
8505b261ecSmrg    if (nMods>0)
8605b261ecSmrg	fprintf(file,";\n\n");
8705b261ecSmrg    return True;
8805b261ecSmrg}
8905b261ecSmrg
9005b261ecSmrg/***====================================================================***/
9105b261ecSmrg
9205b261ecSmrgstatic Bool
9305b261ecSmrgWriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action)
9405b261ecSmrg{
9505b261ecSmrgXkbDescPtr	xkb;
9605b261ecSmrgDisplay *	dpy;
9705b261ecSmrg
9805b261ecSmrg    xkb= result->xkb;
9905b261ecSmrg    dpy= xkb->dpy;
10005b261ecSmrg    fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile));
10105b261ecSmrg    return True;
10205b261ecSmrg}
10305b261ecSmrg
10405b261ecSmrg/***====================================================================***/
10505b261ecSmrg
10605b261ecSmrgBool
10705b261ecSmrgXkbWriteXKBKeycodes(	FILE *			file,
10805b261ecSmrg			XkbFileInfo *		result,
10905b261ecSmrg			Bool			topLevel,
11005b261ecSmrg			Bool			showImplicit,
11105b261ecSmrg			XkbFileAddOnFunc	addOn,
11205b261ecSmrg			void *			priv)
11305b261ecSmrg{
11405b261ecSmrgAtom			kcName;
11505b261ecSmrgregister unsigned 	i;
11605b261ecSmrgXkbDescPtr		xkb;
11705b261ecSmrgDisplay *		dpy;
11805b261ecSmrgchar *			alternate;
11905b261ecSmrg
12005b261ecSmrg    xkb= result->xkb;
12105b261ecSmrg    dpy= xkb->dpy;
12205b261ecSmrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
12305b261ecSmrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
12405b261ecSmrg	return False;
12505b261ecSmrg    }
12605b261ecSmrg    kcName= xkb->names->keycodes;
12705b261ecSmrg    if (kcName!=None)
12805b261ecSmrg	 fprintf(file,"xkb_keycodes \"%s\" {\n",
12905b261ecSmrg					XkbAtomText(dpy,kcName,XkbXKBFile));
13005b261ecSmrg    else fprintf(file,"xkb_keycodes {\n");
13105b261ecSmrg    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
13205b261ecSmrg    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
13305b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
13405b261ecSmrg	if (xkb->names->keys[i].name[0]!='\0') {
13505b261ecSmrg	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
13605b261ecSmrg		 alternate= "alternate ";
13705b261ecSmrg	    else alternate= "";
13805b261ecSmrg	    fprintf(file,"    %s%6s = %d;\n",alternate,
13905b261ecSmrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
14005b261ecSmrg			i);
14105b261ecSmrg	}
14205b261ecSmrg    }
14305b261ecSmrg    if (xkb->indicators!=NULL) {
14405b261ecSmrg	for (i=0;i<XkbNumIndicators;i++) {
14505b261ecSmrg	    char *type;
14605b261ecSmrg	    if (xkb->indicators->phys_indicators&(1<<i))
14705b261ecSmrg			type= "    ";
14805b261ecSmrg	    else	type= "    virtual ";
14905b261ecSmrg	    if (xkb->names->indicators[i]!=None) {
15005b261ecSmrg		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
15105b261ecSmrg			XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile));
15205b261ecSmrg	    }
15305b261ecSmrg	}
15405b261ecSmrg    }
15505b261ecSmrg    if (xkb->names->key_aliases!=NULL) {
15605b261ecSmrg	XkbKeyAliasPtr	pAl;
15705b261ecSmrg	pAl= xkb->names->key_aliases;
15805b261ecSmrg	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
15905b261ecSmrg	    fprintf(file,"    alias %6s = %6s;\n",
16005b261ecSmrg			XkbKeyNameText(pAl->alias,XkbXKBFile),
16105b261ecSmrg			XkbKeyNameText(pAl->real,XkbXKBFile));
16205b261ecSmrg	}
16305b261ecSmrg    }
16405b261ecSmrg    if (addOn)
16505b261ecSmrg	(*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv);
16605b261ecSmrg    fprintf(file,"};\n\n");
16705b261ecSmrg    return True;
16805b261ecSmrg}
16905b261ecSmrg
17005b261ecSmrgBool
17105b261ecSmrgXkbWriteXKBKeyTypes(	FILE *			file,
17205b261ecSmrg			XkbFileInfo *		result,
17305b261ecSmrg			Bool			topLevel,
17405b261ecSmrg			Bool			showImplicit,
17505b261ecSmrg			XkbFileAddOnFunc	addOn,
17605b261ecSmrg			void *			priv)
17705b261ecSmrg{
17805b261ecSmrgDisplay *		dpy;
17905b261ecSmrgregister unsigned	i,n;
18005b261ecSmrgXkbKeyTypePtr		type;
18105b261ecSmrgXkbKTMapEntryPtr	entry;
18205b261ecSmrgXkbDescPtr		xkb;
18305b261ecSmrg
18405b261ecSmrg    xkb= result->xkb;
18505b261ecSmrg    dpy= xkb->dpy;
18605b261ecSmrg    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
18705b261ecSmrg	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
18805b261ecSmrg	return False;
18905b261ecSmrg    }
19005b261ecSmrg    if (xkb->map->num_types<XkbNumRequiredTypes) {
19105b261ecSmrg	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
19205b261ecSmrg	return 0;
19305b261ecSmrg    }
19405b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->types==None))
19505b261ecSmrg	 fprintf(file,"xkb_types {\n\n");
19605b261ecSmrg    else fprintf(file,"xkb_types \"%s\" {\n\n",
19705b261ecSmrg			XkbAtomText(dpy,xkb->names->types,XkbXKBFile));
19805b261ecSmrg    WriteXKBVModDecl(file,dpy,xkb,
19905b261ecSmrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
20005b261ecSmrg
20105b261ecSmrg    type= xkb->map->types;
20205b261ecSmrg    for (i=0;i<xkb->map->num_types;i++,type++) {
20305b261ecSmrg	fprintf(file,"    type \"%s\" {\n",
20405b261ecSmrg		XkbAtomText(dpy,type->name,XkbXKBFile));
20505b261ecSmrg	fprintf(file,"        modifiers= %s;\n",
20605b261ecSmrg	       XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods,
20705b261ecSmrg								XkbXKBFile));
20805b261ecSmrg	entry= type->map;
20905b261ecSmrg	for (n=0;n<type->map_count;n++,entry++) {
21005b261ecSmrg	    char *str;
21105b261ecSmrg	    str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods,
21205b261ecSmrg								XkbXKBFile);
21305b261ecSmrg	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
21405b261ecSmrg	    if ((type->preserve)&&((type->preserve[n].real_mods)||
21505b261ecSmrg				   (type->preserve[n].vmods))) {
21605b261ecSmrg		fprintf(file,"        preserve[%s]= ",str);
21705b261ecSmrg		fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb,
21805b261ecSmrg					type->preserve[n].real_mods,
21905b261ecSmrg					type->preserve[n].vmods,
22005b261ecSmrg					XkbXKBFile));
22105b261ecSmrg	    }
22205b261ecSmrg	}
22305b261ecSmrg	if (type->level_names!=NULL) {
22405b261ecSmrg	    Atom *name= type->level_names;
22505b261ecSmrg	    for (n=0;n<type->num_levels;n++,name++) {
22605b261ecSmrg		if ((*name)==None)
22705b261ecSmrg		    continue;
22805b261ecSmrg		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
22905b261ecSmrg					XkbAtomText(dpy,*name,XkbXKBFile));
23005b261ecSmrg	    }
23105b261ecSmrg	}
23205b261ecSmrg	fprintf(file,"    };\n");
23305b261ecSmrg    }
23405b261ecSmrg    if (addOn)
23505b261ecSmrg	(*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv);
23605b261ecSmrg    fprintf(file,"};\n\n");
23705b261ecSmrg    return True;
23805b261ecSmrg}
23905b261ecSmrg
24005b261ecSmrgstatic Bool
24105b261ecSmrgWriteXKBIndicatorMap(	FILE *			file,
24205b261ecSmrg			XkbFileInfo *		result,
24305b261ecSmrg			Atom			name,
24405b261ecSmrg			XkbIndicatorMapPtr	led,
24505b261ecSmrg			XkbFileAddOnFunc	addOn,
24605b261ecSmrg			void *			priv)
24705b261ecSmrg{
24805b261ecSmrgXkbDescPtr	xkb;
24905b261ecSmrg
25005b261ecSmrg    xkb= result->xkb;
25105b261ecSmrg    fprintf(file,"    indicator \"%s\" {\n",XkbAtomGetString(xkb->dpy,name));
25205b261ecSmrg    if (led->flags&XkbIM_NoExplicit)
25305b261ecSmrg	fprintf(file,"        !allowExplicit;\n");
25405b261ecSmrg    if (led->flags&XkbIM_LEDDrivesKB)
25505b261ecSmrg	fprintf(file,"        indicatorDrivesKeyboard;\n");
25605b261ecSmrg    if (led->which_groups!=0) {
25705b261ecSmrg	if (led->which_groups!=XkbIM_UseEffective) {
25805b261ecSmrg	    fprintf(file,"        whichGroupState= %s;\n",
25905b261ecSmrg			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
26005b261ecSmrg	}
26105b261ecSmrg	fprintf(file,"        groups= 0x%02x;\n",led->groups);
26205b261ecSmrg    }
26305b261ecSmrg    if (led->which_mods!=0) {
26405b261ecSmrg	if (led->which_mods!=XkbIM_UseEffective) {
26505b261ecSmrg	    fprintf(file,"        whichModState= %s;\n",
26605b261ecSmrg			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
26705b261ecSmrg	}
26805b261ecSmrg	fprintf(file,"        modifiers= %s;\n",
26905b261ecSmrg			XkbVModMaskText(xkb->dpy,xkb,
27005b261ecSmrg					led->mods.real_mods,led->mods.vmods,
27105b261ecSmrg					XkbXKBFile));
27205b261ecSmrg    }
27305b261ecSmrg    if (led->ctrls!=0) {
27405b261ecSmrg	fprintf(file,"        controls= %s;\n",
27505b261ecSmrg			XkbControlsMaskText(led->ctrls,XkbXKBFile));
27605b261ecSmrg    }
27705b261ecSmrg    if (addOn)
27805b261ecSmrg	(*addOn)(file,result,False,True,XkmIndicatorsIndex,priv);
27905b261ecSmrg    fprintf(file,"    };\n");
28005b261ecSmrg    return True;
28105b261ecSmrg}
28205b261ecSmrg
28305b261ecSmrgBool
28405b261ecSmrgXkbWriteXKBCompatMap(	FILE *			file,
28505b261ecSmrg			XkbFileInfo *		result,
28605b261ecSmrg			Bool			topLevel,
28705b261ecSmrg			Bool			showImplicit,
28805b261ecSmrg			XkbFileAddOnFunc	addOn,
28905b261ecSmrg			void *			priv)
29005b261ecSmrg{
29105b261ecSmrgDisplay *		dpy;
29205b261ecSmrgregister unsigned	i;
29305b261ecSmrgXkbSymInterpretPtr	interp;
29405b261ecSmrgXkbDescPtr		xkb;
29505b261ecSmrg
29605b261ecSmrg    xkb= result->xkb;
29705b261ecSmrg    dpy= xkb->dpy;
29805b261ecSmrg    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
29905b261ecSmrg	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
30005b261ecSmrg	return False;
30105b261ecSmrg    }
30205b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->compat==None))
30305b261ecSmrg	 fprintf(file,"xkb_compatibility {\n\n");
30405b261ecSmrg    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
30505b261ecSmrg			XkbAtomText(dpy,xkb->names->compat,XkbXKBFile));
30605b261ecSmrg    WriteXKBVModDecl(file,dpy,xkb,
30705b261ecSmrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
30805b261ecSmrg
30905b261ecSmrg    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
31005b261ecSmrg    fprintf(file,"    interpret.repeat= False;\n");
31105b261ecSmrg    fprintf(file,"    interpret.locking= False;\n");
31205b261ecSmrg    interp= xkb->compat->sym_interpret;
31305b261ecSmrg    for (i=0;i<xkb->compat->num_si;i++,interp++) {
31405b261ecSmrg	fprintf(file,"    interpret %s+%s(%s) {\n",
31505b261ecSmrg				((interp->sym==NoSymbol)?"Any":
31605b261ecSmrg					XkbKeysymText(interp->sym,XkbXKBFile)),
31705b261ecSmrg				XkbSIMatchText(interp->match,XkbXKBFile),
31805b261ecSmrg				XkbModMaskText(interp->mods,XkbXKBFile));
31905b261ecSmrg	if (interp->virtual_mod!=XkbNoModifier) {
32005b261ecSmrg	    fprintf(file,"        virtualModifier= %s;\n",
32105b261ecSmrg		XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile));
32205b261ecSmrg	}
32305b261ecSmrg	if (interp->match&XkbSI_LevelOneOnly)
32405b261ecSmrg	    fprintf(file,"        useModMapMods=level1;\n");
32505b261ecSmrg	if (interp->flags&XkbSI_LockingKey)
32605b261ecSmrg	    fprintf(file,"        locking= True;\n");
32705b261ecSmrg	if (interp->flags&XkbSI_AutoRepeat)
32805b261ecSmrg	    fprintf(file,"        repeat= True;\n");
32905b261ecSmrg	fprintf(file,"        action= ");
33005b261ecSmrg	WriteXKBAction(file,result,&interp->act);
33105b261ecSmrg	fprintf(file,";\n");
33205b261ecSmrg	fprintf(file,"    };\n");
33305b261ecSmrg    }
33405b261ecSmrg    for (i=0;i<XkbNumKbdGroups;i++) {
33505b261ecSmrg	XkbModsPtr	gc;
33605b261ecSmrg
33705b261ecSmrg	gc= &xkb->compat->groups[i];
33805b261ecSmrg	if ((gc->real_mods==0)&&(gc->vmods==0))
33905b261ecSmrg	    continue;
34005b261ecSmrg	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb,
34105b261ecSmrg							gc->real_mods,gc->vmods,
34205b261ecSmrg							XkbXKBFile));
34305b261ecSmrg    }
34405b261ecSmrg    if (xkb->indicators) {
34505b261ecSmrg	for (i=0;i<XkbNumIndicators;i++) {
34605b261ecSmrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
34705b261ecSmrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
34805b261ecSmrg		(map->which_mods!=0)||
34905b261ecSmrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
35005b261ecSmrg		(map->ctrls!=0)) {
35105b261ecSmrg		WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map,
35205b261ecSmrg								addOn,priv);
35305b261ecSmrg	    }
35405b261ecSmrg	}
35505b261ecSmrg    }
35605b261ecSmrg    if (addOn)
35705b261ecSmrg	(*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv);
35805b261ecSmrg    fprintf(file,"};\n\n");
35905b261ecSmrg    return True;
36005b261ecSmrg}
36105b261ecSmrg
36205b261ecSmrgBool
36305b261ecSmrgXkbWriteXKBSymbols(	FILE *			file,
36405b261ecSmrg			XkbFileInfo *		result,
36505b261ecSmrg			Bool			topLevel,
36605b261ecSmrg			Bool			showImplicit,
36705b261ecSmrg			XkbFileAddOnFunc	addOn,
36805b261ecSmrg			void *			priv)
36905b261ecSmrg{
37005b261ecSmrgDisplay *		dpy;
37105b261ecSmrgregister unsigned	i,tmp;
37205b261ecSmrgXkbDescPtr		xkb;
37305b261ecSmrgXkbClientMapPtr		map;
37405b261ecSmrgXkbServerMapPtr		srv;
37505b261ecSmrgBool			showActions;
37605b261ecSmrg
37705b261ecSmrg    xkb= result->xkb;
37805b261ecSmrg    map= xkb->map;
37905b261ecSmrg    srv= xkb->server;
38005b261ecSmrg    dpy= xkb->dpy;
38105b261ecSmrg    if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) {
38205b261ecSmrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
38305b261ecSmrg	return False;
38405b261ecSmrg    }
38505b261ecSmrg    if ((!xkb->names)||(!xkb->names->keys)) {
38605b261ecSmrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
38705b261ecSmrg	return False;
38805b261ecSmrg    }
38905b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->symbols==None))
39005b261ecSmrg	 fprintf(file,"xkb_symbols {\n\n");
39105b261ecSmrg    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
39205b261ecSmrg			XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile));
39305b261ecSmrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
39405b261ecSmrg	if (xkb->names->groups[i]!=None) {
39505b261ecSmrg	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
39605b261ecSmrg			XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile));
39705b261ecSmrg	    tmp++;
39805b261ecSmrg	}
39905b261ecSmrg    }
40005b261ecSmrg    if (tmp>0)
40105b261ecSmrg	fprintf(file,"\n");
40205b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
40305b261ecSmrg	Bool	simple;
40405b261ecSmrg	if ((int)XkbKeyNumSyms(xkb,i)<1)
40505b261ecSmrg	    continue;
40605b261ecSmrg	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
40705b261ecSmrg	    continue;
40805b261ecSmrg	simple= True;
40905b261ecSmrg	fprintf(file,"    key %6s {",
41005b261ecSmrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
41105b261ecSmrg	if (srv->explicit) {
41205b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
41305b261ecSmrg	   						(showImplicit)) {
41405b261ecSmrg		int 	typeNdx,g;
41505b261ecSmrg		Bool	multi;
41605b261ecSmrg		char *	comment="  ";
41705b261ecSmrg
41805b261ecSmrg		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
41905b261ecSmrg		    comment= "//";
42005b261ecSmrg		multi= False;
42105b261ecSmrg		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
42205b261ecSmrg		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
42305b261ecSmrg		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
42405b261ecSmrg			multi= True;
42505b261ecSmrg		}
42605b261ecSmrg		if (multi) {
42705b261ecSmrg		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
42805b261ecSmrg			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
42905b261ecSmrg			if (srv->explicit[i]&(1<<g)) {
43005b261ecSmrg			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
43105b261ecSmrg			    	comment,g+1,
43205b261ecSmrg				XkbAtomText(dpy,map->types[typeNdx].name,
43305b261ecSmrg			    	XkbXKBFile));
43405b261ecSmrg			}
43505b261ecSmrg			else if (showImplicit) {
43605b261ecSmrg			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
43705b261ecSmrg				XkbAtomText(dpy,map->types[typeNdx].name,
43805b261ecSmrg			    	XkbXKBFile));
43905b261ecSmrg			}
44005b261ecSmrg		    }
44105b261ecSmrg		}
44205b261ecSmrg		else {
44305b261ecSmrg		    fprintf(file,"\n%s      type= \"%s\",",comment,
44405b261ecSmrg				XkbAtomText(dpy,map->types[typeNdx].name,
44505b261ecSmrg			    	XkbXKBFile));
44605b261ecSmrg		}
44705b261ecSmrg		simple= False;
44805b261ecSmrg	    }
44905b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
45005b261ecSmrg		    					  (xkb->ctrls!=NULL)) {
45105b261ecSmrg		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
45205b261ecSmrg		     fprintf(file,"\n        repeat= Yes,");
45305b261ecSmrg		else fprintf(file,"\n        repeat= No,");
45405b261ecSmrg		simple= False;
45505b261ecSmrg	    }
45605b261ecSmrg	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
45705b261ecSmrg					(xkb->server->vmodmap[i]!=0)) {
45805b261ecSmrg		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
45905b261ecSmrg		    fprintf(file,"\n        virtualMods= %s,",
46005b261ecSmrg				XkbVModMaskText(dpy,xkb,0,
46105b261ecSmrg						xkb->server->vmodmap[i],
46205b261ecSmrg						XkbXKBFile));
46305b261ecSmrg		}
46405b261ecSmrg		else if (showImplicit) {
46505b261ecSmrg		    fprintf(file,"\n//      virtualMods= %s,",
46605b261ecSmrg				XkbVModMaskText(dpy,xkb,0,
46705b261ecSmrg						xkb->server->vmodmap[i],
46805b261ecSmrg						XkbXKBFile));
46905b261ecSmrg		}
47005b261ecSmrg	    }
47105b261ecSmrg	}
47205b261ecSmrg	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
47305b261ecSmrg	    case XkbClampIntoRange:
47405b261ecSmrg		fprintf(file,"\n        groupsClamp,");
47505b261ecSmrg		break;
47605b261ecSmrg	    case XkbRedirectIntoRange:
47705b261ecSmrg		fprintf(file,"\n        groupsRedirect= Group%d,",
47805b261ecSmrg			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
47905b261ecSmrg		break;
48005b261ecSmrg	}
48105b261ecSmrg	if (srv->behaviors!=NULL) {
48205b261ecSmrg	    unsigned type;
48305b261ecSmrg	    type= srv->behaviors[i].type&XkbKB_OpMask;
48405b261ecSmrg
48505b261ecSmrg	    if (type!=XkbKB_Default) {
48605b261ecSmrg		simple= False;
48705b261ecSmrg		fprintf(file,"\n        %s,",
48805b261ecSmrg			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
48905b261ecSmrg	    }
49005b261ecSmrg	}
49105b261ecSmrg	if ((srv->explicit==NULL) || showImplicit ||
49205b261ecSmrg	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
49305b261ecSmrg	     showActions= XkbKeyHasActions(xkb,i);
49405b261ecSmrg	else showActions= False;
49505b261ecSmrg
49605b261ecSmrg	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
49705b261ecSmrg	    simple= False;
49805b261ecSmrg	if (simple) {
49905b261ecSmrg	    KeySym *syms;
50005b261ecSmrg	    unsigned s;
50105b261ecSmrg
50205b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
50305b261ecSmrg	    fprintf(file,"         [ ");
50405b261ecSmrg	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
50505b261ecSmrg		if (s!=0)
50605b261ecSmrg		    fprintf(file,", ");
50705b261ecSmrg		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
50805b261ecSmrg	    }
50905b261ecSmrg	    fprintf(file," ] };\n");
51005b261ecSmrg	}
51105b261ecSmrg	else {
51205b261ecSmrg	    unsigned g,s;
51305b261ecSmrg	    KeySym *syms;
51405b261ecSmrg	    XkbAction *acts;
51505b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
51605b261ecSmrg	    acts= XkbKeyActionsPtr(xkb,i);
51705b261ecSmrg	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
51805b261ecSmrg		if (g!=0)
51905b261ecSmrg		    fprintf(file,",");
52005b261ecSmrg		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
52105b261ecSmrg		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
52205b261ecSmrg		    if (s!=0)
52305b261ecSmrg			fprintf(file,", ");
52405b261ecSmrg		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
52505b261ecSmrg		}
52605b261ecSmrg		fprintf(file," ]");
52705b261ecSmrg		syms+= XkbKeyGroupsWidth(xkb,i);
52805b261ecSmrg		if (showActions) {
52905b261ecSmrg		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
53005b261ecSmrg		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
53105b261ecSmrg			if (s!=0)
53205b261ecSmrg			    fprintf(file,", ");
53305b261ecSmrg			WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]);
53405b261ecSmrg		    }
53505b261ecSmrg		    fprintf(file," ]");
53605b261ecSmrg		    acts+= XkbKeyGroupsWidth(xkb,i);
53705b261ecSmrg		}
53805b261ecSmrg	    }
53905b261ecSmrg	    fprintf(file,"\n    };\n");
54005b261ecSmrg	}
54105b261ecSmrg    }
54205b261ecSmrg    if (map && map->modmap) {
54305b261ecSmrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
54405b261ecSmrg	    if (map->modmap[i]!=0) {
54505b261ecSmrg		register int n,bit;
54605b261ecSmrg		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
54705b261ecSmrg		    if (map->modmap[i]&bit) {
54805b261ecSmrg			char buf[5];
54905b261ecSmrg			memcpy(buf,xkb->names->keys[i].name,4);
55005b261ecSmrg			buf[4]= '\0';
55105b261ecSmrg			fprintf(file,"    modifier_map %s { <%s> };\n",
55205b261ecSmrg					XkbModIndexText(n,XkbXKBFile),buf);
55305b261ecSmrg		    }
55405b261ecSmrg		}
55505b261ecSmrg	    }
55605b261ecSmrg	}
55705b261ecSmrg    }
55805b261ecSmrg    if (addOn)
55905b261ecSmrg	(*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv);
56005b261ecSmrg    fprintf(file,"};\n\n");
56105b261ecSmrg    return True;
56205b261ecSmrg}
56305b261ecSmrg
56405b261ecSmrgstatic Bool
56505b261ecSmrgWriteXKBOutline(	FILE *		file,
56605b261ecSmrg			XkbShapePtr	shape,
56705b261ecSmrg			XkbOutlinePtr	outline,
56805b261ecSmrg			int		lastRadius,
56905b261ecSmrg			int		first,
57005b261ecSmrg			int		indent)
57105b261ecSmrg{
57205b261ecSmrgregister int	i;
57305b261ecSmrgXkbPointPtr	pt;
57405b261ecSmrgchar *		iStr;
57505b261ecSmrg
57605b261ecSmrg    fprintf(file,"%s",iStr= XkbIndentText(first));
57705b261ecSmrg    if (first!=indent)
57805b261ecSmrg	iStr= XkbIndentText(indent);
57905b261ecSmrg    if (outline->corner_radius!=lastRadius) {
58005b261ecSmrg	fprintf(file,"corner= %s,",
58105b261ecSmrg			XkbGeomFPText(outline->corner_radius,XkbMessage));
58205b261ecSmrg	if (shape!=NULL) {
58305b261ecSmrg	    fprintf(file,"\n%s",iStr);
58405b261ecSmrg	}
58505b261ecSmrg    }
58605b261ecSmrg    if (shape) {
58705b261ecSmrg	if (outline==shape->approx)
58805b261ecSmrg	    fprintf(file,"approx= ");
58905b261ecSmrg	else if (outline==shape->primary)
59005b261ecSmrg	    fprintf(file,"primary= ");
59105b261ecSmrg    }
59205b261ecSmrg    fprintf(file,"{");
59305b261ecSmrg    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
59405b261ecSmrg	if (i==0)		fprintf(file," ");
59505b261ecSmrg	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
59605b261ecSmrg	else			fprintf(file,", ");
59705b261ecSmrg	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
59805b261ecSmrg				  XkbGeomFPText(pt->y,XkbXKBFile));
59905b261ecSmrg    }
60005b261ecSmrg    fprintf(file," }");
60105b261ecSmrg    return True;
60205b261ecSmrg}
60305b261ecSmrg
60405b261ecSmrgstatic Bool
60505b261ecSmrgWriteXKBDoodad(	FILE *		file,
60605b261ecSmrg		Display *	dpy,
60705b261ecSmrg		unsigned	indent,
60805b261ecSmrg		XkbGeometryPtr	geom,
60905b261ecSmrg		XkbDoodadPtr	doodad)
61005b261ecSmrg{
61105b261ecSmrgregister char *	i_str;
61205b261ecSmrgXkbShapePtr	shape;
61305b261ecSmrgXkbColorPtr	color;
61405b261ecSmrg
61505b261ecSmrg    i_str= XkbIndentText(indent);
61605b261ecSmrg    fprintf(file,"%s%s \"%s\" {\n",i_str,
61705b261ecSmrg				XkbDoodadTypeText(doodad->any.type,XkbMessage),
61805b261ecSmrg				XkbAtomText(dpy,doodad->any.name,XkbMessage));
61905b261ecSmrg    fprintf(file,"%s    top=      %s;\n",i_str,
62005b261ecSmrg				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
62105b261ecSmrg    fprintf(file,"%s    left=     %s;\n",i_str,
62205b261ecSmrg				XkbGeomFPText(doodad->any.left,XkbXKBFile));
62305b261ecSmrg    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
62405b261ecSmrg    switch (doodad->any.type) {
62505b261ecSmrg	case XkbOutlineDoodad:
62605b261ecSmrg	case XkbSolidDoodad:
62705b261ecSmrg	    if (doodad->shape.angle!=0) {
62805b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
62905b261ecSmrg			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
63005b261ecSmrg	    }
63105b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
63205b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
63305b261ecSmrg			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
63405b261ecSmrg	    }
63505b261ecSmrg	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
63605b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
63705b261ecSmrg			    XkbAtomText(dpy,shape->name,XkbXKBFile));
63805b261ecSmrg	    break;
63905b261ecSmrg	case XkbTextDoodad:
64005b261ecSmrg	    if (doodad->text.angle!=0) {
64105b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
64205b261ecSmrg			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
64305b261ecSmrg	    }
64405b261ecSmrg	    if (doodad->text.width!=0) {
64505b261ecSmrg		fprintf(file,"%s    width=  %s;\n",i_str,
64605b261ecSmrg			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
64705b261ecSmrg
64805b261ecSmrg	    }
64905b261ecSmrg	    if (doodad->text.height!=0) {
65005b261ecSmrg		fprintf(file,"%s    height=  %s;\n",i_str,
65105b261ecSmrg			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
65205b261ecSmrg
65305b261ecSmrg	    }
65405b261ecSmrg	    if (doodad->text.color_ndx!=0) {
65505b261ecSmrg		color= XkbTextDoodadColor(geom,&doodad->text);
65605b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
65705b261ecSmrg			     XkbStringText(color->spec,XkbXKBFile));
65805b261ecSmrg	    }
65905b261ecSmrg	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
66005b261ecSmrg	    		     XkbStringText(doodad->text.font,XkbXKBFile));
66105b261ecSmrg	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
66205b261ecSmrg	    		    XkbStringText(doodad->text.text,XkbXKBFile));
66305b261ecSmrg	    break;
66405b261ecSmrg	case XkbIndicatorDoodad:
66505b261ecSmrg	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
66605b261ecSmrg	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
66705b261ecSmrg	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
66805b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
66905b261ecSmrg	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
67005b261ecSmrg	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
67105b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
67205b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
67305b261ecSmrg			     XkbAtomText(dpy,shape->name,XkbXKBFile));
67405b261ecSmrg	    break;
67505b261ecSmrg	case XkbLogoDoodad:
67605b261ecSmrg	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
67705b261ecSmrg			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
67805b261ecSmrg	    if (doodad->shape.angle!=0) {
67905b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
68005b261ecSmrg			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
68105b261ecSmrg	    }
68205b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
68305b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
68405b261ecSmrg			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
68505b261ecSmrg	    }
68605b261ecSmrg	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
68705b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
68805b261ecSmrg			    XkbAtomText(dpy,shape->name,XkbXKBFile));
68905b261ecSmrg	    break;
69005b261ecSmrg    }
69105b261ecSmrg    fprintf(file,"%s};\n",i_str);
69205b261ecSmrg    return True;
69305b261ecSmrg}
69405b261ecSmrg
69505b261ecSmrg/*ARGSUSED*/
69605b261ecSmrgstatic Bool
69705b261ecSmrgWriteXKBOverlay(	FILE *		file,
69805b261ecSmrg			Display *	dpy,
69905b261ecSmrg			unsigned	indent,
70005b261ecSmrg			XkbGeometryPtr	geom,
70105b261ecSmrg			XkbOverlayPtr	ol)
70205b261ecSmrg{
70305b261ecSmrgregister char *		i_str;
70405b261ecSmrgint			r,k,nOut;
70505b261ecSmrgXkbOverlayRowPtr	row;
70605b261ecSmrgXkbOverlayKeyPtr	key;
70705b261ecSmrg
70805b261ecSmrg    i_str= XkbIndentText(indent);
70905b261ecSmrg    if (ol->name!=None) {
71005b261ecSmrg	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
71105b261ecSmrg    					XkbAtomText(dpy,ol->name,XkbMessage));
71205b261ecSmrg    }
71305b261ecSmrg    else fprintf(file,"%soverlay {\n",i_str);
71405b261ecSmrg    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
71505b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
71605b261ecSmrg	    char *over,*under;
71705b261ecSmrg	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
71805b261ecSmrg	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
71905b261ecSmrg	    if (nOut==0)
72005b261ecSmrg		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
72105b261ecSmrg	    else if ((nOut%4)==0)
72205b261ecSmrg		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
72305b261ecSmrg	    else fprintf(file,", %6s=%6s",under,over);
72405b261ecSmrg	    nOut++;
72505b261ecSmrg	}
72605b261ecSmrg    }
72705b261ecSmrg    fprintf(file,"\n%s};\n",i_str);
72805b261ecSmrg    return True;
72905b261ecSmrg}
73005b261ecSmrg
73105b261ecSmrgstatic Bool
73205b261ecSmrgWriteXKBSection(	FILE *		file,
73305b261ecSmrg			Display *	dpy,
73405b261ecSmrg			XkbSectionPtr 	s,
73505b261ecSmrg			XkbGeometryPtr	geom)
73605b261ecSmrg{
73705b261ecSmrgregister int	i;
73805b261ecSmrgXkbRowPtr	row;
73905b261ecSmrgint		dfltKeyColor = 0;
74005b261ecSmrg
74105b261ecSmrg    fprintf(file,"    section \"%s\" {\n",
74205b261ecSmrg				XkbAtomText(dpy,s->name,XkbXKBFile));
74305b261ecSmrg    if (s->rows&&(s->rows->num_keys>0)) {
74405b261ecSmrg	dfltKeyColor= s->rows->keys[0].color_ndx;
74505b261ecSmrg	fprintf(file,"        key.color= \"%s\";\n",
74605b261ecSmrg		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
74705b261ecSmrg    }
74805b261ecSmrg    fprintf(file,"        priority=  %d;\n",s->priority);
74905b261ecSmrg    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
75005b261ecSmrg    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
75105b261ecSmrg    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
75205b261ecSmrg    fprintf(file,"        height=    %s;\n",
75305b261ecSmrg					XkbGeomFPText(s->height,XkbXKBFile));
75405b261ecSmrg    if (s->angle!=0) {
75505b261ecSmrg	fprintf(file,"        angle=  %s;\n",
75605b261ecSmrg					XkbGeomFPText(s->angle,XkbXKBFile));
75705b261ecSmrg    }
75805b261ecSmrg    for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
75905b261ecSmrg	fprintf(file,"        row {\n");
76005b261ecSmrg	fprintf(file,"            top=  %s;\n",
76105b261ecSmrg					XkbGeomFPText(row->top,XkbXKBFile));
76205b261ecSmrg	fprintf(file,"            left= %s;\n",
76305b261ecSmrg					XkbGeomFPText(row->left,XkbXKBFile));
76405b261ecSmrg	if (row->vertical)
76505b261ecSmrg	    fprintf(file,"            vertical;\n");
76605b261ecSmrg	if (row->num_keys>0) {
76705b261ecSmrg	    register int 	k;
76805b261ecSmrg	    register XkbKeyPtr	key;
76905b261ecSmrg	    int			forceNL=0;
77005b261ecSmrg	    int			nThisLine= 0;
77105b261ecSmrg	    fprintf(file,"            keys {\n");
77205b261ecSmrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
77305b261ecSmrg		XkbShapePtr	shape;
77405b261ecSmrg		if (key->color_ndx!=dfltKeyColor)
77505b261ecSmrg		    forceNL= 1;
77605b261ecSmrg		if (k==0) {
77705b261ecSmrg		     fprintf(file,"                ");
77805b261ecSmrg		     nThisLine= 0;
77905b261ecSmrg		}
78005b261ecSmrg		else if (((nThisLine%2)==1)||(forceNL)) {
78105b261ecSmrg		     fprintf(file,",\n                ");
78205b261ecSmrg		     forceNL= nThisLine= 0;
78305b261ecSmrg		}
78405b261ecSmrg		else {
78505b261ecSmrg		     fprintf(file,", ");
78605b261ecSmrg		     nThisLine++;
78705b261ecSmrg		}
78805b261ecSmrg		shape= XkbKeyShape(geom,key);
78905b261ecSmrg		fprintf(file,"{ %6s, \"%s\", %3s",
79005b261ecSmrg		      XkbKeyNameText(key->name.name,XkbXKBFile),
79105b261ecSmrg		      XkbAtomText(dpy,shape->name,XkbXKBFile),
79205b261ecSmrg		      XkbGeomFPText(key->gap,XkbXKBFile));
79305b261ecSmrg		if (key->color_ndx!=dfltKeyColor) {
79405b261ecSmrg		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
79505b261ecSmrg		    forceNL= 1;
79605b261ecSmrg		}
79705b261ecSmrg		fprintf(file," }");
79805b261ecSmrg	    }
79905b261ecSmrg	    fprintf(file,"\n            };\n");
80005b261ecSmrg	}
80105b261ecSmrg	fprintf(file,"        };\n");
80205b261ecSmrg    }
80305b261ecSmrg    if (s->doodads!=NULL) {
80405b261ecSmrg	XkbDoodadPtr	doodad;
80505b261ecSmrg	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
80605b261ecSmrg	    WriteXKBDoodad(file,dpy,8,geom,doodad);
80705b261ecSmrg	}
80805b261ecSmrg    }
80905b261ecSmrg    if (s->overlays!=NULL) {
81005b261ecSmrg	XkbOverlayPtr	ol;
81105b261ecSmrg	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
81205b261ecSmrg	    WriteXKBOverlay(file,dpy,8,geom,ol);
81305b261ecSmrg	}
81405b261ecSmrg    }
81505b261ecSmrg    fprintf(file,"    }; // End of \"%s\" section\n\n",
81605b261ecSmrg				XkbAtomText(dpy,s->name,XkbXKBFile));
81705b261ecSmrg    return True;
81805b261ecSmrg}
81905b261ecSmrg
82005b261ecSmrgBool
82105b261ecSmrgXkbWriteXKBGeometry(	FILE *			file,
82205b261ecSmrg			XkbFileInfo *		result,
82305b261ecSmrg			Bool			topLevel,
82405b261ecSmrg			Bool			showImplicit,
82505b261ecSmrg			XkbFileAddOnFunc	addOn,
82605b261ecSmrg			void *			priv)
82705b261ecSmrg{
82805b261ecSmrgDisplay *		dpy;
82905b261ecSmrgregister unsigned	i,n;
83005b261ecSmrgXkbDescPtr		xkb;
83105b261ecSmrgXkbGeometryPtr		geom;
83205b261ecSmrg
83305b261ecSmrg    xkb= result->xkb;
83405b261ecSmrg    if ((!xkb)||(!xkb->geom)) {
83505b261ecSmrg	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
83605b261ecSmrg 	return False;
83705b261ecSmrg    }
83805b261ecSmrg    dpy= xkb->dpy;
83905b261ecSmrg    geom= xkb->geom;
84005b261ecSmrg    if (geom->name==None)
84105b261ecSmrg	 fprintf(file,"xkb_geometry {\n\n");
84205b261ecSmrg    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
84305b261ecSmrg				XkbAtomText(dpy,geom->name,XkbXKBFile));
84405b261ecSmrg    fprintf(file,"    width=       %s;\n",
84505b261ecSmrg				XkbGeomFPText(geom->width_mm,XkbXKBFile));
84605b261ecSmrg    fprintf(file,"    height=      %s;\n\n",
84705b261ecSmrg				XkbGeomFPText(geom->height_mm,XkbXKBFile));
84805b261ecSmrg
84905b261ecSmrg    if (geom->key_aliases!=NULL) {
85005b261ecSmrg	XkbKeyAliasPtr	pAl;
85105b261ecSmrg	pAl= geom->key_aliases;
85205b261ecSmrg	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
85305b261ecSmrg	    fprintf(file,"    alias %6s = %6s;\n",
85405b261ecSmrg				XkbKeyNameText(pAl->alias,XkbXKBFile),
85505b261ecSmrg				XkbKeyNameText(pAl->real,XkbXKBFile));
85605b261ecSmrg	}
85705b261ecSmrg	fprintf(file,"\n");
85805b261ecSmrg    }
85905b261ecSmrg
86005b261ecSmrg    if (geom->base_color!=NULL)
86105b261ecSmrg	fprintf(file,"    baseColor=   \"%s\";\n",
86205b261ecSmrg			XkbStringText(geom->base_color->spec,XkbXKBFile));
86305b261ecSmrg    if (geom->label_color!=NULL)
86405b261ecSmrg	fprintf(file,"    labelColor=  \"%s\";\n",
86505b261ecSmrg			XkbStringText(geom->label_color->spec,XkbXKBFile));
86605b261ecSmrg    if (geom->label_font!=NULL)
86705b261ecSmrg	fprintf(file,"    xfont=       \"%s\";\n",
86805b261ecSmrg			XkbStringText(geom->label_font,XkbXKBFile));
86905b261ecSmrg    if ((geom->num_colors>0)&&(showImplicit)) {
87005b261ecSmrg	XkbColorPtr	color;
87105b261ecSmrg	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
87205b261ecSmrg		fprintf(file,"//     color[%d]= \"%s\"\n",i,
87305b261ecSmrg				XkbStringText(color->spec,XkbXKBFile));
87405b261ecSmrg	}
87505b261ecSmrg	fprintf(file,"\n");
87605b261ecSmrg    }
87705b261ecSmrg    if (geom->num_properties>0) {
87805b261ecSmrg	XkbPropertyPtr	prop;
87905b261ecSmrg	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
88005b261ecSmrg	    fprintf(file,"    %s= \"%s\";\n",prop->name,
88105b261ecSmrg    				XkbStringText(prop->value,XkbXKBFile));
88205b261ecSmrg	}
88305b261ecSmrg	fprintf(file,"\n");
88405b261ecSmrg    }
88505b261ecSmrg    if (geom->num_shapes>0) {
88605b261ecSmrg	XkbShapePtr	shape;
88705b261ecSmrg	XkbOutlinePtr	outline;
88805b261ecSmrg	int		lastR;
88905b261ecSmrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
89005b261ecSmrg	    lastR=0;
89105b261ecSmrg	    fprintf(file,"    shape \"%s\" {",
89205b261ecSmrg				   XkbAtomText(dpy,shape->name,XkbXKBFile));
89305b261ecSmrg	    outline= shape->outlines;
89405b261ecSmrg	    if (shape->num_outlines>1) {
89505b261ecSmrg		for (n=0;n<shape->num_outlines;n++,outline++) {
89605b261ecSmrg		    if (n==0)	fprintf(file,"\n");
89705b261ecSmrg		    else	fprintf(file,",\n");
89805b261ecSmrg		    WriteXKBOutline(file,shape,outline,lastR,8,8);
89905b261ecSmrg		    lastR= outline->corner_radius;
90005b261ecSmrg		}
90105b261ecSmrg		fprintf(file,"\n    };\n");
90205b261ecSmrg	    }
90305b261ecSmrg	    else {
90405b261ecSmrg		WriteXKBOutline(file,NULL,outline,lastR,1,8);
90505b261ecSmrg		fprintf(file," };\n");
90605b261ecSmrg	    }
90705b261ecSmrg	}
90805b261ecSmrg    }
90905b261ecSmrg    if (geom->num_sections>0) {
91005b261ecSmrg	XkbSectionPtr	section;
91105b261ecSmrg	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
91205b261ecSmrg	    WriteXKBSection(file,dpy,section,geom);
91305b261ecSmrg	}
91405b261ecSmrg    }
91505b261ecSmrg    if (geom->num_doodads>0) {
91605b261ecSmrg	XkbDoodadPtr	doodad;
91705b261ecSmrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
91805b261ecSmrg	    WriteXKBDoodad(file,dpy,4,geom,doodad);
91905b261ecSmrg	}
92005b261ecSmrg    }
92105b261ecSmrg    if (addOn)
92205b261ecSmrg	(*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv);
92305b261ecSmrg    fprintf(file,"};\n\n");
92405b261ecSmrg    return True;
92505b261ecSmrg}
926