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