xkbout.c revision 4cd6a3ae
1/************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#elif defined(HAVE_CONFIG_H)
30#include <config.h>
31#endif
32
33#include <stdio.h>
34#include <ctype.h>
35#include <stdlib.h>
36#include <X11/Xfuncs.h>
37
38#ifndef XKB_IN_SERVER
39
40#include <X11/Xlib.h>
41#include <X11/XKBlib.h>
42#include <X11/extensions/XKBgeom.h>
43
44#include "XKMformat.h"
45#include "XKBfileInt.h"
46
47#else
48
49#include <X11/X.h>
50#include <X11/keysym.h>
51#include <X11/Xproto.h>
52#include "misc.h"
53#include "inputstr.h"
54#include "dix.h"
55#include <X11/extensions/XKBstr.h>
56#define XKBSRV_NEED_FILE_FUNCS	1
57#include <X11/extensions/XKBsrv.h>
58
59#include <X11/extensions/XKBgeom.h>
60#include <X11/extensions/XKBfile.h>
61
62#endif
63
64#define	VMOD_HIDE_VALUE	0
65#define	VMOD_SHOW_VALUE	1
66#define	VMOD_COMMENT_VALUE 2
67
68static Bool
69WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue)
70{
71register int 	i,nMods;
72Atom *		vmodNames;
73
74    if (xkb==NULL)
75	return False;
76    if (xkb->names!=NULL)
77	 vmodNames= xkb->names->vmods;
78    else vmodNames= NULL;
79
80    for (i=nMods=0;i<XkbNumVirtualMods;i++) {
81	if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) {
82	    if (nMods==0)	fprintf(file,"    virtual_modifiers ");
83	    else		fprintf(file,",");
84	    fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile));
85	    if ((showValue!=VMOD_HIDE_VALUE)&&
86		(xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
87		if (showValue==VMOD_COMMENT_VALUE) {
88		    fprintf(file,"/* = %s */",
89			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
90		}
91		else  {
92		    fprintf(file,"= %s",
93			XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
94		}
95	    }
96	    nMods++;
97	}
98    }
99    if (nMods>0)
100	fprintf(file,";\n\n");
101    return True;
102}
103
104/***====================================================================***/
105
106static Bool
107WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action)
108{
109XkbDescPtr	xkb;
110Display *	dpy;
111
112    xkb= result->xkb;
113    dpy= xkb->dpy;
114    fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile));
115    return True;
116}
117
118/***====================================================================***/
119
120Bool
121XkbWriteXKBKeycodes(	FILE *			file,
122			XkbFileInfo *		result,
123			Bool			topLevel,
124			Bool			showImplicit,
125			XkbFileAddOnFunc	addOn,
126			void *			priv)
127{
128Atom			kcName;
129register unsigned 	i;
130XkbDescPtr		xkb;
131Display *		dpy;
132const char *		alternate;
133
134    xkb= result->xkb;
135    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
136	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
137	return False;
138    }
139    dpy= xkb->dpy;
140    kcName= xkb->names->keycodes;
141    if (kcName!=None)
142	 fprintf(file,"xkb_keycodes \"%s\" {\n",
143					XkbAtomText(dpy,kcName,XkbXKBFile));
144    else fprintf(file,"xkb_keycodes {\n");
145    fprintf(file,"    minimum = %d;\n",xkb->min_key_code);
146    fprintf(file,"    maximum = %d;\n",xkb->max_key_code);
147    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
148	if (xkb->names->keys[i].name[0]!='\0') {
149	    if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
150		 alternate= "alternate ";
151	    else alternate= "";
152	    fprintf(file,"    %s%6s = %d;\n",alternate,
153			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
154			i);
155	}
156    }
157    if (xkb->indicators!=NULL) {
158	for (i=0;i<XkbNumIndicators;i++) {
159	    const char *type;
160	    if (xkb->indicators->phys_indicators&(1<<i))
161			type= "    ";
162	    else	type= "    virtual ";
163	    if (xkb->names->indicators[i]!=None) {
164		fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
165			XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile));
166	    }
167	}
168    }
169    if (xkb->names->key_aliases!=NULL) {
170	XkbKeyAliasPtr	pAl;
171	pAl= xkb->names->key_aliases;
172	for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
173	    fprintf(file,"    alias %6s = %6s;\n",
174			XkbKeyNameText(pAl->alias,XkbXKBFile),
175			XkbKeyNameText(pAl->real,XkbXKBFile));
176	}
177    }
178    if (addOn)
179	(*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv);
180    fprintf(file,"};\n\n");
181    return True;
182}
183
184Bool
185XkbWriteXKBKeyTypes(	FILE *			file,
186			XkbFileInfo *		result,
187			Bool			topLevel,
188			Bool			showImplicit,
189			XkbFileAddOnFunc	addOn,
190			void *			priv)
191{
192Display *		dpy;
193register unsigned	i,n;
194XkbKeyTypePtr		type;
195XkbKTMapEntryPtr	entry;
196XkbDescPtr		xkb;
197
198    xkb= result->xkb;
199    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
200	_XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
201	return False;
202    }
203    dpy= xkb->dpy;
204    if (xkb->map->num_types<XkbNumRequiredTypes) {
205	_XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0);
206	return 0;
207    }
208    if ((xkb->names==NULL)||(xkb->names->types==None))
209	 fprintf(file,"xkb_types {\n\n");
210    else fprintf(file,"xkb_types \"%s\" {\n\n",
211			XkbAtomText(dpy,xkb->names->types,XkbXKBFile));
212    WriteXKBVModDecl(file,dpy,xkb,
213			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
214
215    type= xkb->map->types;
216    for (i=0;i<xkb->map->num_types;i++,type++) {
217	fprintf(file,"    type \"%s\" {\n",
218		XkbAtomText(dpy,type->name,XkbXKBFile));
219	fprintf(file,"        modifiers= %s;\n",
220	       XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods,
221								XkbXKBFile));
222	entry= type->map;
223	for (n=0;n<type->map_count;n++,entry++) {
224	    char *str;
225	    str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods,
226								XkbXKBFile);
227	    fprintf(file,"        map[%s]= Level%d;\n",str,entry->level+1);
228	    if ((type->preserve)&&((type->preserve[n].real_mods)||
229				   (type->preserve[n].vmods))) {
230		fprintf(file,"        preserve[%s]= ",str);
231		fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb,
232					type->preserve[n].real_mods,
233					type->preserve[n].vmods,
234					XkbXKBFile));
235	    }
236	}
237	if (type->level_names!=NULL) {
238	    Atom *name= type->level_names;
239	    for (n=0;n<type->num_levels;n++,name++) {
240		if ((*name)==None)
241		    continue;
242		fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
243					XkbAtomText(dpy,*name,XkbXKBFile));
244	    }
245	}
246	fprintf(file,"    };\n");
247    }
248    if (addOn)
249	(*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv);
250    fprintf(file,"};\n\n");
251    return True;
252}
253
254static Bool
255WriteXKBIndicatorMap(	FILE *			file,
256			XkbFileInfo *		result,
257			Atom			name,
258			XkbIndicatorMapPtr	led,
259			XkbFileAddOnFunc	addOn,
260			void *			priv)
261{
262XkbDescPtr	xkb;
263char *tmp;
264
265    xkb= result->xkb;
266    tmp = XkbAtomGetString(xkb->dpy, name);
267    fprintf(file,"    indicator \"%s\" {\n",tmp);
268    _XkbFree(tmp);
269    if (led->flags&XkbIM_NoExplicit)
270	fprintf(file,"        !allowExplicit;\n");
271    if (led->flags&XkbIM_LEDDrivesKB)
272	fprintf(file,"        indicatorDrivesKeyboard;\n");
273    if (led->which_groups!=0) {
274	if (led->which_groups!=XkbIM_UseEffective) {
275	    fprintf(file,"        whichGroupState= %s;\n",
276			XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
277	}
278	fprintf(file,"        groups= 0x%02x;\n",led->groups);
279    }
280    if (led->which_mods!=0) {
281	if (led->which_mods!=XkbIM_UseEffective) {
282	    fprintf(file,"        whichModState= %s;\n",
283			XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
284	}
285	fprintf(file,"        modifiers= %s;\n",
286			XkbVModMaskText(xkb->dpy,xkb,
287					led->mods.real_mods,led->mods.vmods,
288					XkbXKBFile));
289    }
290    if (led->ctrls!=0) {
291	fprintf(file,"        controls= %s;\n",
292			XkbControlsMaskText(led->ctrls,XkbXKBFile));
293    }
294    if (addOn)
295	(*addOn)(file,result,False,True,XkmIndicatorsIndex,priv);
296    fprintf(file,"    };\n");
297    return True;
298}
299
300Bool
301XkbWriteXKBCompatMap(	FILE *			file,
302			XkbFileInfo *		result,
303			Bool			topLevel,
304			Bool			showImplicit,
305			XkbFileAddOnFunc	addOn,
306			void *			priv)
307{
308Display *		dpy;
309register unsigned	i;
310XkbSymInterpretPtr	interp;
311XkbDescPtr		xkb;
312
313    xkb= result->xkb;
314    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
315	_XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
316	return False;
317    }
318    dpy= xkb->dpy;
319    if ((xkb->names==NULL)||(xkb->names->compat==None))
320	 fprintf(file,"xkb_compatibility {\n\n");
321    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
322			XkbAtomText(dpy,xkb->names->compat,XkbXKBFile));
323    WriteXKBVModDecl(file,dpy,xkb,
324			(showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE));
325
326    fprintf(file,"    interpret.useModMapMods= AnyLevel;\n");
327    fprintf(file,"    interpret.repeat= False;\n");
328    fprintf(file,"    interpret.locking= False;\n");
329    interp= xkb->compat->sym_interpret;
330    for (i=0;i<xkb->compat->num_si;i++,interp++) {
331	fprintf(file,"    interpret %s+%s(%s) {\n",
332				((interp->sym==NoSymbol)?"Any":
333					XkbKeysymText(interp->sym,XkbXKBFile)),
334				XkbSIMatchText(interp->match,XkbXKBFile),
335				XkbModMaskText(interp->mods,XkbXKBFile));
336	if (interp->virtual_mod!=XkbNoModifier) {
337	    fprintf(file,"        virtualModifier= %s;\n",
338		XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile));
339	}
340	if (interp->match&XkbSI_LevelOneOnly)
341	    fprintf(file,"        useModMapMods=level1;\n");
342	if (interp->flags&XkbSI_LockingKey)
343	    fprintf(file,"        locking= True;\n");
344	if (interp->flags&XkbSI_AutoRepeat)
345	    fprintf(file,"        repeat= True;\n");
346	fprintf(file,"        action= ");
347	WriteXKBAction(file,result,&interp->act);
348	fprintf(file,";\n");
349	fprintf(file,"    };\n");
350    }
351    for (i=0;i<XkbNumKbdGroups;i++) {
352	XkbModsPtr	gc;
353
354	gc= &xkb->compat->groups[i];
355	if ((gc->real_mods==0)&&(gc->vmods==0))
356	    continue;
357	fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb,
358							gc->real_mods,gc->vmods,
359							XkbXKBFile));
360    }
361    if (xkb->indicators) {
362	for (i=0;i<XkbNumIndicators;i++) {
363	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
364	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
365		(map->which_mods!=0)||
366		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
367		(map->ctrls!=0)) {
368		WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map,
369								addOn,priv);
370	    }
371	}
372    }
373    if (addOn)
374	(*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv);
375    fprintf(file,"};\n\n");
376    return True;
377}
378
379Bool
380XkbWriteXKBSymbols(	FILE *			file,
381			XkbFileInfo *		result,
382			Bool			topLevel,
383			Bool			showImplicit,
384			XkbFileAddOnFunc	addOn,
385			void *			priv)
386{
387Display *		dpy;
388register unsigned	i,tmp;
389XkbDescPtr		xkb;
390XkbClientMapPtr		map;
391XkbServerMapPtr		srv;
392Bool			showActions;
393
394    xkb= result->xkb;
395
396    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
397	_XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
398	return False;
399    }
400    if ((!xkb->names)||(!xkb->names->keys)) {
401	_XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
402	return False;
403    }
404
405    map= xkb->map;
406    srv= xkb->server;
407    dpy= xkb->dpy;
408
409    if ((xkb->names==NULL)||(xkb->names->symbols==None))
410	 fprintf(file,"xkb_symbols {\n\n");
411    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
412			XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile));
413    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
414	if (xkb->names->groups[i]!=None) {
415	    fprintf(file,"    name[group%d]=\"%s\";\n",i+1,
416			XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile));
417	    tmp++;
418	}
419    }
420    if (tmp>0)
421	fprintf(file,"\n");
422    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
423	Bool	simple;
424	if ((int)XkbKeyNumSyms(xkb,i)<1)
425	    continue;
426	if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
427	    continue;
428	simple= True;
429	fprintf(file,"    key %6s {",
430			XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
431	if (srv->explicit) {
432	    if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
433	   						(showImplicit)) {
434		int 	typeNdx,g;
435		Bool	multi;
436		const char *	comment="  ";
437
438		if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
439		    comment= "//";
440		multi= False;
441		typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
442		for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
443		    if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
444			multi= True;
445		}
446		if (multi) {
447		    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
448			typeNdx= XkbKeyKeyTypeIndex(xkb,i,g);
449			if (srv->explicit[i]&(1<<g)) {
450			    fprintf(file,"\n%s      type[group%d]= \"%s\",",
451			    	comment,g+1,
452				XkbAtomText(dpy,map->types[typeNdx].name,
453			    	XkbXKBFile));
454			}
455			else if (showImplicit) {
456			    fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
457				XkbAtomText(dpy,map->types[typeNdx].name,
458			    	XkbXKBFile));
459			}
460		    }
461		}
462		else {
463		    fprintf(file,"\n%s      type= \"%s\",",comment,
464				XkbAtomText(dpy,map->types[typeNdx].name,
465			    	XkbXKBFile));
466		}
467		simple= False;
468	    }
469	    if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&&
470		    					  (xkb->ctrls!=NULL)) {
471		if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8)))
472		     fprintf(file,"\n        repeat= Yes,");
473		else fprintf(file,"\n        repeat= No,");
474		simple= False;
475	    }
476	    if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&&
477					(xkb->server->vmodmap[i]!=0)) {
478		if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) {
479		    fprintf(file,"\n        virtualMods= %s,",
480				XkbVModMaskText(dpy,xkb,0,
481						xkb->server->vmodmap[i],
482						XkbXKBFile));
483		}
484		else if (showImplicit) {
485		    fprintf(file,"\n//      virtualMods= %s,",
486				XkbVModMaskText(dpy,xkb,0,
487						xkb->server->vmodmap[i],
488						XkbXKBFile));
489		}
490	    }
491	}
492	switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
493	    case XkbClampIntoRange:
494		fprintf(file,"\n        groupsClamp,");
495		break;
496	    case XkbRedirectIntoRange:
497		fprintf(file,"\n        groupsRedirect= Group%d,",
498			XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
499		break;
500	}
501	if (srv->behaviors!=NULL) {
502	    unsigned type;
503	    type= srv->behaviors[i].type&XkbKB_OpMask;
504
505	    if (type!=XkbKB_Default) {
506		simple= False;
507		fprintf(file,"\n        %s,",
508			XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
509	    }
510	}
511	if ((srv->explicit==NULL) || showImplicit ||
512	    ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
513	     showActions= XkbKeyHasActions(xkb,i);
514	else showActions= False;
515
516	if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
517	    simple= False;
518	if (simple) {
519	    KeySym *syms;
520	    unsigned s;
521
522	    syms= XkbKeySymsPtr(xkb,i);
523	    fprintf(file,"         [ ");
524	    for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
525		if (s!=0)
526		    fprintf(file,", ");
527		fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
528	    }
529	    fprintf(file," ] };\n");
530	}
531	else {
532	    unsigned g,s;
533	    KeySym *syms;
534	    XkbAction *acts;
535	    syms= XkbKeySymsPtr(xkb,i);
536	    acts= XkbKeyActionsPtr(xkb,i);
537	    for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
538		if (g!=0)
539		    fprintf(file,",");
540		fprintf(file,"\n        symbols[Group%d]= [ ",g+1);
541		for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
542		    if (s!=0)
543			fprintf(file,", ");
544		    fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
545		}
546		fprintf(file," ]");
547		syms+= XkbKeyGroupsWidth(xkb,i);
548		if (showActions) {
549		    fprintf(file,",\n        actions[Group%d]= [ ",g+1);
550		    for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
551			if (s!=0)
552			    fprintf(file,", ");
553			WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]);
554		    }
555		    fprintf(file," ]");
556		    acts+= XkbKeyGroupsWidth(xkb,i);
557		}
558	    }
559	    fprintf(file,"\n    };\n");
560	}
561    }
562    if (map && map->modmap) {
563	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
564	    if (map->modmap[i]!=0) {
565		register int n,bit;
566		for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
567		    if (map->modmap[i]&bit) {
568			char buf[5];
569			memcpy(buf,xkb->names->keys[i].name,4);
570			buf[4]= '\0';
571			fprintf(file,"    modifier_map %s { <%s> };\n",
572					XkbModIndexText(n,XkbXKBFile),buf);
573		    }
574		}
575	    }
576	}
577    }
578    if (addOn)
579	(*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv);
580    fprintf(file,"};\n\n");
581    return True;
582}
583
584static Bool
585WriteXKBOutline(	FILE *		file,
586			XkbShapePtr	shape,
587			XkbOutlinePtr	outline,
588			int		lastRadius,
589			int		first,
590			int		indent)
591{
592register int	i;
593XkbPointPtr	pt;
594char *		iStr;
595
596    fprintf(file,"%s",iStr= XkbIndentText(first));
597    if (first!=indent)
598	iStr= XkbIndentText(indent);
599    if (outline->corner_radius!=lastRadius) {
600	fprintf(file,"corner= %s,",
601			XkbGeomFPText(outline->corner_radius,XkbMessage));
602	if (shape!=NULL) {
603	    fprintf(file,"\n%s",iStr);
604	}
605    }
606    if (shape) {
607	if (outline==shape->approx)
608	    fprintf(file,"approx= ");
609	else if (outline==shape->primary)
610	    fprintf(file,"primary= ");
611    }
612    fprintf(file,"{");
613    for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) {
614	if (i==0)		fprintf(file," ");
615	else if ((i%4)==0)	fprintf(file,",\n%s  ",iStr);
616	else			fprintf(file,", ");
617	fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile),
618				  XkbGeomFPText(pt->y,XkbXKBFile));
619    }
620    fprintf(file," }");
621    return True;
622}
623
624static Bool
625WriteXKBDoodad(	FILE *		file,
626		Display *	dpy,
627		unsigned	indent,
628		XkbGeometryPtr	geom,
629		XkbDoodadPtr	doodad)
630{
631register char *	i_str;
632XkbShapePtr	shape;
633XkbColorPtr	color;
634
635    i_str= XkbIndentText(indent);
636    fprintf(file,"%s%s \"%s\" {\n",i_str,
637				XkbDoodadTypeText(doodad->any.type,XkbMessage),
638				XkbAtomText(dpy,doodad->any.name,XkbMessage));
639    fprintf(file,"%s    top=      %s;\n",i_str,
640				 XkbGeomFPText(doodad->any.top,XkbXKBFile));
641    fprintf(file,"%s    left=     %s;\n",i_str,
642				XkbGeomFPText(doodad->any.left,XkbXKBFile));
643    fprintf(file,"%s    priority= %d;\n",i_str,doodad->any.priority);
644    switch (doodad->any.type) {
645	case XkbOutlineDoodad:
646	case XkbSolidDoodad:
647	    if (doodad->shape.angle!=0) {
648		fprintf(file,"%s    angle=  %s;\n",i_str,
649			     XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
650	    }
651	    if (doodad->shape.color_ndx!=0) {
652		fprintf(file,"%s    color= \"%s\";\n",i_str,
653			     XkbShapeDoodadColor(geom,&doodad->shape)->spec);
654	    }
655	    shape= XkbShapeDoodadShape(geom,&doodad->shape);
656	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
657			    XkbAtomText(dpy,shape->name,XkbXKBFile));
658	    break;
659	case XkbTextDoodad:
660	    if (doodad->text.angle!=0) {
661		fprintf(file,"%s    angle=  %s;\n",i_str,
662			     XkbGeomFPText(doodad->text.angle,XkbXKBFile));
663	    }
664	    if (doodad->text.width!=0) {
665		fprintf(file,"%s    width=  %s;\n",i_str,
666			     XkbGeomFPText(doodad->text.width,XkbXKBFile));
667
668	    }
669	    if (doodad->text.height!=0) {
670		fprintf(file,"%s    height=  %s;\n",i_str,
671			     XkbGeomFPText(doodad->text.height,XkbXKBFile));
672
673	    }
674	    if (doodad->text.color_ndx!=0) {
675		color= XkbTextDoodadColor(geom,&doodad->text);
676		fprintf(file,"%s    color= \"%s\";\n",i_str,
677			     XkbStringText(color->spec,XkbXKBFile));
678	    }
679	    fprintf(file,"%s    XFont= \"%s\";\n",i_str,
680	    		     XkbStringText(doodad->text.font,XkbXKBFile));
681	    fprintf(file,"%s    text=  \"%s\";\n",i_str,
682	    		    XkbStringText(doodad->text.text,XkbXKBFile));
683	    break;
684	case XkbIndicatorDoodad:
685	    shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
686	    color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator);
687	    fprintf(file,"%s    onColor= \"%s\";\n",i_str,
688	    		    XkbStringText(color->spec,XkbXKBFile));
689	    color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
690	    fprintf(file,"%s    offColor= \"%s\";\n",i_str,
691	    		    XkbStringText(color->spec,XkbXKBFile));
692	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
693			     XkbAtomText(dpy,shape->name,XkbXKBFile));
694	    break;
695	case XkbLogoDoodad:
696	    fprintf(file,"%s    logoName= \"%s\";\n",i_str,
697			     XkbStringText(doodad->logo.logo_name,XkbXKBFile));
698	    if (doodad->shape.angle!=0) {
699		fprintf(file,"%s    angle=  %s;\n",i_str,
700			     XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
701	    }
702	    if (doodad->shape.color_ndx!=0) {
703		fprintf(file,"%s    color= \"%s\";\n",i_str,
704			     XkbLogoDoodadColor(geom,&doodad->logo)->spec);
705	    }
706	    shape= XkbLogoDoodadShape(geom,&doodad->logo);
707	    fprintf(file,"%s    shape= \"%s\";\n",i_str,
708			    XkbAtomText(dpy,shape->name,XkbXKBFile));
709	    break;
710    }
711    fprintf(file,"%s};\n",i_str);
712    return True;
713}
714
715/*ARGSUSED*/
716static Bool
717WriteXKBOverlay(	FILE *		file,
718			Display *	dpy,
719			unsigned	indent,
720			XkbGeometryPtr	geom,
721			XkbOverlayPtr	ol)
722{
723register char *		i_str;
724int			r,k,nOut;
725XkbOverlayRowPtr	row;
726XkbOverlayKeyPtr	key;
727
728    i_str= XkbIndentText(indent);
729    if (ol->name!=None) {
730	 fprintf(file,"%soverlay \"%s\" {\n",i_str,
731    					XkbAtomText(dpy,ol->name,XkbMessage));
732    }
733    else fprintf(file,"%soverlay {\n",i_str);
734    for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
735	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
736	    char *over,*under;
737	    over= XkbKeyNameText(key->over.name,XkbXKBFile);
738	    under= XkbKeyNameText(key->under.name,XkbXKBFile);
739	    if (nOut==0)
740		 fprintf(file,"%s    %6s=%6s",i_str,under,over);
741	    else if ((nOut%4)==0)
742		 fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
743	    else fprintf(file,", %6s=%6s",under,over);
744	    nOut++;
745	}
746    }
747    fprintf(file,"\n%s};\n",i_str);
748    return True;
749}
750
751static Bool
752WriteXKBSection(	FILE *		file,
753			Display *	dpy,
754			XkbSectionPtr 	s,
755			XkbGeometryPtr	geom)
756{
757register int	i;
758XkbRowPtr	row;
759int		dfltKeyColor = 0;
760
761    fprintf(file,"    section \"%s\" {\n",
762				XkbAtomText(dpy,s->name,XkbXKBFile));
763    if (s->rows&&(s->rows->num_keys>0)) {
764	dfltKeyColor= s->rows->keys[0].color_ndx;
765	fprintf(file,"        key.color= \"%s\";\n",
766		XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile));
767    }
768    fprintf(file,"        priority=  %d;\n",s->priority);
769    fprintf(file,"        top=       %s;\n",XkbGeomFPText(s->top,XkbXKBFile));
770    fprintf(file,"        left=      %s;\n",XkbGeomFPText(s->left,XkbXKBFile));
771    fprintf(file,"        width=     %s;\n",XkbGeomFPText(s->width,XkbXKBFile));
772    fprintf(file,"        height=    %s;\n",
773					XkbGeomFPText(s->height,XkbXKBFile));
774    if (s->angle!=0) {
775	fprintf(file,"        angle=  %s;\n",
776					XkbGeomFPText(s->angle,XkbXKBFile));
777    }
778    for (i=0,row=s->rows;row&&i<s->num_rows;i++,row++) {
779	fprintf(file,"        row {\n");
780	fprintf(file,"            top=  %s;\n",
781					XkbGeomFPText(row->top,XkbXKBFile));
782	fprintf(file,"            left= %s;\n",
783					XkbGeomFPText(row->left,XkbXKBFile));
784	if (row->vertical)
785	    fprintf(file,"            vertical;\n");
786	if (row->num_keys>0) {
787	    register int 	k;
788	    register XkbKeyPtr	key;
789	    int			forceNL=0;
790	    int			nThisLine= 0;
791	    fprintf(file,"            keys {\n");
792	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
793		XkbShapePtr	shape;
794		if (key->color_ndx!=dfltKeyColor)
795		    forceNL= 1;
796		if (k==0) {
797		     fprintf(file,"                ");
798		     nThisLine= 0;
799		}
800		else if (((nThisLine%2)==1)||(forceNL)) {
801		     fprintf(file,",\n                ");
802		     forceNL= nThisLine= 0;
803		}
804		else {
805		     fprintf(file,", ");
806		     nThisLine++;
807		}
808		shape= XkbKeyShape(geom,key);
809		fprintf(file,"{ %6s, \"%s\", %3s",
810		      XkbKeyNameText(key->name.name,XkbXKBFile),
811		      XkbAtomText(dpy,shape->name,XkbXKBFile),
812		      XkbGeomFPText(key->gap,XkbXKBFile));
813		if (key->color_ndx!=dfltKeyColor) {
814		    fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
815		    forceNL= 1;
816		}
817		fprintf(file," }");
818	    }
819	    fprintf(file,"\n            };\n");
820	}
821	fprintf(file,"        };\n");
822    }
823    if (s->doodads!=NULL) {
824	XkbDoodadPtr	doodad;
825	for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
826	    WriteXKBDoodad(file,dpy,8,geom,doodad);
827	}
828    }
829    if (s->overlays!=NULL) {
830	XkbOverlayPtr	ol;
831	for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
832	    WriteXKBOverlay(file,dpy,8,geom,ol);
833	}
834    }
835    fprintf(file,"    }; // End of \"%s\" section\n\n",
836				XkbAtomText(dpy,s->name,XkbXKBFile));
837    return True;
838}
839
840Bool
841XkbWriteXKBGeometry(	FILE *			file,
842			XkbFileInfo *		result,
843			Bool			topLevel,
844			Bool			showImplicit,
845			XkbFileAddOnFunc	addOn,
846			void *			priv)
847{
848Display *		dpy;
849register unsigned	i,n;
850XkbDescPtr		xkb;
851XkbGeometryPtr		geom;
852
853    xkb= result->xkb;
854    if ((!xkb)||(!xkb->geom)) {
855	_XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
856 	return False;
857    }
858    dpy= xkb->dpy;
859    geom= xkb->geom;
860    if (geom->name==None)
861	 fprintf(file,"xkb_geometry {\n\n");
862    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
863				XkbAtomText(dpy,geom->name,XkbXKBFile));
864    fprintf(file,"    width=       %s;\n",
865				XkbGeomFPText(geom->width_mm,XkbXKBFile));
866    fprintf(file,"    height=      %s;\n\n",
867				XkbGeomFPText(geom->height_mm,XkbXKBFile));
868
869    if (geom->key_aliases!=NULL) {
870	XkbKeyAliasPtr	pAl;
871	pAl= geom->key_aliases;
872	for (i=0;i<geom->num_key_aliases;i++,pAl++) {
873	    fprintf(file,"    alias %6s = %6s;\n",
874				XkbKeyNameText(pAl->alias,XkbXKBFile),
875				XkbKeyNameText(pAl->real,XkbXKBFile));
876	}
877	fprintf(file,"\n");
878    }
879
880    if (geom->base_color!=NULL)
881	fprintf(file,"    baseColor=   \"%s\";\n",
882			XkbStringText(geom->base_color->spec,XkbXKBFile));
883    if (geom->label_color!=NULL)
884	fprintf(file,"    labelColor=  \"%s\";\n",
885			XkbStringText(geom->label_color->spec,XkbXKBFile));
886    if (geom->label_font!=NULL)
887	fprintf(file,"    xfont=       \"%s\";\n",
888			XkbStringText(geom->label_font,XkbXKBFile));
889    if ((geom->num_colors>0)&&(showImplicit)) {
890	XkbColorPtr	color;
891	for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) {
892		fprintf(file,"//     color[%d]= \"%s\"\n",i,
893				XkbStringText(color->spec,XkbXKBFile));
894	}
895	fprintf(file,"\n");
896    }
897    if (geom->num_properties>0) {
898	XkbPropertyPtr	prop;
899	for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) {
900	    fprintf(file,"    %s= \"%s\";\n",prop->name,
901    				XkbStringText(prop->value,XkbXKBFile));
902	}
903	fprintf(file,"\n");
904    }
905    if (geom->num_shapes>0) {
906	XkbShapePtr	shape;
907	XkbOutlinePtr	outline;
908	int		lastR;
909	for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
910	    lastR=0;
911	    fprintf(file,"    shape \"%s\" {",
912				   XkbAtomText(dpy,shape->name,XkbXKBFile));
913	    outline= shape->outlines;
914	    if (shape->num_outlines>1) {
915		for (n=0;n<shape->num_outlines;n++,outline++) {
916		    if (n==0)	fprintf(file,"\n");
917		    else	fprintf(file,",\n");
918		    WriteXKBOutline(file,shape,outline,lastR,8,8);
919		    lastR= outline->corner_radius;
920		}
921		fprintf(file,"\n    };\n");
922	    }
923	    else {
924		WriteXKBOutline(file,NULL,outline,lastR,1,8);
925		fprintf(file," };\n");
926	    }
927	}
928    }
929    if (geom->num_sections>0) {
930	XkbSectionPtr	section;
931	for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
932	    WriteXKBSection(file,dpy,section,geom);
933	}
934    }
935    if (geom->num_doodads>0) {
936	XkbDoodadPtr	doodad;
937	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
938	    WriteXKBDoodad(file,dpy,4,geom,doodad);
939	}
940    }
941    if (addOn)
942	(*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv);
943    fprintf(file,"};\n\n");
944    return True;
945}
946
947/*ARGSUSED*/
948Bool
949XkbWriteXKBSemantics(	FILE *			file,
950			XkbFileInfo *		result,
951			Bool			topLevel,
952			Bool			showImplicit,
953			XkbFileAddOnFunc	addOn,
954			void *			priv)
955{
956Bool		ok;
957
958    fprintf(file,"xkb_semantics {\n");
959    ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv);
960    ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv);
961    fprintf(file,"};\n");
962    return ok;
963}
964
965/*ARGSUSED*/
966Bool
967XkbWriteXKBLayout(	FILE *			file,
968			XkbFileInfo *		result,
969			Bool			topLevel,
970			Bool			showImplicit,
971			XkbFileAddOnFunc	addOn,
972			void *			priv)
973{
974Bool		ok;
975XkbDescPtr	xkb;
976
977    xkb= result->xkb;
978    fprintf(file,"xkb_layout {\n");
979    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
980    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
981    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
982    if (xkb->geom)
983	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
984    fprintf(file,"};\n");
985    return ok;
986}
987
988/*ARGSUSED*/
989Bool
990XkbWriteXKBKeymap(	FILE *			file,
991			XkbFileInfo *		result,
992			Bool			topLevel,
993			Bool			showImplicit,
994			XkbFileAddOnFunc	addOn,
995			void *			priv)
996{
997Bool		ok;
998XkbDescPtr	xkb;
999
1000    xkb= result->xkb;
1001    fprintf(file,"xkb_keymap {\n");
1002    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
1003    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
1004    ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv);
1005    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
1006    if (xkb->geom)
1007	ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
1008    fprintf(file,"};\n");
1009    return ok;
1010}
1011
1012Bool
1013XkbWriteXKBFile(	FILE *			out,
1014			XkbFileInfo *		result,
1015			Bool			showImplicit,
1016			XkbFileAddOnFunc	addOn,
1017			void *			priv)
1018{
1019Bool	 		ok = False;
1020Bool			(*func)(
1021    FILE *		/* file */,
1022    XkbFileInfo *	/* result */,
1023    Bool		/* topLevel */,
1024    Bool		/* showImplicit */,
1025    XkbFileAddOnFunc	/* addOn */,
1026    void *		/* priv */
1027) = NULL;
1028
1029    switch (result->type) {
1030	case XkmSemanticsFile:
1031	    func= XkbWriteXKBSemantics;
1032	    break;
1033	case XkmLayoutFile:
1034	    func= XkbWriteXKBLayout;
1035	    break;
1036	case XkmKeymapFile:
1037	    func= XkbWriteXKBKeymap;
1038	    break;
1039	case XkmTypesIndex:
1040	    func= XkbWriteXKBKeyTypes;
1041	    break;
1042	case XkmCompatMapIndex:
1043	    func= XkbWriteXKBCompatMap;
1044	    break;
1045	case XkmSymbolsIndex:
1046	    func= XkbWriteXKBSymbols;
1047	    break;
1048	case XkmKeyNamesIndex:
1049	    func= XkbWriteXKBKeycodes;
1050	    break;
1051	case XkmGeometryFile:
1052	case XkmGeometryIndex:
1053	    func= XkbWriteXKBGeometry;
1054	    break;
1055	case XkmVirtualModsIndex:
1056	case XkmIndicatorsIndex:
1057	    _XkbLibError(_XkbErrBadImplementation,
1058	    		XkbConfigText(result->type,XkbMessage),0);
1059	    return False;
1060    }
1061    if (out==NULL) {
1062	_XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0);
1063	ok= False;
1064    }
1065    else if (func) {
1066	ok= (*func)(out,result,True,showImplicit,addOn,priv);
1067    }
1068    return ok;
1069}
1070