1706f2543Smrg/************************************************************
2706f2543Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3706f2543Smrg
4706f2543Smrg Permission to use, copy, modify, and distribute this
5706f2543Smrg software and its documentation for any purpose and without
6706f2543Smrg fee is hereby granted, provided that the above copyright
7706f2543Smrg notice appear in all copies and that both that copyright
8706f2543Smrg notice and this permission notice appear in supporting
9706f2543Smrg documentation, and that the name of Silicon Graphics not be
10706f2543Smrg used in advertising or publicity pertaining to distribution
11706f2543Smrg of the software without specific prior written permission.
12706f2543Smrg Silicon Graphics makes no representation about the suitability
13706f2543Smrg of this software for any purpose. It is provided "as is"
14706f2543Smrg without any express or implied warranty.
15706f2543Smrg
16706f2543Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17706f2543Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18706f2543Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19706f2543Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20706f2543Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22706f2543Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23706f2543Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg
25706f2543Smrg ********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <stdio.h>
32706f2543Smrg#include <ctype.h>
33706f2543Smrg#include <stdlib.h>
34706f2543Smrg#include <X11/Xfuncs.h>
35706f2543Smrg
36706f2543Smrg#include <X11/X.h>
37706f2543Smrg#include <X11/keysym.h>
38706f2543Smrg#include <X11/Xproto.h>
39706f2543Smrg#include <X11/extensions/XKMformat.h>
40706f2543Smrg#include "misc.h"
41706f2543Smrg#include "inputstr.h"
42706f2543Smrg#include "dix.h"
43706f2543Smrg#include "xkbstr.h"
44706f2543Smrg#define XKBSRV_NEED_FILE_FUNCS	1
45706f2543Smrg#include <xkbsrv.h>
46706f2543Smrg
47706f2543Smrg#include "xkbgeom.h"
48706f2543Smrg#include "xkbfile.h"
49706f2543Smrg
50706f2543Smrg#define	VMOD_HIDE_VALUE	0
51706f2543Smrg#define	VMOD_SHOW_VALUE	1
52706f2543Smrg#define	VMOD_COMMENT_VALUE 2
53706f2543Smrg
54706f2543Smrgstatic Bool
55706f2543SmrgWriteXKBVModDecl(FILE *file,XkbDescPtr xkb,int showValue)
56706f2543Smrg{
57706f2543Smrgregister int 	i,nMods;
58706f2543SmrgAtom *		vmodNames;
59706f2543Smrg
60706f2543Smrg    if (xkb==NULL)
61706f2543Smrg	return FALSE;
62706f2543Smrg    if (xkb->names!=NULL)
63706f2543Smrg	 vmodNames= xkb->names->vmods;
64706f2543Smrg    else vmodNames= NULL;
65706f2543Smrg
66706f2543Smrg    for (i=nMods=0;i<XkbNumVirtualMods;i++) {
67706f2543Smrg	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
68706f2543Smrg	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
69706f2543Smrg	    else		fprintf(file,",");
70706f2543Smrg	    fprintf(file,"%s",XkbAtomText(vmodNames[i],XkbXKBFile));
71706f2543Smrg	    if ((showValue!=VMOD_HIDE_VALUE)&&
72706f2543Smrg		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
73706f2543Smrg		if (showValue==VMOD_COMMENT_VALUE) {
74706f2543Smrg		    fprintf(file,"/* = %s */",
75706f2543Smrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
76706f2543Smrg		}
77706f2543Smrg		else  {
78706f2543Smrg		    fprintf(file,"= %s",
79706f2543Smrg			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
80706f2543Smrg		}
81706f2543Smrg	    }
82706f2543Smrg	    nMods++;
83706f2543Smrg	}
84706f2543Smrg    }
85706f2543Smrg    if (nMods>0)
86706f2543Smrg	fprintf(file,";\n\n");
87706f2543Smrg    return TRUE;
88706f2543Smrg}
89706f2543Smrg
90706f2543Smrg/***====================================================================***/
91706f2543Smrg
92706f2543Smrgstatic Bool
93706f2543SmrgWriteXKBAction(FILE *file,XkbDescPtr xkb,XkbAnyAction *action)
94706f2543Smrg{
95706f2543Smrg    fprintf(file,"%s",XkbActionText(xkb,(XkbAction *)action,XkbXKBFile));
96706f2543Smrg    return TRUE;
97706f2543Smrg}
98706f2543Smrg
99706f2543Smrg/***====================================================================***/
100706f2543Smrg
101706f2543SmrgBool
102706f2543SmrgXkbWriteXKBKeycodes(	FILE *			file,
103706f2543Smrg			XkbDescPtr		xkb,
104706f2543Smrg			Bool			topLevel,
105706f2543Smrg			Bool			showImplicit,
106706f2543Smrg			XkbFileAddOnFunc	addOn,
107706f2543Smrg			void *			priv)
108706f2543Smrg{
109706f2543SmrgAtom			kcName;
110706f2543Smrgregister unsigned 	i;
111706f2543Smrgchar *			alternate;
112706f2543Smrg
113706f2543Smrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
114706f2543Smrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
115706f2543Smrg	return FALSE;
116706f2543Smrg    }
117706f2543Smrg    kcName= xkb->names->keycodes;
118706f2543Smrg    if (kcName!=None)
119706f2543Smrg	 fprintf(file,"xkb_keycodes \"%s\" {\n",
120706f2543Smrg					XkbAtomText(kcName,XkbXKBFile));
121706f2543Smrg    else fprintf(file,"xkb_keycodes {\n");
122706f2543Smrg    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
123706f2543Smrg    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
124706f2543Smrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
125706f2543Smrg	if (xkb->names->keys[i].name[0]!='\0') {
126706f2543Smrg	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,TRUE)!=i)
127706f2543Smrg		 alternate= "alternate ";
128706f2543Smrg	    else alternate= "";
129706f2543Smrg	    fprintf(file,"    %s%6s = %d;\n",alternate,
130706f2543Smrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
131706f2543Smrg			i);
132706f2543Smrg	}
133706f2543Smrg    }
134706f2543Smrg    if (xkb->indicators!=NULL) {
135706f2543Smrg	for (i=0;i<XkbNumIndicators;i++) {
136706f2543Smrg	    char *type;
137706f2543Smrg	    if (xkb->indicators->phys_indicators&(1<<i))
138706f2543Smrg			type= "    ";
139706f2543Smrg	    else	type= "    virtual ";
140706f2543Smrg	    if (xkb->names->indicators[i]!=None) {
141706f2543Smrg		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
142706f2543Smrg			XkbAtomText(xkb->names->indicators[i],XkbXKBFile));
143706f2543Smrg	    }
144706f2543Smrg	}
145706f2543Smrg    }
146706f2543Smrg    if (xkb->names->key_aliases!=NULL) {
147706f2543Smrg	XkbKeyAliasPtr	pAl;
148706f2543Smrg	pAl= xkb->names->key_aliases;
149706f2543Smrg	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
150706f2543Smrg	    fprintf(file,"    alias %6s = %6s;\n",
151706f2543Smrg			XkbKeyNameText(pAl->alias,XkbXKBFile),
152706f2543Smrg			XkbKeyNameText(pAl->real,XkbXKBFile));
153706f2543Smrg	}
154706f2543Smrg    }
155706f2543Smrg    if (addOn)
156706f2543Smrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmKeyNamesIndex,priv);
157706f2543Smrg    fprintf(file,"};\n\n");
158706f2543Smrg    return TRUE;
159706f2543Smrg}
160706f2543Smrg
161706f2543SmrgBool
162706f2543SmrgXkbWriteXKBKeyTypes(	FILE *			file,
163706f2543Smrg			XkbDescPtr              xkb,
164706f2543Smrg			Bool			topLevel,
165706f2543Smrg			Bool			showImplicit,
166706f2543Smrg			XkbFileAddOnFunc	addOn,
167706f2543Smrg			void *			priv)
168706f2543Smrg{
169706f2543Smrgregister unsigned	i,n;
170706f2543SmrgXkbKeyTypePtr		type;
171706f2543SmrgXkbKTMapEntryPtr	entry;
172706f2543Smrg
173706f2543Smrg    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
174706f2543Smrg	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
175706f2543Smrg	return FALSE;
176706f2543Smrg    }
177706f2543Smrg    if (xkb->map->num_types<XkbNumRequiredTypes) {
178706f2543Smrg	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
179706f2543Smrg	return 0;
180706f2543Smrg    }
181706f2543Smrg    if ((xkb->names==NULL)||(xkb->names->types==None))
182706f2543Smrg	 fprintf(file,"xkb_types {\n\n");
183706f2543Smrg    else fprintf(file,"xkb_types \"%s\" {\n\n",
184706f2543Smrg			XkbAtomText(xkb->names->types,XkbXKBFile));
185706f2543Smrg    WriteXKBVModDecl(file,xkb,
186706f2543Smrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
187706f2543Smrg
188706f2543Smrg    type= xkb->map->types;
189706f2543Smrg    for (i=0;i<xkb->map->num_types;i++,type++) {
190706f2543Smrg	fprintf(file,"    type \"%s\" {\n",
191706f2543Smrg		XkbAtomText(type->name,XkbXKBFile));
192706f2543Smrg	fprintf(file,"        modifiers= %s;\n",
193706f2543Smrg	       XkbVModMaskText(xkb,type->mods.real_mods,type->mods.vmods,
194706f2543Smrg								XkbXKBFile));
195706f2543Smrg	entry= type->map;
196706f2543Smrg	for (n=0;n<type->map_count;n++,entry++) {
197706f2543Smrg	    char *str;
198706f2543Smrg	    str=XkbVModMaskText(xkb,entry->mods.real_mods,entry->mods.vmods,
199706f2543Smrg								XkbXKBFile);
200706f2543Smrg	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
201706f2543Smrg	    if ((type->preserve)&&((type->preserve[n].real_mods)||
202706f2543Smrg				   (type->preserve[n].vmods))) {
203706f2543Smrg		fprintf(file,"        preserve[%s]= ",str);
204706f2543Smrg		fprintf(file,"%s;\n",XkbVModMaskText(xkb,
205706f2543Smrg					type->preserve[n].real_mods,
206706f2543Smrg					type->preserve[n].vmods,
207706f2543Smrg					XkbXKBFile));
208706f2543Smrg	    }
209706f2543Smrg	}
210706f2543Smrg	if (type->level_names!=NULL) {
211706f2543Smrg	    Atom *name= type->level_names;
212706f2543Smrg	    for (n=0;n<type->num_levels;n++,name++) {
213706f2543Smrg		if ((*name)==None)
214706f2543Smrg		    continue;
215706f2543Smrg		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
216706f2543Smrg					XkbAtomText(*name,XkbXKBFile));
217706f2543Smrg	    }
218706f2543Smrg	}
219706f2543Smrg	fprintf(file,"    };\n");
220706f2543Smrg    }
221706f2543Smrg    if (addOn)
222706f2543Smrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmTypesIndex,priv);
223706f2543Smrg    fprintf(file,"};\n\n");
224706f2543Smrg    return TRUE;
225706f2543Smrg}
226706f2543Smrg
227706f2543Smrgstatic Bool
228706f2543SmrgWriteXKBIndicatorMap(	FILE *			file,
229706f2543Smrg			XkbDescPtr              xkb,
230706f2543Smrg			Atom			name,
231706f2543Smrg			XkbIndicatorMapPtr	led,
232706f2543Smrg			XkbFileAddOnFunc	addOn,
233706f2543Smrg			void *			priv)
234706f2543Smrg{
235706f2543Smrg
236706f2543Smrg    fprintf(file,"    indicator \"%s\" {\n",NameForAtom(name));
237706f2543Smrg    if (led->flags&XkbIM_NoExplicit)
238706f2543Smrg	fprintf(file,"        !allowExplicit;\n");
239706f2543Smrg    if (led->flags&XkbIM_LEDDrivesKB)
240706f2543Smrg	fprintf(file,"        indicatorDrivesKeyboard;\n");
241706f2543Smrg    if (led->which_groups!=0) {
242706f2543Smrg	if (led->which_groups!=XkbIM_UseEffective) {
243706f2543Smrg	    fprintf(file,"        whichGroupState= %s;\n",
244706f2543Smrg			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
245706f2543Smrg	}
246706f2543Smrg	fprintf(file,"        groups= 0x%02x;\n",led->groups);
247706f2543Smrg    }
248706f2543Smrg    if (led->which_mods!=0) {
249706f2543Smrg	if (led->which_mods!=XkbIM_UseEffective) {
250706f2543Smrg	    fprintf(file,"        whichModState= %s;\n",
251706f2543Smrg			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
252706f2543Smrg	}
253706f2543Smrg	fprintf(file,"        modifiers= %s;\n",
254706f2543Smrg			XkbVModMaskText(xkb,
255706f2543Smrg					led->mods.real_mods,led->mods.vmods,
256706f2543Smrg					XkbXKBFile));
257706f2543Smrg    }
258706f2543Smrg    if (led->ctrls!=0) {
259706f2543Smrg	fprintf(file,"        controls= %s;\n",
260706f2543Smrg			XkbControlsMaskText(led->ctrls,XkbXKBFile));
261706f2543Smrg    }
262706f2543Smrg    if (addOn)
263706f2543Smrg	(*addOn)(file,xkb,FALSE,TRUE,XkmIndicatorsIndex,priv);
264706f2543Smrg    fprintf(file,"    };\n");
265706f2543Smrg    return TRUE;
266706f2543Smrg}
267706f2543Smrg
268706f2543SmrgBool
269706f2543SmrgXkbWriteXKBCompatMap(	FILE *			file,
270706f2543Smrg			XkbDescPtr              xkb,
271706f2543Smrg			Bool			topLevel,
272706f2543Smrg			Bool			showImplicit,
273706f2543Smrg			XkbFileAddOnFunc	addOn,
274706f2543Smrg			void *			priv)
275706f2543Smrg{
276706f2543Smrgregister unsigned	i;
277706f2543SmrgXkbSymInterpretPtr	interp;
278706f2543Smrg
279706f2543Smrg    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
280706f2543Smrg	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
281706f2543Smrg	return FALSE;
282706f2543Smrg    }
283706f2543Smrg    if ((xkb->names==NULL)||(xkb->names->compat==None))
284706f2543Smrg	 fprintf(file,"xkb_compatibility {\n\n");
285706f2543Smrg    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
286706f2543Smrg			XkbAtomText(xkb->names->compat,XkbXKBFile));
287706f2543Smrg    WriteXKBVModDecl(file,xkb,
288706f2543Smrg			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
289706f2543Smrg
290706f2543Smrg    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
291706f2543Smrg    fprintf(file,"    interpret.repeat= FALSE;\n");
292706f2543Smrg    fprintf(file,"    interpret.locking= FALSE;\n");
293706f2543Smrg    interp= xkb->compat->sym_interpret;
294706f2543Smrg    for (i=0;i<xkb->compat->num_si;i++,interp++) {
295706f2543Smrg	fprintf(file,"    interpret %s+%s(%s) {\n",
296706f2543Smrg				((interp->sym==NoSymbol)?"Any":
297706f2543Smrg					XkbKeysymText(interp->sym,XkbXKBFile)),
298706f2543Smrg				XkbSIMatchText(interp->match,XkbXKBFile),
299706f2543Smrg				XkbModMaskText(interp->mods,XkbXKBFile));
300706f2543Smrg	if (interp->virtual_mod!=XkbNoModifier) {
301706f2543Smrg	    fprintf(file,"        virtualModifier= %s;\n",
302706f2543Smrg		XkbVModIndexText(xkb,interp->virtual_mod,XkbXKBFile));
303706f2543Smrg	}
304706f2543Smrg	if (interp->match&XkbSI_LevelOneOnly)
305706f2543Smrg	    fprintf(file,"        useModMapMods=level1;\n");
306706f2543Smrg	if (interp->flags&XkbSI_LockingKey)
307706f2543Smrg	    fprintf(file,"        locking= TRUE;\n");
308706f2543Smrg	if (interp->flags&XkbSI_AutoRepeat)
309706f2543Smrg	    fprintf(file,"        repeat= TRUE;\n");
310706f2543Smrg	fprintf(file,"        action= ");
311706f2543Smrg	WriteXKBAction(file,xkb,&interp->act);
312706f2543Smrg	fprintf(file,";\n");
313706f2543Smrg	fprintf(file,"    };\n");
314706f2543Smrg    }
315706f2543Smrg    for (i=0;i<XkbNumKbdGroups;i++) {
316706f2543Smrg	XkbModsPtr	gc;
317706f2543Smrg
318706f2543Smrg	gc= &xkb->compat->groups[i];
319706f2543Smrg	if ((gc->real_mods==0)&&(gc->vmods==0))
320706f2543Smrg	    continue;
321706f2543Smrg	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb,
322706f2543Smrg							gc->real_mods,gc->vmods,
323706f2543Smrg							XkbXKBFile));
324706f2543Smrg    }
325706f2543Smrg    if (xkb->indicators) {
326706f2543Smrg	for (i=0;i<XkbNumIndicators;i++) {
327706f2543Smrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
328706f2543Smrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
329706f2543Smrg		(map->which_mods!=0)||
330706f2543Smrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
331706f2543Smrg		(map->ctrls!=0)) {
332706f2543Smrg		WriteXKBIndicatorMap(file,xkb,xkb->names->indicators[i],map,
333706f2543Smrg								addOn,priv);
334706f2543Smrg	    }
335706f2543Smrg	}
336706f2543Smrg    }
337706f2543Smrg    if (addOn)
338706f2543Smrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmCompatMapIndex,priv);
339706f2543Smrg    fprintf(file,"};\n\n");
340706f2543Smrg    return TRUE;
341706f2543Smrg}
342706f2543Smrg
343706f2543SmrgBool
344706f2543SmrgXkbWriteXKBSymbols(	FILE *			file,
345706f2543Smrg			XkbDescPtr              xkb,
346706f2543Smrg			Bool			topLevel,
347706f2543Smrg			Bool			showImplicit,
348706f2543Smrg			XkbFileAddOnFunc	addOn,
349706f2543Smrg			void *			priv)
350706f2543Smrg{
351706f2543Smrgregister unsigned	i,tmp;
352706f2543SmrgXkbClientMapPtr		map;
353706f2543SmrgXkbServerMapPtr		srv;
354706f2543SmrgBool			showActions;
355706f2543Smrg
356706f2543Smrg    if (!xkb) {
357706f2543Smrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
358706f2543Smrg	return FALSE;
359706f2543Smrg    }
360706f2543Smrg
361706f2543Smrg    map= xkb->map;
362706f2543Smrg    if ((!map)||(!map->syms)||(!map->key_sym_map)) {
363706f2543Smrg	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
364706f2543Smrg	return FALSE;
365706f2543Smrg    }
366706f2543Smrg    if ((!xkb->names)||(!xkb->names->keys)) {
367706f2543Smrg	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
368706f2543Smrg	return FALSE;
369706f2543Smrg    }
370706f2543Smrg    if ((xkb->names==NULL)||(xkb->names->symbols==None))
371706f2543Smrg	 fprintf(file,"xkb_symbols {\n\n");
372706f2543Smrg    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
373706f2543Smrg			XkbAtomText(xkb->names->symbols,XkbXKBFile));
374706f2543Smrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
375706f2543Smrg	if (xkb->names->groups[i]!=None) {
376706f2543Smrg	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
377706f2543Smrg			XkbAtomText(xkb->names->groups[i],XkbXKBFile));
378706f2543Smrg	    tmp++;
379706f2543Smrg	}
380706f2543Smrg    }
381706f2543Smrg    if (tmp>0)
382706f2543Smrg	fprintf(file,"\n");
383706f2543Smrg    srv= xkb->server;
384706f2543Smrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
385706f2543Smrg	Bool	simple;
386706f2543Smrg	if ((int)XkbKeyNumSyms(xkb,i)<1)
387706f2543Smrg	    continue;
388706f2543Smrg	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,TRUE)!=i)
389706f2543Smrg	    continue;
390706f2543Smrg	simple= TRUE;
391706f2543Smrg	fprintf(file,"    key %6s {",
392706f2543Smrg			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
393706f2543Smrg	if (srv->explicit) {
394706f2543Smrg	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
395706f2543Smrg	   						(showImplicit)) {
396706f2543Smrg		int 	typeNdx,g;
397706f2543Smrg		Bool	multi;
398706f2543Smrg		char *	comment="  ";
399706f2543Smrg
400706f2543Smrg		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
401706f2543Smrg		    comment= "//";
402706f2543Smrg		multi= FALSE;
403706f2543Smrg		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
404706f2543Smrg		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
405706f2543Smrg		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
406706f2543Smrg			multi= TRUE;
407706f2543Smrg		}
408706f2543Smrg		if (multi) {
409706f2543Smrg		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
410706f2543Smrg			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
411706f2543Smrg			if (srv->explicit[i]&(1<<g)) {
412706f2543Smrg			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
413706f2543Smrg			    	comment,g+1,
414706f2543Smrg				XkbAtomText(map->types[typeNdx].name,
415706f2543Smrg			    	XkbXKBFile));
416706f2543Smrg			}
417706f2543Smrg			else if (showImplicit) {
418706f2543Smrg			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
419706f2543Smrg				XkbAtomText(map->types[typeNdx].name,
420706f2543Smrg			    	XkbXKBFile));
421706f2543Smrg			}
422706f2543Smrg		    }
423706f2543Smrg		}
424706f2543Smrg		else {
425706f2543Smrg		    fprintf(file,"\n%s      type= \"%s\",",comment,
426706f2543Smrg				XkbAtomText(map->types[typeNdx].name,
427706f2543Smrg			    	XkbXKBFile));
428706f2543Smrg		}
429706f2543Smrg		simple= FALSE;
430706f2543Smrg	    }
431706f2543Smrg	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
432706f2543Smrg		    					  (xkb->ctrls!=NULL)) {
433706f2543Smrg		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
434706f2543Smrg		     fprintf(file,"\n        repeat= Yes,");
435706f2543Smrg		else fprintf(file,"\n        repeat= No,");
436706f2543Smrg		simple= FALSE;
437706f2543Smrg	    }
438706f2543Smrg	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
439706f2543Smrg					(xkb->server->vmodmap[i]!=0)) {
440706f2543Smrg		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
441706f2543Smrg		    fprintf(file,"\n        virtualMods= %s,",
442706f2543Smrg				XkbVModMaskText(xkb,0,
443706f2543Smrg						xkb->server->vmodmap[i],
444706f2543Smrg						XkbXKBFile));
445706f2543Smrg		}
446706f2543Smrg		else if (showImplicit) {
447706f2543Smrg		    fprintf(file,"\n//      virtualMods= %s,",
448706f2543Smrg				XkbVModMaskText(xkb,0,
449706f2543Smrg						xkb->server->vmodmap[i],
450706f2543Smrg						XkbXKBFile));
451706f2543Smrg		}
452706f2543Smrg	    }
453706f2543Smrg	}
454706f2543Smrg	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
455706f2543Smrg	    case XkbClampIntoRange:
456706f2543Smrg		fprintf(file,"\n        groupsClamp,");
457706f2543Smrg		break;
458706f2543Smrg	    case XkbRedirectIntoRange:
459706f2543Smrg		fprintf(file,"\n        groupsRedirect= Group%d,",
460706f2543Smrg			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
461706f2543Smrg		break;
462706f2543Smrg	}
463706f2543Smrg	if (srv->behaviors!=NULL) {
464706f2543Smrg	    unsigned type;
465706f2543Smrg	    type= srv->behaviors[i].type&XkbKB_OpMask;
466706f2543Smrg
467706f2543Smrg	    if (type!=XkbKB_Default) {
468706f2543Smrg		simple= FALSE;
469706f2543Smrg		fprintf(file,"\n        %s,",
470706f2543Smrg			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
471706f2543Smrg	    }
472706f2543Smrg	}
473706f2543Smrg	if ((srv->explicit==NULL) || showImplicit ||
474706f2543Smrg	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
475706f2543Smrg	     showActions= XkbKeyHasActions(xkb,i);
476706f2543Smrg	else showActions= FALSE;
477706f2543Smrg
478706f2543Smrg	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
479706f2543Smrg	    simple= FALSE;
480706f2543Smrg	if (simple) {
481706f2543Smrg	    KeySym *syms;
482706f2543Smrg	    unsigned s;
483706f2543Smrg
484706f2543Smrg	    syms= XkbKeySymsPtr(xkb,i);
485706f2543Smrg	    fprintf(file,"         [ ");
486706f2543Smrg	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
487706f2543Smrg		if (s!=0)
488706f2543Smrg		    fprintf(file,", ");
489706f2543Smrg		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
490706f2543Smrg	    }
491706f2543Smrg	    fprintf(file," ] };\n");
492706f2543Smrg	}
493706f2543Smrg	else {
494706f2543Smrg	    unsigned g,s;
495706f2543Smrg	    KeySym *syms;
496706f2543Smrg	    XkbAction *acts;
497706f2543Smrg	    syms= XkbKeySymsPtr(xkb,i);
498706f2543Smrg	    acts= XkbKeyActionsPtr(xkb,i);
499706f2543Smrg	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
500706f2543Smrg		if (g!=0)
501706f2543Smrg		    fprintf(file,",");
502706f2543Smrg		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
503706f2543Smrg		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
504706f2543Smrg		    if (s!=0)
505706f2543Smrg			fprintf(file,", ");
506706f2543Smrg		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
507706f2543Smrg		}
508706f2543Smrg		fprintf(file," ]");
509706f2543Smrg		syms+= XkbKeyGroupsWidth(xkb,i);
510706f2543Smrg		if (showActions) {
511706f2543Smrg		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
512706f2543Smrg		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
513706f2543Smrg			if (s!=0)
514706f2543Smrg			    fprintf(file,", ");
515706f2543Smrg			WriteXKBAction(file,xkb,(XkbAnyAction *)&acts[s]);
516706f2543Smrg		    }
517706f2543Smrg		    fprintf(file," ]");
518706f2543Smrg		    acts+= XkbKeyGroupsWidth(xkb,i);
519706f2543Smrg		}
520706f2543Smrg	    }
521706f2543Smrg	    fprintf(file,"\n    };\n");
522706f2543Smrg	}
523706f2543Smrg    }
524706f2543Smrg    if (map && map->modmap) {
525706f2543Smrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
526706f2543Smrg	    if (map->modmap[i]!=0) {
527706f2543Smrg		register int n,bit;
528706f2543Smrg		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
529706f2543Smrg		    if (map->modmap[i]&bit) {
530706f2543Smrg			char buf[5];
531706f2543Smrg			memcpy(buf,xkb->names->keys[i].name,4);
532706f2543Smrg			buf[4]= '\0';
533706f2543Smrg			fprintf(file,"    modifier_map %s { <%s> };\n",
534706f2543Smrg					XkbModIndexText(n,XkbXKBFile),buf);
535706f2543Smrg		    }
536706f2543Smrg		}
537706f2543Smrg	    }
538706f2543Smrg	}
539706f2543Smrg    }
540706f2543Smrg    if (addOn)
541706f2543Smrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmSymbolsIndex,priv);
542706f2543Smrg    fprintf(file,"};\n\n");
543706f2543Smrg    return TRUE;
544706f2543Smrg}
545706f2543Smrg
546706f2543Smrgstatic Bool
547706f2543SmrgWriteXKBOutline(	FILE *		file,
548706f2543Smrg			XkbShapePtr	shape,
549706f2543Smrg			XkbOutlinePtr	outline,
550706f2543Smrg			int		lastRadius,
551706f2543Smrg			int		first,
552706f2543Smrg			int		indent)
553706f2543Smrg{
554706f2543Smrgregister int	i;
555706f2543SmrgXkbPointPtr	pt;
556706f2543Smrgchar *		iStr;
557706f2543Smrg
558706f2543Smrg    fprintf(file,"%s",iStr= XkbIndentText(first));
559706f2543Smrg    if (first!=indent)
560706f2543Smrg	iStr= XkbIndentText(indent);
561706f2543Smrg    if (outline->corner_radius!=lastRadius) {
562706f2543Smrg	fprintf(file,"corner= %s,",
563706f2543Smrg			XkbGeomFPText(outline->corner_radius,XkbMessage));
564706f2543Smrg	if (shape!=NULL) {
565706f2543Smrg	    fprintf(file,"\n%s",iStr);
566706f2543Smrg	}
567706f2543Smrg    }
568706f2543Smrg    if (shape) {
569706f2543Smrg	if (outline==shape->approx)
570706f2543Smrg	    fprintf(file,"approx= ");
571706f2543Smrg	else if (outline==shape->primary)
572706f2543Smrg	    fprintf(file,"primary= ");
573706f2543Smrg    }
574706f2543Smrg    fprintf(file,"{");
575706f2543Smrg    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
576706f2543Smrg	if (i==0)		fprintf(file," ");
577706f2543Smrg	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
578706f2543Smrg	else			fprintf(file,", ");
579706f2543Smrg	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
580706f2543Smrg				  XkbGeomFPText(pt->y,XkbXKBFile));
581706f2543Smrg    }
582706f2543Smrg    fprintf(file," }");
583706f2543Smrg    return TRUE;
584706f2543Smrg}
585706f2543Smrg
586706f2543Smrgstatic Bool
587706f2543SmrgWriteXKBDoodad(	FILE *		file,
588706f2543Smrg		unsigned	indent,
589706f2543Smrg		XkbGeometryPtr	geom,
590706f2543Smrg		XkbDoodadPtr	doodad)
591706f2543Smrg{
592706f2543Smrgregister char *	i_str;
593706f2543SmrgXkbShapePtr	shape;
594706f2543SmrgXkbColorPtr	color;
595706f2543Smrg
596706f2543Smrg    i_str= XkbIndentText(indent);
597706f2543Smrg    fprintf(file,"%s%s \"%s\" {\n",i_str,
598706f2543Smrg				XkbDoodadTypeText(doodad->any.type,XkbMessage),
599706f2543Smrg				XkbAtomText(doodad->any.name,XkbMessage));
600706f2543Smrg    fprintf(file,"%s    top=      %s;\n",i_str,
601706f2543Smrg				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
602706f2543Smrg    fprintf(file,"%s    left=     %s;\n",i_str,
603706f2543Smrg				XkbGeomFPText(doodad->any.left,XkbXKBFile));
604706f2543Smrg    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
605706f2543Smrg    switch (doodad->any.type) {
606706f2543Smrg	case XkbOutlineDoodad:
607706f2543Smrg	case XkbSolidDoodad:
608706f2543Smrg	    if (doodad->shape.angle!=0) {
609706f2543Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
610706f2543Smrg			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
611706f2543Smrg	    }
612706f2543Smrg	    if (doodad->shape.color_ndx!=0) {
613706f2543Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
614706f2543Smrg			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
615706f2543Smrg	    }
616706f2543Smrg	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
617706f2543Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
618706f2543Smrg			    XkbAtomText(shape->name,XkbXKBFile));
619706f2543Smrg	    break;
620706f2543Smrg	case XkbTextDoodad:
621706f2543Smrg	    if (doodad->text.angle!=0) {
622706f2543Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
623706f2543Smrg			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
624706f2543Smrg	    }
625706f2543Smrg	    if (doodad->text.width!=0) {
626706f2543Smrg		fprintf(file,"%s    width=  %s;\n",i_str,
627706f2543Smrg			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
628706f2543Smrg
629706f2543Smrg	    }
630706f2543Smrg	    if (doodad->text.height!=0) {
631706f2543Smrg		fprintf(file,"%s    height=  %s;\n",i_str,
632706f2543Smrg			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
633706f2543Smrg
634706f2543Smrg	    }
635706f2543Smrg	    if (doodad->text.color_ndx!=0) {
636706f2543Smrg		color= XkbTextDoodadColor(geom,&doodad->text);
637706f2543Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
638706f2543Smrg			     XkbStringText(color->spec,XkbXKBFile));
639706f2543Smrg	    }
640706f2543Smrg	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
641706f2543Smrg	    		     XkbStringText(doodad->text.font,XkbXKBFile));
642706f2543Smrg	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
643706f2543Smrg	    		    XkbStringText(doodad->text.text,XkbXKBFile));
644706f2543Smrg	    break;
645706f2543Smrg	case XkbIndicatorDoodad:
646706f2543Smrg	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
647706f2543Smrg	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
648706f2543Smrg	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
649706f2543Smrg	    		    XkbStringText(color->spec,XkbXKBFile));
650706f2543Smrg	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
651706f2543Smrg	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
652706f2543Smrg	    		    XkbStringText(color->spec,XkbXKBFile));
653706f2543Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
654706f2543Smrg			     XkbAtomText(shape->name,XkbXKBFile));
655706f2543Smrg	    break;
656706f2543Smrg	case XkbLogoDoodad:
657706f2543Smrg	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
658706f2543Smrg			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
659706f2543Smrg	    if (doodad->shape.angle!=0) {
660706f2543Smrg		fprintf(file,"%s    angle=  %s;\n",i_str,
661706f2543Smrg			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
662706f2543Smrg	    }
663706f2543Smrg	    if (doodad->shape.color_ndx!=0) {
664706f2543Smrg		fprintf(file,"%s    color= \"%s\";\n",i_str,
665706f2543Smrg			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
666706f2543Smrg	    }
667706f2543Smrg	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
668706f2543Smrg	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
669706f2543Smrg			    XkbAtomText(shape->name,XkbXKBFile));
670706f2543Smrg	    break;
671706f2543Smrg    }
672706f2543Smrg    fprintf(file,"%s};\n",i_str);
673706f2543Smrg    return TRUE;
674706f2543Smrg}
675706f2543Smrg
676706f2543Smrg/*ARGSUSED*/
677706f2543Smrgstatic Bool
678706f2543SmrgWriteXKBOverlay(	FILE *		file,
679706f2543Smrg			unsigned	indent,
680706f2543Smrg			XkbGeometryPtr	geom,
681706f2543Smrg			XkbOverlayPtr	ol)
682706f2543Smrg{
683706f2543Smrgregister char *		i_str;
684706f2543Smrgint			r,k,nOut;
685706f2543SmrgXkbOverlayRowPtr	row;
686706f2543SmrgXkbOverlayKeyPtr	key;
687706f2543Smrg
688706f2543Smrg    i_str= XkbIndentText(indent);
689706f2543Smrg    if (ol->name!=None) {
690706f2543Smrg	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
691706f2543Smrg    					XkbAtomText(ol->name,XkbMessage));
692706f2543Smrg    }
693706f2543Smrg    else fprintf(file,"%soverlay {\n",i_str);
694706f2543Smrg    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
695706f2543Smrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
696706f2543Smrg	    char *over,*under;
697706f2543Smrg	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
698706f2543Smrg	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
699706f2543Smrg	    if (nOut==0)
700706f2543Smrg		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
701706f2543Smrg	    else if ((nOut%4)==0)
702706f2543Smrg		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
703706f2543Smrg	    else fprintf(file,", %6s=%6s",under,over);
704706f2543Smrg	    nOut++;
705706f2543Smrg	}
706706f2543Smrg    }
707706f2543Smrg    fprintf(file,"\n%s};\n",i_str);
708706f2543Smrg    return TRUE;
709706f2543Smrg}
710706f2543Smrg
711706f2543Smrgstatic Bool
712706f2543SmrgWriteXKBSection(	FILE *		file,
713706f2543Smrg			XkbSectionPtr 	s,
714706f2543Smrg			XkbGeometryPtr	geom)
715706f2543Smrg{
716706f2543Smrgregister int	i;
717706f2543SmrgXkbRowPtr	row;
718706f2543Smrgint		dfltKeyColor = 0;
719706f2543Smrg
720706f2543Smrg    fprintf(file,"    section \"%s\" {\n",
721706f2543Smrg				XkbAtomText(s->name,XkbXKBFile));
722706f2543Smrg    if (s->rows&&(s->rows->num_keys>0)) {
723706f2543Smrg	dfltKeyColor= s->rows->keys[0].color_ndx;
724706f2543Smrg	fprintf(file,"        key.color= \"%s\";\n",
725706f2543Smrg		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
726706f2543Smrg    }
727706f2543Smrg    fprintf(file,"        priority=  %d;\n",s->priority);
728706f2543Smrg    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
729706f2543Smrg    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
730706f2543Smrg    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
731706f2543Smrg    fprintf(file,"        height=    %s;\n",
732706f2543Smrg					XkbGeomFPText(s->height,XkbXKBFile));
733706f2543Smrg    if (s->angle!=0) {
734706f2543Smrg	fprintf(file,"        angle=  %s;\n",
735706f2543Smrg					XkbGeomFPText(s->angle,XkbXKBFile));
736706f2543Smrg    }
737706f2543Smrg    for (i=0,row=s->rows;i<s->num_rows;i++,row++) {
738706f2543Smrg	fprintf(file,"        row {\n");
739706f2543Smrg	fprintf(file,"            top=  %s;\n",
740706f2543Smrg					XkbGeomFPText(row->top,XkbXKBFile));
741706f2543Smrg	fprintf(file,"            left= %s;\n",
742706f2543Smrg					XkbGeomFPText(row->left,XkbXKBFile));
743706f2543Smrg	if (row->vertical)
744706f2543Smrg	    fprintf(file,"            vertical;\n");
745706f2543Smrg	if (row->num_keys>0) {
746706f2543Smrg	    register int 	k;
747706f2543Smrg	    register XkbKeyPtr	key;
748706f2543Smrg	    int			forceNL=0;
749706f2543Smrg	    int			nThisLine= 0;
750706f2543Smrg	    fprintf(file,"            keys {\n");
751706f2543Smrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
752706f2543Smrg		XkbShapePtr	shape;
753706f2543Smrg		if (key->color_ndx!=dfltKeyColor)
754706f2543Smrg		    forceNL= 1;
755706f2543Smrg		if (k==0) {
756706f2543Smrg		     fprintf(file,"                ");
757706f2543Smrg		     nThisLine= 0;
758706f2543Smrg		}
759706f2543Smrg		else if (((nThisLine%2)==1)||(forceNL)) {
760706f2543Smrg		     fprintf(file,",\n                ");
761706f2543Smrg		     forceNL= nThisLine= 0;
762706f2543Smrg		}
763706f2543Smrg		else {
764706f2543Smrg		     fprintf(file,", ");
765706f2543Smrg		     nThisLine++;
766706f2543Smrg		}
767706f2543Smrg		shape= XkbKeyShape(geom,key);
768706f2543Smrg		fprintf(file,"{ %6s, \"%s\", %3s",
769706f2543Smrg		      XkbKeyNameText(key->name.name,XkbXKBFile),
770706f2543Smrg		      XkbAtomText(shape->name,XkbXKBFile),
771706f2543Smrg		      XkbGeomFPText(key->gap,XkbXKBFile));
772706f2543Smrg		if (key->color_ndx!=dfltKeyColor) {
773706f2543Smrg		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
774706f2543Smrg		    forceNL= 1;
775706f2543Smrg		}
776706f2543Smrg		fprintf(file," }");
777706f2543Smrg	    }
778706f2543Smrg	    fprintf(file,"\n            };\n");
779706f2543Smrg	}
780706f2543Smrg	fprintf(file,"        };\n");
781706f2543Smrg    }
782706f2543Smrg    if (s->doodads!=NULL) {
783706f2543Smrg	XkbDoodadPtr	doodad;
784706f2543Smrg	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
785706f2543Smrg	    WriteXKBDoodad(file,8,geom,doodad);
786706f2543Smrg	}
787706f2543Smrg    }
788706f2543Smrg    if (s->overlays!=NULL) {
789706f2543Smrg	XkbOverlayPtr	ol;
790706f2543Smrg	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
791706f2543Smrg	    WriteXKBOverlay(file,8,geom,ol);
792706f2543Smrg	}
793706f2543Smrg    }
794706f2543Smrg    fprintf(file,"    }; // End of \"%s\" section\n\n",
795706f2543Smrg				XkbAtomText(s->name,XkbXKBFile));
796706f2543Smrg    return TRUE;
797706f2543Smrg}
798706f2543Smrg
799706f2543SmrgBool
800706f2543SmrgXkbWriteXKBGeometry(	FILE *			file,
801706f2543Smrg			XkbDescPtr              xkb,
802706f2543Smrg			Bool			topLevel,
803706f2543Smrg			Bool			showImplicit,
804706f2543Smrg			XkbFileAddOnFunc	addOn,
805706f2543Smrg			void *			priv)
806706f2543Smrg{
807706f2543Smrgregister unsigned	i,n;
808706f2543SmrgXkbGeometryPtr		geom;
809706f2543Smrg
810706f2543Smrg    if ((!xkb)||(!xkb->geom)) {
811706f2543Smrg	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
812706f2543Smrg	return FALSE;
813706f2543Smrg    }
814706f2543Smrg    geom= xkb->geom;
815706f2543Smrg    if (geom->name==None)
816706f2543Smrg	 fprintf(file,"xkb_geometry {\n\n");
817706f2543Smrg    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
818706f2543Smrg				XkbAtomText(geom->name,XkbXKBFile));
819706f2543Smrg    fprintf(file,"    width=       %s;\n",
820706f2543Smrg				XkbGeomFPText(geom->width_mm,XkbXKBFile));
821706f2543Smrg    fprintf(file,"    height=      %s;\n\n",
822706f2543Smrg				XkbGeomFPText(geom->height_mm,XkbXKBFile));
823706f2543Smrg
824706f2543Smrg    if (geom->key_aliases!=NULL) {
825706f2543Smrg	XkbKeyAliasPtr	pAl;
826706f2543Smrg	pAl= geom->key_aliases;
827706f2543Smrg	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
828706f2543Smrg	    fprintf(file,"    alias %6s = %6s;\n",
829706f2543Smrg				XkbKeyNameText(pAl->alias,XkbXKBFile),
830706f2543Smrg				XkbKeyNameText(pAl->real,XkbXKBFile));
831706f2543Smrg	}
832706f2543Smrg	fprintf(file,"\n");
833706f2543Smrg    }
834706f2543Smrg
835706f2543Smrg    if (geom->base_color!=NULL)
836706f2543Smrg	fprintf(file,"    baseColor=   \"%s\";\n",
837706f2543Smrg			XkbStringText(geom->base_color->spec,XkbXKBFile));
838706f2543Smrg    if (geom->label_color!=NULL)
839706f2543Smrg	fprintf(file,"    labelColor=  \"%s\";\n",
840706f2543Smrg			XkbStringText(geom->label_color->spec,XkbXKBFile));
841706f2543Smrg    if (geom->label_font!=NULL)
842706f2543Smrg	fprintf(file,"    xfont=       \"%s\";\n",
843706f2543Smrg			XkbStringText(geom->label_font,XkbXKBFile));
844706f2543Smrg    if ((geom->num_colors>0)&&(showImplicit)) {
845706f2543Smrg	XkbColorPtr	color;
846706f2543Smrg	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
847706f2543Smrg		fprintf(file,"//     color[%d]= \"%s\"\n",i,
848706f2543Smrg				XkbStringText(color->spec,XkbXKBFile));
849706f2543Smrg	}
850706f2543Smrg	fprintf(file,"\n");
851706f2543Smrg    }
852706f2543Smrg    if (geom->num_properties>0) {
853706f2543Smrg	XkbPropertyPtr	prop;
854706f2543Smrg	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
855706f2543Smrg	    fprintf(file,"    %s= \"%s\";\n",prop->name,
856706f2543Smrg    				XkbStringText(prop->value,XkbXKBFile));
857706f2543Smrg	}
858706f2543Smrg	fprintf(file,"\n");
859706f2543Smrg    }
860706f2543Smrg    if (geom->num_shapes>0) {
861706f2543Smrg	XkbShapePtr	shape;
862706f2543Smrg	XkbOutlinePtr	outline;
863706f2543Smrg	int		lastR;
864706f2543Smrg	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
865706f2543Smrg	    lastR=0;
866706f2543Smrg	    fprintf(file,"    shape \"%s\" {",
867706f2543Smrg				   XkbAtomText(shape->name,XkbXKBFile));
868706f2543Smrg	    outline= shape->outlines;
869706f2543Smrg	    if (shape->num_outlines>1) {
870706f2543Smrg		for (n=0;n<shape->num_outlines;n++,outline++) {
871706f2543Smrg		    if (n==0)	fprintf(file,"\n");
872706f2543Smrg		    else	fprintf(file,",\n");
873706f2543Smrg		    WriteXKBOutline(file,shape,outline,lastR,8,8);
874706f2543Smrg		    lastR= outline->corner_radius;
875706f2543Smrg		}
876706f2543Smrg		fprintf(file,"\n    };\n");
877706f2543Smrg	    }
878706f2543Smrg	    else {
879706f2543Smrg		WriteXKBOutline(file,NULL,outline,lastR,1,8);
880706f2543Smrg		fprintf(file," };\n");
881706f2543Smrg	    }
882706f2543Smrg	}
883706f2543Smrg    }
884706f2543Smrg    if (geom->num_sections>0) {
885706f2543Smrg	XkbSectionPtr	section;
886706f2543Smrg	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
887706f2543Smrg	    WriteXKBSection(file,section,geom);
888706f2543Smrg	}
889706f2543Smrg    }
890706f2543Smrg    if (geom->num_doodads>0) {
891706f2543Smrg	XkbDoodadPtr	doodad;
892706f2543Smrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
893706f2543Smrg	    WriteXKBDoodad(file,4,geom,doodad);
894706f2543Smrg	}
895706f2543Smrg    }
896706f2543Smrg    if (addOn)
897706f2543Smrg	(*addOn)(file,xkb,topLevel,showImplicit,XkmGeometryIndex,priv);
898706f2543Smrg    fprintf(file,"};\n\n");
899706f2543Smrg    return TRUE;
900706f2543Smrg}
901