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