xkbout.c revision 4642e01f
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"
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)
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,",");
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");
8705b261ecSmrg    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));
9605b261ecSmrg    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);
11505b261ecSmrg	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') {
12605b261ecSmrg	    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");
15805b261ecSmrg    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);
17505b261ecSmrg	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");
22405b261ecSmrg    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
2364642e01fSmrg    fprintf(file,"    indicator \"%s\" {\n",XkbAtomGetString(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)
2634642e01fSmrg	(*addOn)(file,xkb,False,True,XkmIndicatorsIndex,priv);
26405b261ecSmrg    fprintf(file,"    };\n");
26505b261ecSmrg    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);
28105b261ecSmrg	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");
29105b261ecSmrg    fprintf(file,"    interpret.repeat= False;\n");
29205b261ecSmrg    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)
30705b261ecSmrg	    fprintf(file,"        locking= True;\n");
30805b261ecSmrg	if (interp->flags&XkbSI_AutoRepeat)
30905b261ecSmrg	    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");
34005b261ecSmrg    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
35605b261ecSmrg    map= xkb->map;
35705b261ecSmrg    srv= xkb->server;
35805b261ecSmrg    if ((!xkb)||(!map)||(!map->syms)||(!map->key_sym_map)) {
35905b261ecSmrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
36005b261ecSmrg	return False;
36105b261ecSmrg    }
36205b261ecSmrg    if ((!xkb->names)||(!xkb->names->keys)) {
36305b261ecSmrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
36405b261ecSmrg	return False;
36505b261ecSmrg    }
36605b261ecSmrg    if ((xkb->names==NULL)||(xkb->names->symbols==None))
36705b261ecSmrg	 fprintf(file,"xkb_symbols {\n\n");
36805b261ecSmrg    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
3694642e01fSmrg			XkbAtomText(xkb->names->symbols,XkbXKBFile));
37005b261ecSmrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
37105b261ecSmrg	if (xkb->names->groups[i]!=None) {
37205b261ecSmrg	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
3734642e01fSmrg			XkbAtomText(xkb->names->groups[i],XkbXKBFile));
37405b261ecSmrg	    tmp++;
37505b261ecSmrg	}
37605b261ecSmrg    }
37705b261ecSmrg    if (tmp>0)
37805b261ecSmrg	fprintf(file,"\n");
37905b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
38005b261ecSmrg	Bool	simple;
38105b261ecSmrg	if ((int)XkbKeyNumSyms(xkb,i)<1)
38205b261ecSmrg	    continue;
38305b261ecSmrg	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
38405b261ecSmrg	    continue;
38505b261ecSmrg	simple= True;
38605b261ecSmrg	fprintf(file,"    key %6s {",
38705b261ecSmrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
38805b261ecSmrg	if (srv->explicit) {
38905b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
39005b261ecSmrg	   						(showImplicit)) {
39105b261ecSmrg		int 	typeNdx,g;
39205b261ecSmrg		Bool	multi;
39305b261ecSmrg		char *	comment="  ";
39405b261ecSmrg
39505b261ecSmrg		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
39605b261ecSmrg		    comment= "//";
39705b261ecSmrg		multi= False;
39805b261ecSmrg		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
39905b261ecSmrg		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
40005b261ecSmrg		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
40105b261ecSmrg			multi= True;
40205b261ecSmrg		}
40305b261ecSmrg		if (multi) {
40405b261ecSmrg		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
40505b261ecSmrg			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
40605b261ecSmrg			if (srv->explicit[i]&(1<<g)) {
40705b261ecSmrg			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
40805b261ecSmrg			    	comment,g+1,
4094642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
41005b261ecSmrg			    	XkbXKBFile));
41105b261ecSmrg			}
41205b261ecSmrg			else if (showImplicit) {
41305b261ecSmrg			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
4144642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
41505b261ecSmrg			    	XkbXKBFile));
41605b261ecSmrg			}
41705b261ecSmrg		    }
41805b261ecSmrg		}
41905b261ecSmrg		else {
42005b261ecSmrg		    fprintf(file,"\n%s      type= \"%s\",",comment,
4214642e01fSmrg				XkbAtomText(map->types[typeNdx].name,
42205b261ecSmrg			    	XkbXKBFile));
42305b261ecSmrg		}
42405b261ecSmrg		simple= False;
42505b261ecSmrg	    }
42605b261ecSmrg	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
42705b261ecSmrg		    					  (xkb->ctrls!=NULL)) {
42805b261ecSmrg		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
42905b261ecSmrg		     fprintf(file,"\n        repeat= Yes,");
43005b261ecSmrg		else fprintf(file,"\n        repeat= No,");
43105b261ecSmrg		simple= False;
43205b261ecSmrg	    }
43305b261ecSmrg	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
43405b261ecSmrg					(xkb->server->vmodmap[i]!=0)) {
43505b261ecSmrg		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
43605b261ecSmrg		    fprintf(file,"\n        virtualMods= %s,",
4374642e01fSmrg				XkbVModMaskText(xkb,0,
43805b261ecSmrg						xkb->server->vmodmap[i],
43905b261ecSmrg						XkbXKBFile));
44005b261ecSmrg		}
44105b261ecSmrg		else if (showImplicit) {
44205b261ecSmrg		    fprintf(file,"\n//      virtualMods= %s,",
4434642e01fSmrg				XkbVModMaskText(xkb,0,
44405b261ecSmrg						xkb->server->vmodmap[i],
44505b261ecSmrg						XkbXKBFile));
44605b261ecSmrg		}
44705b261ecSmrg	    }
44805b261ecSmrg	}
44905b261ecSmrg	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
45005b261ecSmrg	    case XkbClampIntoRange:
45105b261ecSmrg		fprintf(file,"\n        groupsClamp,");
45205b261ecSmrg		break;
45305b261ecSmrg	    case XkbRedirectIntoRange:
45405b261ecSmrg		fprintf(file,"\n        groupsRedirect= Group%d,",
45505b261ecSmrg			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
45605b261ecSmrg		break;
45705b261ecSmrg	}
45805b261ecSmrg	if (srv->behaviors!=NULL) {
45905b261ecSmrg	    unsigned type;
46005b261ecSmrg	    type= srv->behaviors[i].type&XkbKB_OpMask;
46105b261ecSmrg
46205b261ecSmrg	    if (type!=XkbKB_Default) {
46305b261ecSmrg		simple= False;
46405b261ecSmrg		fprintf(file,"\n        %s,",
46505b261ecSmrg			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
46605b261ecSmrg	    }
46705b261ecSmrg	}
46805b261ecSmrg	if ((srv->explicit==NULL) || showImplicit ||
46905b261ecSmrg	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
47005b261ecSmrg	     showActions= XkbKeyHasActions(xkb,i);
47105b261ecSmrg	else showActions= False;
47205b261ecSmrg
47305b261ecSmrg	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
47405b261ecSmrg	    simple= False;
47505b261ecSmrg	if (simple) {
47605b261ecSmrg	    KeySym *syms;
47705b261ecSmrg	    unsigned s;
47805b261ecSmrg
47905b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
48005b261ecSmrg	    fprintf(file,"         [ ");
48105b261ecSmrg	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
48205b261ecSmrg		if (s!=0)
48305b261ecSmrg		    fprintf(file,", ");
48405b261ecSmrg		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
48505b261ecSmrg	    }
48605b261ecSmrg	    fprintf(file," ] };\n");
48705b261ecSmrg	}
48805b261ecSmrg	else {
48905b261ecSmrg	    unsigned g,s;
49005b261ecSmrg	    KeySym *syms;
49105b261ecSmrg	    XkbAction *acts;
49205b261ecSmrg	    syms= XkbKeySymsPtr(xkb,i);
49305b261ecSmrg	    acts= XkbKeyActionsPtr(xkb,i);
49405b261ecSmrg	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
49505b261ecSmrg		if (g!=0)
49605b261ecSmrg		    fprintf(file,",");
49705b261ecSmrg		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
49805b261ecSmrg		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
49905b261ecSmrg		    if (s!=0)
50005b261ecSmrg			fprintf(file,", ");
50105b261ecSmrg		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
50205b261ecSmrg		}
50305b261ecSmrg		fprintf(file," ]");
50405b261ecSmrg		syms+= XkbKeyGroupsWidth(xkb,i);
50505b261ecSmrg		if (showActions) {
50605b261ecSmrg		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
50705b261ecSmrg		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
50805b261ecSmrg			if (s!=0)
50905b261ecSmrg			    fprintf(file,", ");
5104642e01fSmrg			WriteXKBAction(file,xkb,(XkbAnyAction *)&acts[s]);
51105b261ecSmrg		    }
51205b261ecSmrg		    fprintf(file," ]");
51305b261ecSmrg		    acts+= XkbKeyGroupsWidth(xkb,i);
51405b261ecSmrg		}
51505b261ecSmrg	    }
51605b261ecSmrg	    fprintf(file,"\n    };\n");
51705b261ecSmrg	}
51805b261ecSmrg    }
51905b261ecSmrg    if (map && map->modmap) {
52005b261ecSmrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
52105b261ecSmrg	    if (map->modmap[i]!=0) {
52205b261ecSmrg		register int n,bit;
52305b261ecSmrg		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
52405b261ecSmrg		    if (map->modmap[i]&bit) {
52505b261ecSmrg			char buf[5];
52605b261ecSmrg			memcpy(buf,xkb->names->keys[i].name,4);
52705b261ecSmrg			buf[4]= '\0';
52805b261ecSmrg			fprintf(file,"    modifier_map %s { <%s> };\n",
52905b261ecSmrg					XkbModIndexText(n,XkbXKBFile),buf);
53005b261ecSmrg		    }
53105b261ecSmrg		}
53205b261ecSmrg	    }
53305b261ecSmrg	}
53405b261ecSmrg    }
53505b261ecSmrg    if (addOn)
5364642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv);
53705b261ecSmrg    fprintf(file,"};\n\n");
53805b261ecSmrg    return True;
53905b261ecSmrg}
54005b261ecSmrg
54105b261ecSmrgstatic Bool
54205b261ecSmrgWriteXKBOutline(	FILE *		file,
54305b261ecSmrg			XkbShapePtr	shape,
54405b261ecSmrg			XkbOutlinePtr	outline,
54505b261ecSmrg			int		lastRadius,
54605b261ecSmrg			int		first,
54705b261ecSmrg			int		indent)
54805b261ecSmrg{
54905b261ecSmrgregister int	i;
55005b261ecSmrgXkbPointPtr	pt;
55105b261ecSmrgchar *		iStr;
55205b261ecSmrg
55305b261ecSmrg    fprintf(file,"%s",iStr= XkbIndentText(first));
55405b261ecSmrg    if (first!=indent)
55505b261ecSmrg	iStr= XkbIndentText(indent);
55605b261ecSmrg    if (outline->corner_radius!=lastRadius) {
55705b261ecSmrg	fprintf(file,"corner= %s,",
55805b261ecSmrg			XkbGeomFPText(outline->corner_radius,XkbMessage));
55905b261ecSmrg	if (shape!=NULL) {
56005b261ecSmrg	    fprintf(file,"\n%s",iStr);
56105b261ecSmrg	}
56205b261ecSmrg    }
56305b261ecSmrg    if (shape) {
56405b261ecSmrg	if (outline==shape->approx)
56505b261ecSmrg	    fprintf(file,"approx= ");
56605b261ecSmrg	else if (outline==shape->primary)
56705b261ecSmrg	    fprintf(file,"primary= ");
56805b261ecSmrg    }
56905b261ecSmrg    fprintf(file,"{");
57005b261ecSmrg    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
57105b261ecSmrg	if (i==0)		fprintf(file," ");
57205b261ecSmrg	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
57305b261ecSmrg	else			fprintf(file,", ");
57405b261ecSmrg	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
57505b261ecSmrg				  XkbGeomFPText(pt->y,XkbXKBFile));
57605b261ecSmrg    }
57705b261ecSmrg    fprintf(file," }");
57805b261ecSmrg    return True;
57905b261ecSmrg}
58005b261ecSmrg
58105b261ecSmrgstatic Bool
58205b261ecSmrgWriteXKBDoodad(	FILE *		file,
58305b261ecSmrg		unsigned	indent,
58405b261ecSmrg		XkbGeometryPtr	geom,
58505b261ecSmrg		XkbDoodadPtr	doodad)
58605b261ecSmrg{
58705b261ecSmrgregister char *	i_str;
58805b261ecSmrgXkbShapePtr	shape;
58905b261ecSmrgXkbColorPtr	color;
59005b261ecSmrg
59105b261ecSmrg    i_str= XkbIndentText(indent);
59205b261ecSmrg    fprintf(file,"%s%s \"%s\" {\n",i_str,
59305b261ecSmrg				XkbDoodadTypeText(doodad->any.type,XkbMessage),
5944642e01fSmrg				XkbAtomText(doodad->any.name,XkbMessage));
59505b261ecSmrg    fprintf(file,"%s    top=      %s;\n",i_str,
59605b261ecSmrg				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
59705b261ecSmrg    fprintf(file,"%s    left=     %s;\n",i_str,
59805b261ecSmrg				XkbGeomFPText(doodad->any.left,XkbXKBFile));
59905b261ecSmrg    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
60005b261ecSmrg    switch (doodad->any.type) {
60105b261ecSmrg	case XkbOutlineDoodad:
60205b261ecSmrg	case XkbSolidDoodad:
60305b261ecSmrg	    if (doodad->shape.angle!=0) {
60405b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
60505b261ecSmrg			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
60605b261ecSmrg	    }
60705b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
60805b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
60905b261ecSmrg			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
61005b261ecSmrg	    }
61105b261ecSmrg	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
61205b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6134642e01fSmrg			    XkbAtomText(shape->name,XkbXKBFile));
61405b261ecSmrg	    break;
61505b261ecSmrg	case XkbTextDoodad:
61605b261ecSmrg	    if (doodad->text.angle!=0) {
61705b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
61805b261ecSmrg			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
61905b261ecSmrg	    }
62005b261ecSmrg	    if (doodad->text.width!=0) {
62105b261ecSmrg		fprintf(file,"%s    width=  %s;\n",i_str,
62205b261ecSmrg			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
62305b261ecSmrg
62405b261ecSmrg	    }
62505b261ecSmrg	    if (doodad->text.height!=0) {
62605b261ecSmrg		fprintf(file,"%s    height=  %s;\n",i_str,
62705b261ecSmrg			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
62805b261ecSmrg
62905b261ecSmrg	    }
63005b261ecSmrg	    if (doodad->text.color_ndx!=0) {
63105b261ecSmrg		color= XkbTextDoodadColor(geom,&doodad->text);
63205b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
63305b261ecSmrg			     XkbStringText(color->spec,XkbXKBFile));
63405b261ecSmrg	    }
63505b261ecSmrg	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
63605b261ecSmrg	    		     XkbStringText(doodad->text.font,XkbXKBFile));
63705b261ecSmrg	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
63805b261ecSmrg	    		    XkbStringText(doodad->text.text,XkbXKBFile));
63905b261ecSmrg	    break;
64005b261ecSmrg	case XkbIndicatorDoodad:
64105b261ecSmrg	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
64205b261ecSmrg	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
64305b261ecSmrg	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
64405b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
64505b261ecSmrg	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
64605b261ecSmrg	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
64705b261ecSmrg	    		    XkbStringText(color->spec,XkbXKBFile));
64805b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6494642e01fSmrg			     XkbAtomText(shape->name,XkbXKBFile));
65005b261ecSmrg	    break;
65105b261ecSmrg	case XkbLogoDoodad:
65205b261ecSmrg	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
65305b261ecSmrg			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
65405b261ecSmrg	    if (doodad->shape.angle!=0) {
65505b261ecSmrg		fprintf(file,"%s    angle=  %s;\n",i_str,
65605b261ecSmrg			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
65705b261ecSmrg	    }
65805b261ecSmrg	    if (doodad->shape.color_ndx!=0) {
65905b261ecSmrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
66005b261ecSmrg			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
66105b261ecSmrg	    }
66205b261ecSmrg	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
66305b261ecSmrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
6644642e01fSmrg			    XkbAtomText(shape->name,XkbXKBFile));
66505b261ecSmrg	    break;
66605b261ecSmrg    }
66705b261ecSmrg    fprintf(file,"%s};\n",i_str);
66805b261ecSmrg    return True;
66905b261ecSmrg}
67005b261ecSmrg
67105b261ecSmrg/*ARGSUSED*/
67205b261ecSmrgstatic Bool
67305b261ecSmrgWriteXKBOverlay(	FILE *		file,
67405b261ecSmrg			unsigned	indent,
67505b261ecSmrg			XkbGeometryPtr	geom,
67605b261ecSmrg			XkbOverlayPtr	ol)
67705b261ecSmrg{
67805b261ecSmrgregister char *		i_str;
67905b261ecSmrgint			r,k,nOut;
68005b261ecSmrgXkbOverlayRowPtr	row;
68105b261ecSmrgXkbOverlayKeyPtr	key;
68205b261ecSmrg
68305b261ecSmrg    i_str= XkbIndentText(indent);
68405b261ecSmrg    if (ol->name!=None) {
68505b261ecSmrg	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
6864642e01fSmrg    					XkbAtomText(ol->name,XkbMessage));
68705b261ecSmrg    }
68805b261ecSmrg    else fprintf(file,"%soverlay {\n",i_str);
68905b261ecSmrg    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
69005b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
69105b261ecSmrg	    char *over,*under;
69205b261ecSmrg	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
69305b261ecSmrg	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
69405b261ecSmrg	    if (nOut==0)
69505b261ecSmrg		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
69605b261ecSmrg	    else if ((nOut%4)==0)
69705b261ecSmrg		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
69805b261ecSmrg	    else fprintf(file,", %6s=%6s",under,over);
69905b261ecSmrg	    nOut++;
70005b261ecSmrg	}
70105b261ecSmrg    }
70205b261ecSmrg    fprintf(file,"\n%s};\n",i_str);
70305b261ecSmrg    return True;
70405b261ecSmrg}
70505b261ecSmrg
70605b261ecSmrgstatic Bool
70705b261ecSmrgWriteXKBSection(	FILE *		file,
70805b261ecSmrg			XkbSectionPtr 	s,
70905b261ecSmrg			XkbGeometryPtr	geom)
71005b261ecSmrg{
71105b261ecSmrgregister int	i;
71205b261ecSmrgXkbRowPtr	row;
71305b261ecSmrgint		dfltKeyColor = 0;
71405b261ecSmrg
71505b261ecSmrg    fprintf(file,"    section \"%s\" {\n",
7164642e01fSmrg				XkbAtomText(s->name,XkbXKBFile));
71705b261ecSmrg    if (s->rows&&(s->rows->num_keys>0)) {
71805b261ecSmrg	dfltKeyColor= s->rows->keys[0].color_ndx;
71905b261ecSmrg	fprintf(file,"        key.color= \"%s\";\n",
72005b261ecSmrg		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
72105b261ecSmrg    }
72205b261ecSmrg    fprintf(file,"        priority=  %d;\n",s->priority);
72305b261ecSmrg    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
72405b261ecSmrg    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
72505b261ecSmrg    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
72605b261ecSmrg    fprintf(file,"        height=    %s;\n",
72705b261ecSmrg					XkbGeomFPText(s->height,XkbXKBFile));
72805b261ecSmrg    if (s->angle!=0) {
72905b261ecSmrg	fprintf(file,"        angle=  %s;\n",
73005b261ecSmrg					XkbGeomFPText(s->angle,XkbXKBFile));
73105b261ecSmrg    }
73205b261ecSmrg    for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
73305b261ecSmrg	fprintf(file,"        row {\n");
73405b261ecSmrg	fprintf(file,"            top=  %s;\n",
73505b261ecSmrg					XkbGeomFPText(row->top,XkbXKBFile));
73605b261ecSmrg	fprintf(file,"            left= %s;\n",
73705b261ecSmrg					XkbGeomFPText(row->left,XkbXKBFile));
73805b261ecSmrg	if (row->vertical)
73905b261ecSmrg	    fprintf(file,"            vertical;\n");
74005b261ecSmrg	if (row->num_keys>0) {
74105b261ecSmrg	    register int 	k;
74205b261ecSmrg	    register XkbKeyPtr	key;
74305b261ecSmrg	    int			forceNL=0;
74405b261ecSmrg	    int			nThisLine= 0;
74505b261ecSmrg	    fprintf(file,"            keys {\n");
74605b261ecSmrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
74705b261ecSmrg		XkbShapePtr	shape;
74805b261ecSmrg		if (key->color_ndx!=dfltKeyColor)
74905b261ecSmrg		    forceNL= 1;
75005b261ecSmrg		if (k==0) {
75105b261ecSmrg		     fprintf(file,"                ");
75205b261ecSmrg		     nThisLine= 0;
75305b261ecSmrg		}
75405b261ecSmrg		else if (((nThisLine%2)==1)||(forceNL)) {
75505b261ecSmrg		     fprintf(file,",\n                ");
75605b261ecSmrg		     forceNL= nThisLine= 0;
75705b261ecSmrg		}
75805b261ecSmrg		else {
75905b261ecSmrg		     fprintf(file,", ");
76005b261ecSmrg		     nThisLine++;
76105b261ecSmrg		}
76205b261ecSmrg		shape= XkbKeyShape(geom,key);
76305b261ecSmrg		fprintf(file,"{ %6s, \"%s\", %3s",
76405b261ecSmrg		      XkbKeyNameText(key->name.name,XkbXKBFile),
7654642e01fSmrg		      XkbAtomText(shape->name,XkbXKBFile),
76605b261ecSmrg		      XkbGeomFPText(key->gap,XkbXKBFile));
76705b261ecSmrg		if (key->color_ndx!=dfltKeyColor) {
76805b261ecSmrg		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
76905b261ecSmrg		    forceNL= 1;
77005b261ecSmrg		}
77105b261ecSmrg		fprintf(file," }");
77205b261ecSmrg	    }
77305b261ecSmrg	    fprintf(file,"\n            };\n");
77405b261ecSmrg	}
77505b261ecSmrg	fprintf(file,"        };\n");
77605b261ecSmrg    }
77705b261ecSmrg    if (s->doodads!=NULL) {
77805b261ecSmrg	XkbDoodadPtr	doodad;
77905b261ecSmrg	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
7804642e01fSmrg	    WriteXKBDoodad(file,8,geom,doodad);
78105b261ecSmrg	}
78205b261ecSmrg    }
78305b261ecSmrg    if (s->overlays!=NULL) {
78405b261ecSmrg	XkbOverlayPtr	ol;
78505b261ecSmrg	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
7864642e01fSmrg	    WriteXKBOverlay(file,8,geom,ol);
78705b261ecSmrg	}
78805b261ecSmrg    }
78905b261ecSmrg    fprintf(file,"    }; // End of \"%s\" section\n\n",
7904642e01fSmrg				XkbAtomText(s->name,XkbXKBFile));
79105b261ecSmrg    return True;
79205b261ecSmrg}
79305b261ecSmrg
79405b261ecSmrgBool
79505b261ecSmrgXkbWriteXKBGeometry(	FILE *			file,
7964642e01fSmrg			XkbDescPtr              xkb,
79705b261ecSmrg			Bool			topLevel,
79805b261ecSmrg			Bool			showImplicit,
79905b261ecSmrg			XkbFileAddOnFunc	addOn,
80005b261ecSmrg			void *			priv)
80105b261ecSmrg{
80205b261ecSmrgregister unsigned	i,n;
80305b261ecSmrgXkbGeometryPtr		geom;
80405b261ecSmrg
80505b261ecSmrg    if ((!xkb)||(!xkb->geom)) {
80605b261ecSmrg	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
80705b261ecSmrg 	return False;
80805b261ecSmrg    }
80905b261ecSmrg    geom= xkb->geom;
81005b261ecSmrg    if (geom->name==None)
81105b261ecSmrg	 fprintf(file,"xkb_geometry {\n\n");
81205b261ecSmrg    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
8134642e01fSmrg				XkbAtomText(geom->name,XkbXKBFile));
81405b261ecSmrg    fprintf(file,"    width=       %s;\n",
81505b261ecSmrg				XkbGeomFPText(geom->width_mm,XkbXKBFile));
81605b261ecSmrg    fprintf(file,"    height=      %s;\n\n",
81705b261ecSmrg				XkbGeomFPText(geom->height_mm,XkbXKBFile));
81805b261ecSmrg
81905b261ecSmrg    if (geom->key_aliases!=NULL) {
82005b261ecSmrg	XkbKeyAliasPtr	pAl;
82105b261ecSmrg	pAl= geom->key_aliases;
82205b261ecSmrg	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
82305b261ecSmrg	    fprintf(file,"    alias %6s = %6s;\n",
82405b261ecSmrg				XkbKeyNameText(pAl->alias,XkbXKBFile),
82505b261ecSmrg				XkbKeyNameText(pAl->real,XkbXKBFile));
82605b261ecSmrg	}
82705b261ecSmrg	fprintf(file,"\n");
82805b261ecSmrg    }
82905b261ecSmrg
83005b261ecSmrg    if (geom->base_color!=NULL)
83105b261ecSmrg	fprintf(file,"    baseColor=   \"%s\";\n",
83205b261ecSmrg			XkbStringText(geom->base_color->spec,XkbXKBFile));
83305b261ecSmrg    if (geom->label_color!=NULL)
83405b261ecSmrg	fprintf(file,"    labelColor=  \"%s\";\n",
83505b261ecSmrg			XkbStringText(geom->label_color->spec,XkbXKBFile));
83605b261ecSmrg    if (geom->label_font!=NULL)
83705b261ecSmrg	fprintf(file,"    xfont=       \"%s\";\n",
83805b261ecSmrg			XkbStringText(geom->label_font,XkbXKBFile));
83905b261ecSmrg    if ((geom->num_colors>0)&&(showImplicit)) {
84005b261ecSmrg	XkbColorPtr	color;
84105b261ecSmrg	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
84205b261ecSmrg		fprintf(file,"//     color[%d]= \"%s\"\n",i,
84305b261ecSmrg				XkbStringText(color->spec,XkbXKBFile));
84405b261ecSmrg	}
84505b261ecSmrg	fprintf(file,"\n");
84605b261ecSmrg    }
84705b261ecSmrg    if (geom->num_properties>0) {
84805b261ecSmrg	XkbPropertyPtr	prop;
84905b261ecSmrg	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
85005b261ecSmrg	    fprintf(file,"    %s= \"%s\";\n",prop->name,
85105b261ecSmrg    				XkbStringText(prop->value,XkbXKBFile));
85205b261ecSmrg	}
85305b261ecSmrg	fprintf(file,"\n");
85405b261ecSmrg    }
85505b261ecSmrg    if (geom->num_shapes>0) {
85605b261ecSmrg	XkbShapePtr	shape;
85705b261ecSmrg	XkbOutlinePtr	outline;
85805b261ecSmrg	int		lastR;
85905b261ecSmrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
86005b261ecSmrg	    lastR=0;
86105b261ecSmrg	    fprintf(file,"    shape \"%s\" {",
8624642e01fSmrg				   XkbAtomText(shape->name,XkbXKBFile));
86305b261ecSmrg	    outline= shape->outlines;
86405b261ecSmrg	    if (shape->num_outlines>1) {
86505b261ecSmrg		for (n=0;n<shape->num_outlines;n++,outline++) {
86605b261ecSmrg		    if (n==0)	fprintf(file,"\n");
86705b261ecSmrg		    else	fprintf(file,",\n");
86805b261ecSmrg		    WriteXKBOutline(file,shape,outline,lastR,8,8);
86905b261ecSmrg		    lastR= outline->corner_radius;
87005b261ecSmrg		}
87105b261ecSmrg		fprintf(file,"\n    };\n");
87205b261ecSmrg	    }
87305b261ecSmrg	    else {
87405b261ecSmrg		WriteXKBOutline(file,NULL,outline,lastR,1,8);
87505b261ecSmrg		fprintf(file," };\n");
87605b261ecSmrg	    }
87705b261ecSmrg	}
87805b261ecSmrg    }
87905b261ecSmrg    if (geom->num_sections>0) {
88005b261ecSmrg	XkbSectionPtr	section;
88105b261ecSmrg	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
8824642e01fSmrg	    WriteXKBSection(file,section,geom);
88305b261ecSmrg	}
88405b261ecSmrg    }
88505b261ecSmrg    if (geom->num_doodads>0) {
88605b261ecSmrg	XkbDoodadPtr	doodad;
88705b261ecSmrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
8884642e01fSmrg	    WriteXKBDoodad(file,4,geom,doodad);
88905b261ecSmrg	}
89005b261ecSmrg    }
89105b261ecSmrg    if (addOn)
8924642e01fSmrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmGeometryIndex,priv);
89305b261ecSmrg    fprintf(file,"};\n\n");
89405b261ecSmrg    return True;
89505b261ecSmrg}
896