xkbout.c revision 6747b715
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#include <X11/keysym.h>
3805b261ecSmrg#include <X11/Xproto.h>
396747b715Smrg#include <X11/extensions/XKMformat.h>
4005b261ecSmrg#include "misc.h"
4105b261ecSmrg#include "inputstr.h"
4205b261ecSmrg#include "dix.h"
434642e01fSmrg#include "xkbstr.h"
4405b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS	1
4505b261ecSmrg#include <xkbsrv.h>
4605b261ecSmrg
474642e01fSmrg#include "xkbgeom.h"
484642e01fSmrg#include "xkbfile.h"
4905b261ecSmrg
5005b261ecSmrg#define	VMOD_HIDE_VALUE	0
5105b261ecSmrg#define	VMOD_SHOW_VALUE	1
5205b261ecSmrg#define	VMOD_COMMENT_VALUE 2
5305b261ecSmrg
5405b261ecSmrgstatic Bool
554642e01fSmrgWriteXKBVModDecl(FILE *file,XkbDescPtr xkb,int showValue)
5605b261ecSmrg{
5705b261ecSmrgregister int 	i,nMods;
5805b261ecSmrgAtom *		vmodNames;
5905b261ecSmrg
6005b261ecSmrg    if (xkb==NULL)
616747b715Smrg	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,",");
704642e01fSmrg	    fprintf(file,"%s",XkbAtomText(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");
876747b715Smrg    return TRUE;
8805b261ecSmrg}
8905b261ecSmrg
9005b261ecSmrg/***====================================================================***/
9105b261ecSmrg
9205b261ecSmrgstatic Bool
934642e01fSmrgWriteXKBAction(FILE *file,XkbDescPtr xkb,XkbAnyAction *action)
9405b261ecSmrg{
954642e01fSmrg    fprintf(file,"%s",XkbActionText(xkb,(XkbAction *)action,XkbXKBFile));
966747b715Smrg    return TRUE;
9705b261ecSmrg}
9805b261ecSmrg
9905b261ecSmrg/***====================================================================***/
10005b261ecSmrg
10105b261ecSmrgBool
10205b261ecSmrgXkbWriteXKBKeycodes(	FILE *			file,
1034642e01fSmrg			XkbDescPtr		xkb,
10405b261ecSmrg			Bool			topLevel,
10505b261ecSmrg			Bool			showImplicit,
10605b261ecSmrg			XkbFileAddOnFunc	addOn,
10705b261ecSmrg			void *			priv)
10805b261ecSmrg{
10905b261ecSmrgAtom			kcName;
11005b261ecSmrgregister unsigned 	i;
11105b261ecSmrgchar *			alternate;
11205b261ecSmrg
11305b261ecSmrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
11405b261ecSmrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
1156747b715Smrg	return FALSE;
11605b261ecSmrg    }
11705b261ecSmrg    kcName= xkb->names->keycodes;
11805b261ecSmrg    if (kcName!=None)
11905b261ecSmrg	 fprintf(file,"xkb_keycodes \"%s\" {\n",
1204642e01fSmrg					XkbAtomText(kcName,XkbXKBFile));
12105b261ecSmrg    else fprintf(file,"xkb_keycodes {\n");
12205b261ecSmrg    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
12305b261ecSmrg    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
12405b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
12505b261ecSmrg	if (xkb->names->keys[i].name[0]!='\0') {
1266747b715Smrg	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,TRUE)!=i)
12705b261ecSmrg		 alternate= "alternate ";
12805b261ecSmrg	    else alternate= "";
12905b261ecSmrg	    fprintf(file,"    %s%6s = %d;\n",alternate,
13005b261ecSmrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
13105b261ecSmrg			i);
13205b261ecSmrg	}
13305b261ecSmrg    }
13405b261ecSmrg    if (xkb->indicators!=NULL) {
13505b261ecSmrg	for (i=0;i<XkbNumIndicators;i++) {
13605b261ecSmrg	    char *type;
13705b261ecSmrg	    if (xkb->indicators->phys_indicators&(1<<i))
13805b261ecSmrg			type= "    ";
13905b261ecSmrg	    else	type= "    virtual ";
14005b261ecSmrg	    if (xkb->names->indicators[i]!=None) {
14105b261ecSmrg		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
1424642e01fSmrg			XkbAtomText(xkb->names->indicators[i],XkbXKBFile));
14305b261ecSmrg	    }
14405b261ecSmrg	}
14505b261ecSmrg    }
14605b261ecSmrg    if (xkb->names->key_aliases!=NULL) {
14705b261ecSmrg	XkbKeyAliasPtr	pAl;
14805b261ecSmrg	pAl= xkb->names->key_aliases;
14905b261ecSmrg	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
15005b261ecSmrg	    fprintf(file,"    alias %6s = %6s;\n",
15105b261ecSmrg			XkbKeyNameText(pAl->alias,XkbXKBFile),
15205b261ecSmrg			XkbKeyNameText(pAl->real,XkbXKBFile));
15305b261ecSmrg	}
15405b261ecSmrg    }
15505b261ecSmrg    if (addOn)
1564642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmKeyNamesIndex,priv);
15705b261ecSmrg    fprintf(file,"};\n\n");
1586747b715Smrg    return TRUE;
15905b261ecSmrg}
16005b261ecSmrg
16105b261ecSmrgBool
16205b261ecSmrgXkbWriteXKBKeyTypes(	FILE *			file,
1634642e01fSmrg			XkbDescPtr              xkb,
16405b261ecSmrg			Bool			topLevel,
16505b261ecSmrg			Bool			showImplicit,
16605b261ecSmrg			XkbFileAddOnFunc	addOn,
16705b261ecSmrg			void *			priv)
16805b261ecSmrg{
16905b261ecSmrgregister unsigned	i,n;
17005b261ecSmrgXkbKeyTypePtr		type;
17105b261ecSmrgXkbKTMapEntryPtr	entry;
17205b261ecSmrg
17305b261ecSmrg    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
17405b261ecSmrg	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
1756747b715Smrg	return FALSE;
17605b261ecSmrg    }
17705b261ecSmrg    if (xkb->map->num_types<XkbNumRequiredTypes) {
17805b261ecSmrg	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
17905b261ecSmrg	return 0;
18005b261ecSmrg    }
18105b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->types==None))
18205b261ecSmrg	 fprintf(file,"xkb_types {\n\n");
18305b261ecSmrg    else fprintf(file,"xkb_types \"%s\" {\n\n",
1844642e01fSmrg			XkbAtomText(xkb->names->types,XkbXKBFile));
1854642e01fSmrg    WriteXKBVModDecl(file,xkb,
18605b261ecSmrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
18705b261ecSmrg
18805b261ecSmrg    type= xkb->map->types;
18905b261ecSmrg    for (i=0;i<xkb->map->num_types;i++,type++) {
19005b261ecSmrg	fprintf(file,"    type \"%s\" {\n",
1914642e01fSmrg		XkbAtomText(type->name,XkbXKBFile));
19205b261ecSmrg	fprintf(file,"        modifiers= %s;\n",
1934642e01fSmrg	       XkbVModMaskText(xkb,type->mods.real_mods,type->mods.vmods,
19405b261ecSmrg								XkbXKBFile));
19505b261ecSmrg	entry= type->map;
19605b261ecSmrg	for (n=0;n<type->map_count;n++,entry++) {
19705b261ecSmrg	    char *str;
1984642e01fSmrg	    str=XkbVModMaskText(xkb,entry->mods.real_mods,entry->mods.vmods,
19905b261ecSmrg								XkbXKBFile);
20005b261ecSmrg	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
20105b261ecSmrg	    if ((type->preserve)&&((type->preserve[n].real_mods)||
20205b261ecSmrg				   (type->preserve[n].vmods))) {
20305b261ecSmrg		fprintf(file,"        preserve[%s]= ",str);
2044642e01fSmrg		fprintf(file,"%s;\n",XkbVModMaskText(xkb,
20505b261ecSmrg					type->preserve[n].real_mods,
20605b261ecSmrg					type->preserve[n].vmods,
20705b261ecSmrg					XkbXKBFile));
20805b261ecSmrg	    }
20905b261ecSmrg	}
21005b261ecSmrg	if (type->level_names!=NULL) {
21105b261ecSmrg	    Atom *name= type->level_names;
21205b261ecSmrg	    for (n=0;n<type->num_levels;n++,name++) {
21305b261ecSmrg		if ((*name)==None)
21405b261ecSmrg		    continue;
21505b261ecSmrg		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
2164642e01fSmrg					XkbAtomText(*name,XkbXKBFile));
21705b261ecSmrg	    }
21805b261ecSmrg	}
21905b261ecSmrg	fprintf(file,"    };\n");
22005b261ecSmrg    }
22105b261ecSmrg    if (addOn)
2224642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmTypesIndex,priv);
22305b261ecSmrg    fprintf(file,"};\n\n");
2246747b715Smrg    return TRUE;
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrgstatic Bool
22805b261ecSmrgWriteXKBIndicatorMap(	FILE *			file,
2294642e01fSmrg			XkbDescPtr              xkb,
23005b261ecSmrg			Atom			name,
23105b261ecSmrg			XkbIndicatorMapPtr	led,
23205b261ecSmrg			XkbFileAddOnFunc	addOn,
23305b261ecSmrg			void *			priv)
23405b261ecSmrg{
23505b261ecSmrg
2366747b715Smrg    fprintf(file,"    indicator \"%s\" {\n",NameForAtom(name));
23705b261ecSmrg    if (led->flags&XkbIM_NoExplicit)
23805b261ecSmrg	fprintf(file,"        !allowExplicit;\n");
23905b261ecSmrg    if (led->flags&XkbIM_LEDDrivesKB)
24005b261ecSmrg	fprintf(file,"        indicatorDrivesKeyboard;\n");
24105b261ecSmrg    if (led->which_groups!=0) {
24205b261ecSmrg	if (led->which_groups!=XkbIM_UseEffective) {
24305b261ecSmrg	    fprintf(file,"        whichGroupState= %s;\n",
24405b261ecSmrg			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
24505b261ecSmrg	}
24605b261ecSmrg	fprintf(file,"        groups= 0x%02x;\n",led->groups);
24705b261ecSmrg    }
24805b261ecSmrg    if (led->which_mods!=0) {
24905b261ecSmrg	if (led->which_mods!=XkbIM_UseEffective) {
25005b261ecSmrg	    fprintf(file,"        whichModState= %s;\n",
25105b261ecSmrg			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
25205b261ecSmrg	}
25305b261ecSmrg	fprintf(file,"        modifiers= %s;\n",
2544642e01fSmrg			XkbVModMaskText(xkb,
25505b261ecSmrg					led->mods.real_mods,led->mods.vmods,
25605b261ecSmrg					XkbXKBFile));
25705b261ecSmrg    }
25805b261ecSmrg    if (led->ctrls!=0) {
25905b261ecSmrg	fprintf(file,"        controls= %s;\n",
26005b261ecSmrg			XkbControlsMaskText(led->ctrls,XkbXKBFile));
26105b261ecSmrg    }
26205b261ecSmrg    if (addOn)
2636747b715Smrg	(*addOn)(file,xkb,FALSE,TRUE,XkmIndicatorsIndex,priv);
26405b261ecSmrg    fprintf(file,"    };\n");
2656747b715Smrg    return TRUE;
26605b261ecSmrg}
26705b261ecSmrg
26805b261ecSmrgBool
26905b261ecSmrgXkbWriteXKBCompatMap(	FILE *			file,
2704642e01fSmrg			XkbDescPtr              xkb,
27105b261ecSmrg			Bool			topLevel,
27205b261ecSmrg			Bool			showImplicit,
27305b261ecSmrg			XkbFileAddOnFunc	addOn,
27405b261ecSmrg			void *			priv)
27505b261ecSmrg{
27605b261ecSmrgregister unsigned	i;
27705b261ecSmrgXkbSymInterpretPtr	interp;
27805b261ecSmrg
27905b261ecSmrg    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
28005b261ecSmrg	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
2816747b715Smrg	return FALSE;
28205b261ecSmrg    }
28305b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->compat==None))
28405b261ecSmrg	 fprintf(file,"xkb_compatibility {\n\n");
28505b261ecSmrg    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
2864642e01fSmrg			XkbAtomText(xkb->names->compat,XkbXKBFile));
2874642e01fSmrg    WriteXKBVModDecl(file,xkb,
28805b261ecSmrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
28905b261ecSmrg
29005b261ecSmrg    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
2916747b715Smrg    fprintf(file,"    interpret.repeat= FALSE;\n");
2926747b715Smrg    fprintf(file,"    interpret.locking= FALSE;\n");
29305b261ecSmrg    interp= xkb->compat->sym_interpret;
29405b261ecSmrg    for (i=0;i<xkb->compat->num_si;i++,interp++) {
29505b261ecSmrg	fprintf(file,"    interpret %s+%s(%s) {\n",
29605b261ecSmrg				((interp->sym==NoSymbol)?"Any":
29705b261ecSmrg					XkbKeysymText(interp->sym,XkbXKBFile)),
29805b261ecSmrg				XkbSIMatchText(interp->match,XkbXKBFile),
29905b261ecSmrg				XkbModMaskText(interp->mods,XkbXKBFile));
30005b261ecSmrg	if (interp->virtual_mod!=XkbNoModifier) {
30105b261ecSmrg	    fprintf(file,"        virtualModifier= %s;\n",
3024642e01fSmrg		XkbVModIndexText(xkb,interp->virtual_mod,XkbXKBFile));
30305b261ecSmrg	}
30405b261ecSmrg	if (interp->match&XkbSI_LevelOneOnly)
30505b261ecSmrg	    fprintf(file,"        useModMapMods=level1;\n");
30605b261ecSmrg	if (interp->flags&XkbSI_LockingKey)
3076747b715Smrg	    fprintf(file,"        locking= TRUE;\n");
30805b261ecSmrg	if (interp->flags&XkbSI_AutoRepeat)
3096747b715Smrg	    fprintf(file,"        repeat= TRUE;\n");
31005b261ecSmrg	fprintf(file,"        action= ");
3114642e01fSmrg	WriteXKBAction(file,xkb,&interp->act);
31205b261ecSmrg	fprintf(file,";\n");
31305b261ecSmrg	fprintf(file,"    };\n");
31405b261ecSmrg    }
31505b261ecSmrg    for (i=0;i<XkbNumKbdGroups;i++) {
31605b261ecSmrg	XkbModsPtr	gc;
31705b261ecSmrg
31805b261ecSmrg	gc= &xkb->compat->groups[i];
31905b261ecSmrg	if ((gc->real_mods==0)&&(gc->vmods==0))
32005b261ecSmrg	    continue;
3214642e01fSmrg	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb,
32205b261ecSmrg							gc->real_mods,gc->vmods,
32305b261ecSmrg							XkbXKBFile));
32405b261ecSmrg    }
32505b261ecSmrg    if (xkb->indicators) {
32605b261ecSmrg	for (i=0;i<XkbNumIndicators;i++) {
32705b261ecSmrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
32805b261ecSmrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
32905b261ecSmrg		(map->which_mods!=0)||
33005b261ecSmrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
33105b261ecSmrg		(map->ctrls!=0)) {
3324642e01fSmrg		WriteXKBIndicatorMap(file,xkb,xkb->names->indicators[i],map,
33305b261ecSmrg								addOn,priv);
33405b261ecSmrg	    }
33505b261ecSmrg	}
33605b261ecSmrg    }
33705b261ecSmrg    if (addOn)
3384642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmCompatMapIndex,priv);
33905b261ecSmrg    fprintf(file,"};\n\n");
3406747b715Smrg    return TRUE;
34105b261ecSmrg}
34205b261ecSmrg
34305b261ecSmrgBool
34405b261ecSmrgXkbWriteXKBSymbols(	FILE *			file,
3454642e01fSmrg			XkbDescPtr              xkb,
34605b261ecSmrg			Bool			topLevel,
34705b261ecSmrg			Bool			showImplicit,
34805b261ecSmrg			XkbFileAddOnFunc	addOn,
34905b261ecSmrg			void *			priv)
35005b261ecSmrg{
35105b261ecSmrgregister unsigned	i,tmp;
35205b261ecSmrgXkbClientMapPtr		map;
35305b261ecSmrgXkbServerMapPtr		srv;
35405b261ecSmrgBool			showActions;
35505b261ecSmrg
3566747b715Smrg    if (!xkb) {
3576747b715Smrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
3586747b715Smrg	return FALSE;
3596747b715Smrg    }
3606747b715Smrg
36105b261ecSmrg    map= xkb->map;
3626747b715Smrg    if ((!map)||(!map->syms)||(!map->key_sym_map)) {
36305b261ecSmrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
3646747b715Smrg	return FALSE;
36505b261ecSmrg    }
36605b261ecSmrg    if ((!xkb->names)||(!xkb->names->keys)) {
36705b261ecSmrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
3686747b715Smrg	return FALSE;
36905b261ecSmrg    }
37005b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->symbols==None))
37105b261ecSmrg	 fprintf(file,"xkb_symbols {\n\n");
37205b261ecSmrg    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
3734642e01fSmrg			XkbAtomText(xkb->names->symbols,XkbXKBFile));
37405b261ecSmrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
37505b261ecSmrg	if (xkb->names->groups[i]!=None) {
37605b261ecSmrg	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
3774642e01fSmrg			XkbAtomText(xkb->names->groups[i],XkbXKBFile));
37805b261ecSmrg	    tmp++;
37905b261ecSmrg	}
38005b261ecSmrg    }
38105b261ecSmrg    if (tmp>0)
38205b261ecSmrg	fprintf(file,"\n");
3836747b715Smrg    srv= xkb->server;
38405b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
38505b261ecSmrg	Bool	simple;
38605b261ecSmrg	if ((int)XkbKeyNumSyms(xkb,i)<1)
38705b261ecSmrg	    continue;
3886747b715Smrg	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,TRUE)!=i)
38905b261ecSmrg	    continue;
3906747b715Smrg	simple= TRUE;
39105b261ecSmrg	fprintf(file,"    key %6s {",
39205b261ecSmrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
39305b261ecSmrg	if (srv->explicit) {
39405b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
39505b261ecSmrg	   						(showImplicit)) {
39605b261ecSmrg		int 	typeNdx,g;
39705b261ecSmrg		Bool	multi;
39805b261ecSmrg		char *	comment="  ";
39905b261ecSmrg
40005b261ecSmrg		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
40105b261ecSmrg		    comment= "//";
4026747b715Smrg		multi= FALSE;
40305b261ecSmrg		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
40405b261ecSmrg		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
40505b261ecSmrg		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
4066747b715Smrg			multi= TRUE;
40705b261ecSmrg		}
40805b261ecSmrg		if (multi) {
40905b261ecSmrg		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
41005b261ecSmrg			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
41105b261ecSmrg			if (srv->explicit[i]&(1<<g)) {
41205b261ecSmrg			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
41305b261ecSmrg			    	comment,g+1,
4144642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
41505b261ecSmrg			    	XkbXKBFile));
41605b261ecSmrg			}
41705b261ecSmrg			else if (showImplicit) {
41805b261ecSmrg			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
4194642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
42005b261ecSmrg			    	XkbXKBFile));
42105b261ecSmrg			}
42205b261ecSmrg		    }
42305b261ecSmrg		}
42405b261ecSmrg		else {
42505b261ecSmrg		    fprintf(file,"\n%s      type= \"%s\",",comment,
4264642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
42705b261ecSmrg			    	XkbXKBFile));
42805b261ecSmrg		}
4296747b715Smrg		simple= FALSE;
43005b261ecSmrg	    }
43105b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
43205b261ecSmrg		    					  (xkb->ctrls!=NULL)) {
43305b261ecSmrg		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
43405b261ecSmrg		     fprintf(file,"\n        repeat= Yes,");
43505b261ecSmrg		else fprintf(file,"\n        repeat= No,");
4366747b715Smrg		simple= FALSE;
43705b261ecSmrg	    }
43805b261ecSmrg	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
43905b261ecSmrg					(xkb->server->vmodmap[i]!=0)) {
44005b261ecSmrg		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
44105b261ecSmrg		    fprintf(file,"\n        virtualMods= %s,",
4424642e01fSmrg				XkbVModMaskText(xkb,0,
44305b261ecSmrg						xkb->server->vmodmap[i],
44405b261ecSmrg						XkbXKBFile));
44505b261ecSmrg		}
44605b261ecSmrg		else if (showImplicit) {
44705b261ecSmrg		    fprintf(file,"\n//      virtualMods= %s,",
4484642e01fSmrg				XkbVModMaskText(xkb,0,
44905b261ecSmrg						xkb->server->vmodmap[i],
45005b261ecSmrg						XkbXKBFile));
45105b261ecSmrg		}
45205b261ecSmrg	    }
45305b261ecSmrg	}
45405b261ecSmrg	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
45505b261ecSmrg	    case XkbClampIntoRange:
45605b261ecSmrg		fprintf(file,"\n        groupsClamp,");
45705b261ecSmrg		break;
45805b261ecSmrg	    case XkbRedirectIntoRange:
45905b261ecSmrg		fprintf(file,"\n        groupsRedirect= Group%d,",
46005b261ecSmrg			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
46105b261ecSmrg		break;
46205b261ecSmrg	}
46305b261ecSmrg	if (srv->behaviors!=NULL) {
46405b261ecSmrg	    unsigned type;
46505b261ecSmrg	    type= srv->behaviors[i].type&XkbKB_OpMask;
46605b261ecSmrg
46705b261ecSmrg	    if (type!=XkbKB_Default) {
4686747b715Smrg		simple= FALSE;
46905b261ecSmrg		fprintf(file,"\n        %s,",
47005b261ecSmrg			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
47105b261ecSmrg	    }
47205b261ecSmrg	}
47305b261ecSmrg	if ((srv->explicit==NULL) || showImplicit ||
47405b261ecSmrg	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
47505b261ecSmrg	     showActions= XkbKeyHasActions(xkb,i);
4766747b715Smrg	else showActions= FALSE;
47705b261ecSmrg
47805b261ecSmrg	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
4796747b715Smrg	    simple= FALSE;
48005b261ecSmrg	if (simple) {
48105b261ecSmrg	    KeySym *syms;
48205b261ecSmrg	    unsigned s;
48305b261ecSmrg
48405b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
48505b261ecSmrg	    fprintf(file,"         [ ");
48605b261ecSmrg	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
48705b261ecSmrg		if (s!=0)
48805b261ecSmrg		    fprintf(file,", ");
48905b261ecSmrg		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
49005b261ecSmrg	    }
49105b261ecSmrg	    fprintf(file," ] };\n");
49205b261ecSmrg	}
49305b261ecSmrg	else {
49405b261ecSmrg	    unsigned g,s;
49505b261ecSmrg	    KeySym *syms;
49605b261ecSmrg	    XkbAction *acts;
49705b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
49805b261ecSmrg	    acts= XkbKeyActionsPtr(xkb,i);
49905b261ecSmrg	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
50005b261ecSmrg		if (g!=0)
50105b261ecSmrg		    fprintf(file,",");
50205b261ecSmrg		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
50305b261ecSmrg		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
50405b261ecSmrg		    if (s!=0)
50505b261ecSmrg			fprintf(file,", ");
50605b261ecSmrg		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
50705b261ecSmrg		}
50805b261ecSmrg		fprintf(file," ]");
50905b261ecSmrg		syms+= XkbKeyGroupsWidth(xkb,i);
51005b261ecSmrg		if (showActions) {
51105b261ecSmrg		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
51205b261ecSmrg		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
51305b261ecSmrg			if (s!=0)
51405b261ecSmrg			    fprintf(file,", ");
5154642e01fSmrg			WriteXKBAction(file,xkb,(XkbAnyAction *)&acts[s]);
51605b261ecSmrg		    }
51705b261ecSmrg		    fprintf(file," ]");
51805b261ecSmrg		    acts+= XkbKeyGroupsWidth(xkb,i);
51905b261ecSmrg		}
52005b261ecSmrg	    }
52105b261ecSmrg	    fprintf(file,"\n    };\n");
52205b261ecSmrg	}
52305b261ecSmrg    }
52405b261ecSmrg    if (map && map->modmap) {
52505b261ecSmrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
52605b261ecSmrg	    if (map->modmap[i]!=0) {
52705b261ecSmrg		register int n,bit;
52805b261ecSmrg		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
52905b261ecSmrg		    if (map->modmap[i]&bit) {
53005b261ecSmrg			char buf[5];
53105b261ecSmrg			memcpy(buf,xkb->names->keys[i].name,4);
53205b261ecSmrg			buf[4]= '\0';
53305b261ecSmrg			fprintf(file,"    modifier_map %s { <%s> };\n",
53405b261ecSmrg					XkbModIndexText(n,XkbXKBFile),buf);
53505b261ecSmrg		    }
53605b261ecSmrg		}
53705b261ecSmrg	    }
53805b261ecSmrg	}
53905b261ecSmrg    }
54005b261ecSmrg    if (addOn)
5414642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv);
54205b261ecSmrg    fprintf(file,"};\n\n");
5436747b715Smrg    return TRUE;
54405b261ecSmrg}
54505b261ecSmrg
54605b261ecSmrgstatic Bool
54705b261ecSmrgWriteXKBOutline(	FILE *		file,
54805b261ecSmrg			XkbShapePtr	shape,
54905b261ecSmrg			XkbOutlinePtr	outline,
55005b261ecSmrg			int		lastRadius,
55105b261ecSmrg			int		first,
55205b261ecSmrg			int		indent)
55305b261ecSmrg{
55405b261ecSmrgregister int	i;
55505b261ecSmrgXkbPointPtr	pt;
55605b261ecSmrgchar *		iStr;
55705b261ecSmrg
55805b261ecSmrg    fprintf(file,"%s",iStr= XkbIndentText(first));
55905b261ecSmrg    if (first!=indent)
56005b261ecSmrg	iStr= XkbIndentText(indent);
56105b261ecSmrg    if (outline->corner_radius!=lastRadius) {
56205b261ecSmrg	fprintf(file,"corner= %s,",
56305b261ecSmrg			XkbGeomFPText(outline->corner_radius,XkbMessage));
56405b261ecSmrg	if (shape!=NULL) {
56505b261ecSmrg	    fprintf(file,"\n%s",iStr);
56605b261ecSmrg	}
56705b261ecSmrg    }
56805b261ecSmrg    if (shape) {
56905b261ecSmrg	if (outline==shape->approx)
57005b261ecSmrg	    fprintf(file,"approx= ");
57105b261ecSmrg	else if (outline==shape->primary)
57205b261ecSmrg	    fprintf(file,"primary= ");
57305b261ecSmrg    }
57405b261ecSmrg    fprintf(file,"{");
57505b261ecSmrg    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
57605b261ecSmrg	if (i==0)		fprintf(file," ");
57705b261ecSmrg	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
57805b261ecSmrg	else			fprintf(file,", ");
57905b261ecSmrg	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
58005b261ecSmrg				  XkbGeomFPText(pt->y,XkbXKBFile));
58105b261ecSmrg    }
58205b261ecSmrg    fprintf(file," }");
5836747b715Smrg    return TRUE;
58405b261ecSmrg}
58505b261ecSmrg
58605b261ecSmrgstatic Bool
58705b261ecSmrgWriteXKBDoodad(	FILE *		file,
58805b261ecSmrg		unsigned	indent,
58905b261ecSmrg		XkbGeometryPtr	geom,
59005b261ecSmrg		XkbDoodadPtr	doodad)
59105b261ecSmrg{
59205b261ecSmrgregister char *	i_str;
59305b261ecSmrgXkbShapePtr	shape;
59405b261ecSmrgXkbColorPtr	color;
59505b261ecSmrg
59605b261ecSmrg    i_str= XkbIndentText(indent);
59705b261ecSmrg    fprintf(file,"%s%s \"%s\" {\n",i_str,
59805b261ecSmrg				XkbDoodadTypeText(doodad->any.type,XkbMessage),
5994642e01fSmrg				XkbAtomText(doodad->any.name,XkbMessage));
60005b261ecSmrg    fprintf(file,"%s    top=      %s;\n",i_str,
60105b261ecSmrg				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
60205b261ecSmrg    fprintf(file,"%s    left=     %s;\n",i_str,
60305b261ecSmrg				XkbGeomFPText(doodad->any.left,XkbXKBFile));
60405b261ecSmrg    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
60505b261ecSmrg    switch (doodad->any.type) {
60605b261ecSmrg	case XkbOutlineDoodad:
60705b261ecSmrg	case XkbSolidDoodad:
60805b261ecSmrg	    if (doodad->shape.angle!=0) {
60905b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
61005b261ecSmrg			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
61105b261ecSmrg	    }
61205b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
61305b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
61405b261ecSmrg			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
61505b261ecSmrg	    }
61605b261ecSmrg	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
61705b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6184642e01fSmrg			    XkbAtomText(shape->name,XkbXKBFile));
61905b261ecSmrg	    break;
62005b261ecSmrg	case XkbTextDoodad:
62105b261ecSmrg	    if (doodad->text.angle!=0) {
62205b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
62305b261ecSmrg			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
62405b261ecSmrg	    }
62505b261ecSmrg	    if (doodad->text.width!=0) {
62605b261ecSmrg		fprintf(file,"%s    width=  %s;\n",i_str,
62705b261ecSmrg			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
62805b261ecSmrg
62905b261ecSmrg	    }
63005b261ecSmrg	    if (doodad->text.height!=0) {
63105b261ecSmrg		fprintf(file,"%s    height=  %s;\n",i_str,
63205b261ecSmrg			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
63305b261ecSmrg
63405b261ecSmrg	    }
63505b261ecSmrg	    if (doodad->text.color_ndx!=0) {
63605b261ecSmrg		color= XkbTextDoodadColor(geom,&doodad->text);
63705b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
63805b261ecSmrg			     XkbStringText(color->spec,XkbXKBFile));
63905b261ecSmrg	    }
64005b261ecSmrg	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
64105b261ecSmrg	    		     XkbStringText(doodad->text.font,XkbXKBFile));
64205b261ecSmrg	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
64305b261ecSmrg	    		    XkbStringText(doodad->text.text,XkbXKBFile));
64405b261ecSmrg	    break;
64505b261ecSmrg	case XkbIndicatorDoodad:
64605b261ecSmrg	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
64705b261ecSmrg	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
64805b261ecSmrg	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
64905b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
65005b261ecSmrg	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
65105b261ecSmrg	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
65205b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
65305b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6544642e01fSmrg			     XkbAtomText(shape->name,XkbXKBFile));
65505b261ecSmrg	    break;
65605b261ecSmrg	case XkbLogoDoodad:
65705b261ecSmrg	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
65805b261ecSmrg			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
65905b261ecSmrg	    if (doodad->shape.angle!=0) {
66005b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
66105b261ecSmrg			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
66205b261ecSmrg	    }
66305b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
66405b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
66505b261ecSmrg			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
66605b261ecSmrg	    }
66705b261ecSmrg	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
66805b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6694642e01fSmrg			    XkbAtomText(shape->name,XkbXKBFile));
67005b261ecSmrg	    break;
67105b261ecSmrg    }
67205b261ecSmrg    fprintf(file,"%s};\n",i_str);
6736747b715Smrg    return TRUE;
67405b261ecSmrg}
67505b261ecSmrg
67605b261ecSmrg/*ARGSUSED*/
67705b261ecSmrgstatic Bool
67805b261ecSmrgWriteXKBOverlay(	FILE *		file,
67905b261ecSmrg			unsigned	indent,
68005b261ecSmrg			XkbGeometryPtr	geom,
68105b261ecSmrg			XkbOverlayPtr	ol)
68205b261ecSmrg{
68305b261ecSmrgregister char *		i_str;
68405b261ecSmrgint			r,k,nOut;
68505b261ecSmrgXkbOverlayRowPtr	row;
68605b261ecSmrgXkbOverlayKeyPtr	key;
68705b261ecSmrg
68805b261ecSmrg    i_str= XkbIndentText(indent);
68905b261ecSmrg    if (ol->name!=None) {
69005b261ecSmrg	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
6914642e01fSmrg    					XkbAtomText(ol->name,XkbMessage));
69205b261ecSmrg    }
69305b261ecSmrg    else fprintf(file,"%soverlay {\n",i_str);
69405b261ecSmrg    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
69505b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
69605b261ecSmrg	    char *over,*under;
69705b261ecSmrg	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
69805b261ecSmrg	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
69905b261ecSmrg	    if (nOut==0)
70005b261ecSmrg		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
70105b261ecSmrg	    else if ((nOut%4)==0)
70205b261ecSmrg		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
70305b261ecSmrg	    else fprintf(file,", %6s=%6s",under,over);
70405b261ecSmrg	    nOut++;
70505b261ecSmrg	}
70605b261ecSmrg    }
70705b261ecSmrg    fprintf(file,"\n%s};\n",i_str);
7086747b715Smrg    return TRUE;
70905b261ecSmrg}
71005b261ecSmrg
71105b261ecSmrgstatic Bool
71205b261ecSmrgWriteXKBSection(	FILE *		file,
71305b261ecSmrg			XkbSectionPtr 	s,
71405b261ecSmrg			XkbGeometryPtr	geom)
71505b261ecSmrg{
71605b261ecSmrgregister int	i;
71705b261ecSmrgXkbRowPtr	row;
71805b261ecSmrgint		dfltKeyColor = 0;
71905b261ecSmrg
72005b261ecSmrg    fprintf(file,"    section \"%s\" {\n",
7214642e01fSmrg				XkbAtomText(s->name,XkbXKBFile));
72205b261ecSmrg    if (s->rows&&(s->rows->num_keys>0)) {
72305b261ecSmrg	dfltKeyColor= s->rows->keys[0].color_ndx;
72405b261ecSmrg	fprintf(file,"        key.color= \"%s\";\n",
72505b261ecSmrg		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
72605b261ecSmrg    }
72705b261ecSmrg    fprintf(file,"        priority=  %d;\n",s->priority);
72805b261ecSmrg    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
72905b261ecSmrg    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
73005b261ecSmrg    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
73105b261ecSmrg    fprintf(file,"        height=    %s;\n",
73205b261ecSmrg					XkbGeomFPText(s->height,XkbXKBFile));
73305b261ecSmrg    if (s->angle!=0) {
73405b261ecSmrg	fprintf(file,"        angle=  %s;\n",
73505b261ecSmrg					XkbGeomFPText(s->angle,XkbXKBFile));
73605b261ecSmrg    }
73705b261ecSmrg    for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
73805b261ecSmrg	fprintf(file,"        row {\n");
73905b261ecSmrg	fprintf(file,"            top=  %s;\n",
74005b261ecSmrg					XkbGeomFPText(row->top,XkbXKBFile));
74105b261ecSmrg	fprintf(file,"            left= %s;\n",
74205b261ecSmrg					XkbGeomFPText(row->left,XkbXKBFile));
74305b261ecSmrg	if (row->vertical)
74405b261ecSmrg	    fprintf(file,"            vertical;\n");
74505b261ecSmrg	if (row->num_keys>0) {
74605b261ecSmrg	    register int 	k;
74705b261ecSmrg	    register XkbKeyPtr	key;
74805b261ecSmrg	    int			forceNL=0;
74905b261ecSmrg	    int			nThisLine= 0;
75005b261ecSmrg	    fprintf(file,"            keys {\n");
75105b261ecSmrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
75205b261ecSmrg		XkbShapePtr	shape;
75305b261ecSmrg		if (key->color_ndx!=dfltKeyColor)
75405b261ecSmrg		    forceNL= 1;
75505b261ecSmrg		if (k==0) {
75605b261ecSmrg		     fprintf(file,"                ");
75705b261ecSmrg		     nThisLine= 0;
75805b261ecSmrg		}
75905b261ecSmrg		else if (((nThisLine%2)==1)||(forceNL)) {
76005b261ecSmrg		     fprintf(file,",\n                ");
76105b261ecSmrg		     forceNL= nThisLine= 0;
76205b261ecSmrg		}
76305b261ecSmrg		else {
76405b261ecSmrg		     fprintf(file,", ");
76505b261ecSmrg		     nThisLine++;
76605b261ecSmrg		}
76705b261ecSmrg		shape= XkbKeyShape(geom,key);
76805b261ecSmrg		fprintf(file,"{ %6s, \"%s\", %3s",
76905b261ecSmrg		      XkbKeyNameText(key->name.name,XkbXKBFile),
7704642e01fSmrg		      XkbAtomText(shape->name,XkbXKBFile),
77105b261ecSmrg		      XkbGeomFPText(key->gap,XkbXKBFile));
77205b261ecSmrg		if (key->color_ndx!=dfltKeyColor) {
77305b261ecSmrg		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
77405b261ecSmrg		    forceNL= 1;
77505b261ecSmrg		}
77605b261ecSmrg		fprintf(file," }");
77705b261ecSmrg	    }
77805b261ecSmrg	    fprintf(file,"\n            };\n");
77905b261ecSmrg	}
78005b261ecSmrg	fprintf(file,"        };\n");
78105b261ecSmrg    }
78205b261ecSmrg    if (s->doodads!=NULL) {
78305b261ecSmrg	XkbDoodadPtr	doodad;
78405b261ecSmrg	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
7854642e01fSmrg	    WriteXKBDoodad(file,8,geom,doodad);
78605b261ecSmrg	}
78705b261ecSmrg    }
78805b261ecSmrg    if (s->overlays!=NULL) {
78905b261ecSmrg	XkbOverlayPtr	ol;
79005b261ecSmrg	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
7914642e01fSmrg	    WriteXKBOverlay(file,8,geom,ol);
79205b261ecSmrg	}
79305b261ecSmrg    }
79405b261ecSmrg    fprintf(file,"    }; // End of \"%s\" section\n\n",
7954642e01fSmrg				XkbAtomText(s->name,XkbXKBFile));
7966747b715Smrg    return TRUE;
79705b261ecSmrg}
79805b261ecSmrg
79905b261ecSmrgBool
80005b261ecSmrgXkbWriteXKBGeometry(	FILE *			file,
8014642e01fSmrg			XkbDescPtr              xkb,
80205b261ecSmrg			Bool			topLevel,
80305b261ecSmrg			Bool			showImplicit,
80405b261ecSmrg			XkbFileAddOnFunc	addOn,
80505b261ecSmrg			void *			priv)
80605b261ecSmrg{
80705b261ecSmrgregister unsigned	i,n;
80805b261ecSmrgXkbGeometryPtr		geom;
80905b261ecSmrg
81005b261ecSmrg    if ((!xkb)||(!xkb->geom)) {
81105b261ecSmrg	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
8126747b715Smrg	return FALSE;
81305b261ecSmrg    }
81405b261ecSmrg    geom= xkb->geom;
81505b261ecSmrg    if (geom->name==None)
81605b261ecSmrg	 fprintf(file,"xkb_geometry {\n\n");
81705b261ecSmrg    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
8184642e01fSmrg				XkbAtomText(geom->name,XkbXKBFile));
81905b261ecSmrg    fprintf(file,"    width=       %s;\n",
82005b261ecSmrg				XkbGeomFPText(geom->width_mm,XkbXKBFile));
82105b261ecSmrg    fprintf(file,"    height=      %s;\n\n",
82205b261ecSmrg				XkbGeomFPText(geom->height_mm,XkbXKBFile));
82305b261ecSmrg
82405b261ecSmrg    if (geom->key_aliases!=NULL) {
82505b261ecSmrg	XkbKeyAliasPtr	pAl;
82605b261ecSmrg	pAl= geom->key_aliases;
82705b261ecSmrg	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
82805b261ecSmrg	    fprintf(file,"    alias %6s = %6s;\n",
82905b261ecSmrg				XkbKeyNameText(pAl->alias,XkbXKBFile),
83005b261ecSmrg				XkbKeyNameText(pAl->real,XkbXKBFile));
83105b261ecSmrg	}
83205b261ecSmrg	fprintf(file,"\n");
83305b261ecSmrg    }
83405b261ecSmrg
83505b261ecSmrg    if (geom->base_color!=NULL)
83605b261ecSmrg	fprintf(file,"    baseColor=   \"%s\";\n",
83705b261ecSmrg			XkbStringText(geom->base_color->spec,XkbXKBFile));
83805b261ecSmrg    if (geom->label_color!=NULL)
83905b261ecSmrg	fprintf(file,"    labelColor=  \"%s\";\n",
84005b261ecSmrg			XkbStringText(geom->label_color->spec,XkbXKBFile));
84105b261ecSmrg    if (geom->label_font!=NULL)
84205b261ecSmrg	fprintf(file,"    xfont=       \"%s\";\n",
84305b261ecSmrg			XkbStringText(geom->label_font,XkbXKBFile));
84405b261ecSmrg    if ((geom->num_colors>0)&&(showImplicit)) {
84505b261ecSmrg	XkbColorPtr	color;
84605b261ecSmrg	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
84705b261ecSmrg		fprintf(file,"//     color[%d]= \"%s\"\n",i,
84805b261ecSmrg				XkbStringText(color->spec,XkbXKBFile));
84905b261ecSmrg	}
85005b261ecSmrg	fprintf(file,"\n");
85105b261ecSmrg    }
85205b261ecSmrg    if (geom->num_properties>0) {
85305b261ecSmrg	XkbPropertyPtr	prop;
85405b261ecSmrg	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
85505b261ecSmrg	    fprintf(file,"    %s= \"%s\";\n",prop->name,
85605b261ecSmrg    				XkbStringText(prop->value,XkbXKBFile));
85705b261ecSmrg	}
85805b261ecSmrg	fprintf(file,"\n");
85905b261ecSmrg    }
86005b261ecSmrg    if (geom->num_shapes>0) {
86105b261ecSmrg	XkbShapePtr	shape;
86205b261ecSmrg	XkbOutlinePtr	outline;
86305b261ecSmrg	int		lastR;
86405b261ecSmrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
86505b261ecSmrg	    lastR=0;
86605b261ecSmrg	    fprintf(file,"    shape \"%s\" {",
8674642e01fSmrg				   XkbAtomText(shape->name,XkbXKBFile));
86805b261ecSmrg	    outline= shape->outlines;
86905b261ecSmrg	    if (shape->num_outlines>1) {
87005b261ecSmrg		for (n=0;n<shape->num_outlines;n++,outline++) {
87105b261ecSmrg		    if (n==0)	fprintf(file,"\n");
87205b261ecSmrg		    else	fprintf(file,",\n");
87305b261ecSmrg		    WriteXKBOutline(file,shape,outline,lastR,8,8);
87405b261ecSmrg		    lastR= outline->corner_radius;
87505b261ecSmrg		}
87605b261ecSmrg		fprintf(file,"\n    };\n");
87705b261ecSmrg	    }
87805b261ecSmrg	    else {
87905b261ecSmrg		WriteXKBOutline(file,NULL,outline,lastR,1,8);
88005b261ecSmrg		fprintf(file," };\n");
88105b261ecSmrg	    }
88205b261ecSmrg	}
88305b261ecSmrg    }
88405b261ecSmrg    if (geom->num_sections>0) {
88505b261ecSmrg	XkbSectionPtr	section;
88605b261ecSmrg	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
8874642e01fSmrg	    WriteXKBSection(file,section,geom);
88805b261ecSmrg	}
88905b261ecSmrg    }
89005b261ecSmrg    if (geom->num_doodads>0) {
89105b261ecSmrg	XkbDoodadPtr	doodad;
89205b261ecSmrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
8934642e01fSmrg	    WriteXKBDoodad(file,4,geom,doodad);
89405b261ecSmrg	}
89505b261ecSmrg    }
89605b261ecSmrg    if (addOn)
8974642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmGeometryIndex,priv);
89805b261ecSmrg    fprintf(file,"};\n\n");
8996747b715Smrg    return TRUE;
90005b261ecSmrg}
901