18c9fbc29Smrg/************************************************************
28c9fbc29Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
38c9fbc29Smrg
48c9fbc29Smrg Permission to use, copy, modify, and distribute this
58c9fbc29Smrg software and its documentation for any purpose and without
68c9fbc29Smrg fee is hereby granted, provided that the above copyright
78c9fbc29Smrg notice appear in all copies and that both that copyright
88c9fbc29Smrg notice and this permission notice appear in supporting
94cd6a3aeSmrg documentation, and that the name of Silicon Graphics not be
104cd6a3aeSmrg used in advertising or publicity pertaining to distribution
118c9fbc29Smrg of the software without specific prior written permission.
124cd6a3aeSmrg Silicon Graphics makes no representation about the suitability
138c9fbc29Smrg of this software for any purpose. It is provided "as is"
148c9fbc29Smrg without any express or implied warranty.
154cd6a3aeSmrg
164cd6a3aeSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
174cd6a3aeSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
188c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
194cd6a3aeSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
204cd6a3aeSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
214cd6a3aeSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
228c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
238c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
248c9fbc29Smrg
258c9fbc29Smrg ********************************************************/
268c9fbc29Smrg
278c9fbc29Smrg#ifdef HAVE_DIX_CONFIG_H
288c9fbc29Smrg#include <dix-config.h>
298c9fbc29Smrg#elif defined(HAVE_CONFIG_H)
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg
338c9fbc29Smrg#include <stdio.h>
348c9fbc29Smrg#include <ctype.h>
358c9fbc29Smrg#include <stdlib.h>
368c9fbc29Smrg#include <X11/Xfuncs.h>
378c9fbc29Smrg
388c9fbc29Smrg
398c9fbc29Smrg#include <X11/Xlib.h>
408c9fbc29Smrg#include <X11/XKBlib.h>
418c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
428c9fbc29Smrg
438c9fbc29Smrg#include "XKMformat.h"
448c9fbc29Smrg#include "XKBfileInt.h"
458c9fbc29Smrg
468c9fbc29Smrg
478c9fbc29Smrg#define	VMOD_HIDE_VALUE	0
488c9fbc29Smrg#define	VMOD_SHOW_VALUE	1
498c9fbc29Smrg#define	VMOD_COMMENT_VALUE 2
508c9fbc29Smrg
518c9fbc29Smrgstatic Bool
5270728a38SmrgWriteXKBVModDecl(FILE *file, Display *dpy, XkbDescPtr xkb, int showValue)
538c9fbc29Smrg{
5470728a38Smrg    register int i, nMods;
5570728a38Smrg    Atom *vmodNames;
5670728a38Smrg
5770728a38Smrg    if (xkb == NULL)
5870728a38Smrg        return False;
5970728a38Smrg    if (xkb->names != NULL)
6070728a38Smrg        vmodNames = xkb->names->vmods;
6170728a38Smrg    else
6270728a38Smrg        vmodNames = NULL;
6370728a38Smrg
6470728a38Smrg    for (i = nMods = 0; i < XkbNumVirtualMods; i++) {
6570728a38Smrg        if ((vmodNames != NULL) && (vmodNames[i] != None)) {
6670728a38Smrg            if (nMods == 0)
6770728a38Smrg                fprintf(file, "    virtual_modifiers ");
6870728a38Smrg            else
6970728a38Smrg                fprintf(file, ",");
7070728a38Smrg            fprintf(file, "%s", XkbAtomText(dpy, vmodNames[i], XkbXKBFile));
7170728a38Smrg            if ((showValue != VMOD_HIDE_VALUE) &&
7270728a38Smrg                (xkb->server) && (xkb->server->vmods[i] != XkbNoModifierMask)) {
7370728a38Smrg                if (showValue == VMOD_COMMENT_VALUE) {
7470728a38Smrg                    fprintf(file, "/* = %s */",
7570728a38Smrg                            XkbModMaskText(xkb->server->vmods[i], XkbXKBFile));
7670728a38Smrg                }
7770728a38Smrg                else {
7870728a38Smrg                    fprintf(file, "= %s",
7970728a38Smrg                            XkbModMaskText(xkb->server->vmods[i], XkbXKBFile));
8070728a38Smrg                }
8170728a38Smrg            }
8270728a38Smrg            nMods++;
8370728a38Smrg        }
848c9fbc29Smrg    }
8570728a38Smrg    if (nMods > 0)
8670728a38Smrg        fprintf(file, ";\n\n");
878c9fbc29Smrg    return True;
888c9fbc29Smrg}
898c9fbc29Smrg
908c9fbc29Smrg/***====================================================================***/
918c9fbc29Smrg
928c9fbc29Smrgstatic Bool
9370728a38SmrgWriteXKBAction(FILE *file, XkbFileInfo *result, XkbAnyAction *action)
948c9fbc29Smrg{
9570728a38Smrg    XkbDescPtr xkb;
9670728a38Smrg    Display *dpy;
978c9fbc29Smrg
9870728a38Smrg    xkb = result->xkb;
9970728a38Smrg    dpy = xkb->dpy;
10070728a38Smrg    fprintf(file, "%s",
10170728a38Smrg            XkbActionText(dpy, xkb, (XkbAction *) action, XkbXKBFile));
1028c9fbc29Smrg    return True;
1038c9fbc29Smrg}
1048c9fbc29Smrg
1058c9fbc29Smrg/***====================================================================***/
1068c9fbc29Smrg
1078c9fbc29SmrgBool
10870728a38SmrgXkbWriteXKBKeycodes(FILE *              file,
10970728a38Smrg                    XkbFileInfo *       result,
11070728a38Smrg                    Bool                topLevel,
11170728a38Smrg                    Bool                showImplicit,
11270728a38Smrg                    XkbFileAddOnFunc    addOn,
11370728a38Smrg                    void *              priv)
1148c9fbc29Smrg{
11570728a38Smrg    Atom kcName;
11670728a38Smrg    register unsigned i;
11770728a38Smrg    XkbDescPtr xkb;
11870728a38Smrg    Display *dpy;
11970728a38Smrg    const char *alternate;
12070728a38Smrg
12170728a38Smrg    xkb = result->xkb;
12270728a38Smrg    if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) {
12370728a38Smrg        _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBKeycodes", 0);
12470728a38Smrg        return False;
1258c9fbc29Smrg    }
12670728a38Smrg    dpy = xkb->dpy;
12770728a38Smrg    kcName = xkb->names->keycodes;
12870728a38Smrg    if (kcName != None)
12970728a38Smrg        fprintf(file, "xkb_keycodes \"%s\" {\n",
13070728a38Smrg                XkbAtomText(dpy, kcName, XkbXKBFile));
13170728a38Smrg    else
13270728a38Smrg        fprintf(file, "xkb_keycodes {\n");
13370728a38Smrg    fprintf(file, "    minimum = %d;\n", xkb->min_key_code);
13470728a38Smrg    fprintf(file, "    maximum = %d;\n", xkb->max_key_code);
13570728a38Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
13670728a38Smrg        if (xkb->names->keys[i].name[0] != '\0') {
13770728a38Smrg            if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, True) != i)
13870728a38Smrg                alternate = "alternate ";
13970728a38Smrg            else
14070728a38Smrg                alternate = "";
14170728a38Smrg            fprintf(file, "    %s%6s = %d;\n", alternate,
14270728a38Smrg                    XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile), i);
14370728a38Smrg        }
1448c9fbc29Smrg    }
14570728a38Smrg    if (xkb->indicators != NULL) {
14670728a38Smrg        for (i = 0; i < XkbNumIndicators; i++) {
14770728a38Smrg            const char *type;
14870728a38Smrg
14970728a38Smrg            if (xkb->indicators->phys_indicators & (1 << i))
15070728a38Smrg                type = "    ";
15170728a38Smrg            else
15270728a38Smrg                type = "    virtual ";
15370728a38Smrg            if (xkb->names->indicators[i] != None) {
15470728a38Smrg                fprintf(file, "%sindicator %d = \"%s\";\n", type, i + 1,
15570728a38Smrg                        XkbAtomText(dpy, xkb->names->indicators[i],
15670728a38Smrg                                    XkbXKBFile));
15770728a38Smrg            }
15870728a38Smrg        }
1598c9fbc29Smrg    }
16070728a38Smrg    if (xkb->names->key_aliases != NULL) {
16170728a38Smrg        XkbKeyAliasPtr pAl;
16270728a38Smrg
16370728a38Smrg        pAl = xkb->names->key_aliases;
16470728a38Smrg        for (i = 0; i < xkb->names->num_key_aliases; i++, pAl++) {
16570728a38Smrg            fprintf(file, "    alias %6s = %6s;\n",
16670728a38Smrg                    XkbKeyNameText(pAl->alias, XkbXKBFile),
16770728a38Smrg                    XkbKeyNameText(pAl->real, XkbXKBFile));
16870728a38Smrg        }
1698c9fbc29Smrg    }
1708c9fbc29Smrg    if (addOn)
17170728a38Smrg        (*addOn) (file, result, topLevel, showImplicit, XkmKeyNamesIndex, priv);
17270728a38Smrg    fprintf(file, "};\n\n");
1738c9fbc29Smrg    return True;
1748c9fbc29Smrg}
1758c9fbc29Smrg
1768c9fbc29SmrgBool
17770728a38SmrgXkbWriteXKBKeyTypes(FILE *              file,
17870728a38Smrg                    XkbFileInfo *       result,
17970728a38Smrg                    Bool                topLevel,
18070728a38Smrg                    Bool                showImplicit,
18170728a38Smrg                    XkbFileAddOnFunc    addOn,
18270728a38Smrg                    void *              priv)
1838c9fbc29Smrg{
18470728a38Smrg    Display *dpy;
18570728a38Smrg    register unsigned i, n;
18670728a38Smrg    XkbKeyTypePtr type;
18770728a38Smrg    XkbKTMapEntryPtr entry;
18870728a38Smrg    XkbDescPtr xkb;
18970728a38Smrg
19070728a38Smrg    xkb = result->xkb;
19170728a38Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->types)) {
19270728a38Smrg        _XkbLibError(_XkbErrMissingTypes, "XkbWriteXKBKeyTypes", 0);
19370728a38Smrg        return False;
1948c9fbc29Smrg    }
19570728a38Smrg    dpy = xkb->dpy;
19670728a38Smrg    if (xkb->map->num_types < XkbNumRequiredTypes) {
19770728a38Smrg        _XkbLibError(_XkbErrMissingReqTypes, "XkbWriteXKBKeyTypes", 0);
19870728a38Smrg        return 0;
1998c9fbc29Smrg    }
20070728a38Smrg    if ((xkb->names == NULL) || (xkb->names->types == None))
20170728a38Smrg        fprintf(file, "xkb_types {\n\n");
20270728a38Smrg    else
20370728a38Smrg        fprintf(file, "xkb_types \"%s\" {\n\n",
20470728a38Smrg                XkbAtomText(dpy, xkb->names->types, XkbXKBFile));
20570728a38Smrg    WriteXKBVModDecl(file, dpy, xkb,
20670728a38Smrg                     (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE));
20770728a38Smrg
20870728a38Smrg    type = xkb->map->types;
20970728a38Smrg    for (i = 0; i < xkb->map->num_types; i++, type++) {
21070728a38Smrg        fprintf(file, "    type \"%s\" {\n",
21170728a38Smrg                XkbAtomText(dpy, type->name, XkbXKBFile));
21270728a38Smrg        fprintf(file, "        modifiers= %s;\n",
21370728a38Smrg                XkbVModMaskText(dpy, xkb, type->mods.real_mods,
21470728a38Smrg                                type->mods.vmods, XkbXKBFile));
21570728a38Smrg        entry = type->map;
21670728a38Smrg        for (n = 0; n < type->map_count; n++, entry++) {
21770728a38Smrg            char *str;
21870728a38Smrg
21970728a38Smrg            str =
22070728a38Smrg                XkbVModMaskText(dpy, xkb, entry->mods.real_mods,
22170728a38Smrg                                entry->mods.vmods, XkbXKBFile);
22270728a38Smrg            fprintf(file, "        map[%s]= Level%d;\n", str, entry->level + 1);
22370728a38Smrg            if ((type->preserve) && ((type->preserve[n].real_mods) ||
22470728a38Smrg                                     (type->preserve[n].vmods))) {
22570728a38Smrg                fprintf(file, "        preserve[%s]= ", str);
22670728a38Smrg                fprintf(file, "%s;\n", XkbVModMaskText(dpy, xkb,
22770728a38Smrg                                                       type->preserve[n].
22870728a38Smrg                                                       real_mods,
22970728a38Smrg                                                       type->preserve[n].vmods,
23070728a38Smrg                                                       XkbXKBFile));
23170728a38Smrg            }
23270728a38Smrg        }
23370728a38Smrg        if (type->level_names != NULL) {
23470728a38Smrg            Atom *name = type->level_names;
23570728a38Smrg
23670728a38Smrg            for (n = 0; n < type->num_levels; n++, name++) {
23770728a38Smrg                if ((*name) == None)
23870728a38Smrg                    continue;
23970728a38Smrg                fprintf(file, "        level_name[Level%d]= \"%s\";\n", n + 1,
24070728a38Smrg                        XkbAtomText(dpy, *name, XkbXKBFile));
24170728a38Smrg            }
24270728a38Smrg        }
24370728a38Smrg        fprintf(file, "    };\n");
2448c9fbc29Smrg    }
2458c9fbc29Smrg    if (addOn)
24670728a38Smrg        (*addOn) (file, result, topLevel, showImplicit, XkmTypesIndex, priv);
24770728a38Smrg    fprintf(file, "};\n\n");
2488c9fbc29Smrg    return True;
2498c9fbc29Smrg}
2508c9fbc29Smrg
2518c9fbc29Smrgstatic Bool
25270728a38SmrgWriteXKBIndicatorMap(FILE *             file,
25370728a38Smrg                     XkbFileInfo *      result,
25470728a38Smrg                     Atom               name,
25570728a38Smrg                     XkbIndicatorMapPtr led,
25670728a38Smrg                     XkbFileAddOnFunc   addOn,
25770728a38Smrg                     void *             priv)
2588c9fbc29Smrg{
25970728a38Smrg    XkbDescPtr xkb;
26070728a38Smrg    char *tmp;
2618c9fbc29Smrg
26270728a38Smrg    xkb = result->xkb;
2638c9fbc29Smrg    tmp = XkbAtomGetString(xkb->dpy, name);
26470728a38Smrg    fprintf(file, "    indicator \"%s\" {\n", tmp);
2658c9fbc29Smrg    _XkbFree(tmp);
26670728a38Smrg    if (led->flags & XkbIM_NoExplicit)
26770728a38Smrg        fprintf(file, "        !allowExplicit;\n");
26870728a38Smrg    if (led->flags & XkbIM_LEDDrivesKB)
26970728a38Smrg        fprintf(file, "        indicatorDrivesKeyboard;\n");
27070728a38Smrg    if (led->which_groups != 0) {
27170728a38Smrg        if (led->which_groups != XkbIM_UseEffective) {
27270728a38Smrg            fprintf(file, "        whichGroupState= %s;\n",
27370728a38Smrg                    XkbIMWhichStateMaskText(led->which_groups, XkbXKBFile));
27470728a38Smrg        }
27570728a38Smrg        fprintf(file, "        groups= 0x%02x;\n", led->groups);
2768c9fbc29Smrg    }
27770728a38Smrg    if (led->which_mods != 0) {
27870728a38Smrg        if (led->which_mods != XkbIM_UseEffective) {
27970728a38Smrg            fprintf(file, "        whichModState= %s;\n",
28070728a38Smrg                    XkbIMWhichStateMaskText(led->which_mods, XkbXKBFile));
28170728a38Smrg        }
28270728a38Smrg        fprintf(file, "        modifiers= %s;\n",
28370728a38Smrg                XkbVModMaskText(xkb->dpy, xkb,
28470728a38Smrg                                led->mods.real_mods, led->mods.vmods,
28570728a38Smrg                                XkbXKBFile));
2868c9fbc29Smrg    }
28770728a38Smrg    if (led->ctrls != 0) {
28870728a38Smrg        fprintf(file, "        controls= %s;\n",
28970728a38Smrg                XkbControlsMaskText(led->ctrls, XkbXKBFile));
2908c9fbc29Smrg    }
2918c9fbc29Smrg    if (addOn)
29270728a38Smrg        (*addOn) (file, result, False, True, XkmIndicatorsIndex, priv);
29370728a38Smrg    fprintf(file, "    };\n");
2948c9fbc29Smrg    return True;
2958c9fbc29Smrg}
2968c9fbc29Smrg
2978c9fbc29SmrgBool
29870728a38SmrgXkbWriteXKBCompatMap(FILE *             file,
29970728a38Smrg                     XkbFileInfo *      result,
30070728a38Smrg                     Bool               topLevel,
30170728a38Smrg                     Bool               showImplicit,
30270728a38Smrg                     XkbFileAddOnFunc   addOn,
30370728a38Smrg                     void *             priv)
3048c9fbc29Smrg{
30570728a38Smrg    Display *           dpy;
30670728a38Smrg    register unsigned   i;
30770728a38Smrg    XkbSymInterpretPtr  interp;
30870728a38Smrg    XkbDescPtr          xkb;
30970728a38Smrg
31070728a38Smrg    xkb = result->xkb;
31170728a38Smrg    if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) {
31270728a38Smrg        _XkbLibError(_XkbErrMissingCompatMap, "XkbWriteXKBCompatMap", 0);
31370728a38Smrg        return False;
3148c9fbc29Smrg    }
31570728a38Smrg    dpy = xkb->dpy;
31670728a38Smrg    if ((xkb->names == NULL) || (xkb->names->compat == None))
31770728a38Smrg        fprintf(file, "xkb_compatibility {\n\n");
31870728a38Smrg    else
31970728a38Smrg        fprintf(file, "xkb_compatibility \"%s\" {\n\n",
32070728a38Smrg                XkbAtomText(dpy, xkb->names->compat, XkbXKBFile));
32170728a38Smrg    WriteXKBVModDecl(file, dpy, xkb,
32270728a38Smrg                     (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE));
32370728a38Smrg
32470728a38Smrg    fprintf(file, "    interpret.useModMapMods= AnyLevel;\n");
32570728a38Smrg    fprintf(file, "    interpret.repeat= False;\n");
32670728a38Smrg    fprintf(file, "    interpret.locking= False;\n");
32770728a38Smrg    interp = xkb->compat->sym_interpret;
32870728a38Smrg    for (i = 0; i < xkb->compat->num_si; i++, interp++) {
32970728a38Smrg        fprintf(file, "    interpret %s+%s(%s) {\n",
33070728a38Smrg                ((interp->sym == NoSymbol) ? "Any" :
33170728a38Smrg                 XkbKeysymText(interp->sym, XkbXKBFile)),
33270728a38Smrg                XkbSIMatchText(interp->match, XkbXKBFile),
33370728a38Smrg                XkbModMaskText(interp->mods, XkbXKBFile));
33470728a38Smrg        if (interp->virtual_mod != XkbNoModifier) {
33570728a38Smrg            fprintf(file, "        virtualModifier= %s;\n",
33670728a38Smrg                    XkbVModIndexText(dpy, xkb, interp->virtual_mod,
33770728a38Smrg                                     XkbXKBFile));
33870728a38Smrg        }
33970728a38Smrg        if (interp->match & XkbSI_LevelOneOnly)
34070728a38Smrg            fprintf(file, "        useModMapMods=level1;\n");
34170728a38Smrg        if (interp->flags & XkbSI_LockingKey)
34270728a38Smrg            fprintf(file, "        locking= True;\n");
34370728a38Smrg        if (interp->flags & XkbSI_AutoRepeat)
34470728a38Smrg            fprintf(file, "        repeat= True;\n");
34570728a38Smrg        fprintf(file, "        action= ");
34670728a38Smrg        WriteXKBAction(file, result, &interp->act);
34770728a38Smrg        fprintf(file, ";\n");
34870728a38Smrg        fprintf(file, "    };\n");
3498c9fbc29Smrg    }
35070728a38Smrg    for (i = 0; i < XkbNumKbdGroups; i++) {
35170728a38Smrg        XkbModsPtr gc;
35270728a38Smrg
35370728a38Smrg        gc = &xkb->compat->groups[i];
35470728a38Smrg        if ((gc->real_mods == 0) && (gc->vmods == 0))
35570728a38Smrg            continue;
35670728a38Smrg        fprintf(file, "    group %d = %s;\n", i + 1,
35770728a38Smrg                XkbVModMaskText(xkb->dpy, xkb, gc->real_mods, gc->vmods,
35870728a38Smrg                                XkbXKBFile));
3598c9fbc29Smrg    }
3608c9fbc29Smrg    if (xkb->indicators) {
36170728a38Smrg        for (i = 0; i < XkbNumIndicators; i++) {
36270728a38Smrg            XkbIndicatorMapPtr map = &xkb->indicators->maps[i];
36370728a38Smrg
36470728a38Smrg            if ((map->flags != 0) || (map->which_groups != 0) ||
36570728a38Smrg                (map->groups != 0) || (map->which_mods != 0) ||
36670728a38Smrg                (map->mods.real_mods != 0) || (map->mods.vmods != 0) ||
36770728a38Smrg                (map->ctrls != 0)) {
36870728a38Smrg                WriteXKBIndicatorMap(file, result, xkb->names->indicators[i],
36970728a38Smrg                                     map, addOn, priv);
37070728a38Smrg            }
37170728a38Smrg        }
3728c9fbc29Smrg    }
3738c9fbc29Smrg    if (addOn)
37470728a38Smrg        (*addOn) (file, result, topLevel, showImplicit, XkmCompatMapIndex,
37570728a38Smrg                  priv);
37670728a38Smrg    fprintf(file, "};\n\n");
3778c9fbc29Smrg    return True;
3788c9fbc29Smrg}
3798c9fbc29Smrg
3808c9fbc29SmrgBool
38170728a38SmrgXkbWriteXKBSymbols(FILE *               file,
38270728a38Smrg                   XkbFileInfo *        result,
38370728a38Smrg                   Bool                 topLevel,
38470728a38Smrg                   Bool                 showImplicit,
38570728a38Smrg                   XkbFileAddOnFunc     addOn,
38670728a38Smrg                   void *               priv)
3878c9fbc29Smrg{
38870728a38Smrg    Display *dpy;
38970728a38Smrg    register unsigned i, tmp;
39070728a38Smrg    XkbDescPtr xkb;
39170728a38Smrg    XkbClientMapPtr map;
39270728a38Smrg    XkbServerMapPtr srv;
39370728a38Smrg    Bool showActions;
39470728a38Smrg
39570728a38Smrg    xkb = result->xkb;
39670728a38Smrg
39770728a38Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->syms) || (!xkb->map->key_sym_map)) {
39870728a38Smrg        _XkbLibError(_XkbErrMissingSymbols, "XkbWriteXKBSymbols", 0);
39970728a38Smrg        return False;
4008c9fbc29Smrg    }
40170728a38Smrg    if ((!xkb->names) || (!xkb->names->keys)) {
40270728a38Smrg        _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBSymbols", 0);
40370728a38Smrg        return False;
4048c9fbc29Smrg    }
4058c9fbc29Smrg
40670728a38Smrg    map = xkb->map;
40770728a38Smrg    srv = xkb->server;
40870728a38Smrg    dpy = xkb->dpy;
40970728a38Smrg
41070728a38Smrg    if ((xkb->names == NULL) || (xkb->names->symbols == None))
41170728a38Smrg        fprintf(file, "xkb_symbols {\n\n");
41270728a38Smrg    else
41370728a38Smrg        fprintf(file, "xkb_symbols \"%s\" {\n\n",
41470728a38Smrg                XkbAtomText(dpy, xkb->names->symbols, XkbXKBFile));
41570728a38Smrg    for (tmp = i = 0; i < XkbNumKbdGroups; i++) {
41670728a38Smrg        if (xkb->names->groups[i] != None) {
41770728a38Smrg            fprintf(file, "    name[group%d]=\"%s\";\n", i + 1,
41870728a38Smrg                    XkbAtomText(dpy, xkb->names->groups[i], XkbXKBFile));
41970728a38Smrg            tmp++;
42070728a38Smrg        }
4218c9fbc29Smrg    }
42270728a38Smrg    if (tmp > 0)
42370728a38Smrg        fprintf(file, "\n");
42470728a38Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
42570728a38Smrg        Bool simple;
42670728a38Smrg
42770728a38Smrg        if ((int) XkbKeyNumSyms(xkb, i) < 1)
42870728a38Smrg            continue;
42970728a38Smrg        if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, True) != i)
43070728a38Smrg            continue;
43170728a38Smrg        simple = True;
43270728a38Smrg        fprintf(file, "    key %6s {",
43370728a38Smrg                XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile));
43470728a38Smrg        if (srv->explicit) {
43570728a38Smrg            if (((srv->explicit[i] & XkbExplicitKeyTypesMask) != 0) ||
43670728a38Smrg                (showImplicit)) {
43770728a38Smrg                int typeNdx, g;
43870728a38Smrg                Bool multi;
43970728a38Smrg                const char *comment = "  ";
44070728a38Smrg
44170728a38Smrg                if ((srv->explicit[i] & XkbExplicitKeyTypesMask) == 0)
44270728a38Smrg                    comment = "//";
44370728a38Smrg                multi = False;
44470728a38Smrg                typeNdx = XkbKeyKeyTypeIndex(xkb, i, 0);
44570728a38Smrg                for (g = 1; (g < XkbKeyNumGroups(xkb, i)) && (!multi); g++) {
44670728a38Smrg                    if (XkbKeyKeyTypeIndex(xkb, i, g) != typeNdx)
44770728a38Smrg                        multi = True;
44870728a38Smrg                }
44970728a38Smrg                if (multi) {
45070728a38Smrg                    for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) {
45170728a38Smrg                        typeNdx = XkbKeyKeyTypeIndex(xkb, i, g);
45270728a38Smrg                        if (srv->explicit[i] & (1 << g)) {
45370728a38Smrg                            fprintf(file, "\n%s      type[group%d]= \"%s\",",
45470728a38Smrg                                    comment, g + 1,
45570728a38Smrg                                    XkbAtomText(dpy, map->types[typeNdx].name,
45670728a38Smrg                                                XkbXKBFile));
45770728a38Smrg                        }
45870728a38Smrg                        else if (showImplicit) {
45970728a38Smrg                            fprintf(file, "\n//      type[group%d]= \"%s\",",
46070728a38Smrg                                    g + 1,
46170728a38Smrg                                    XkbAtomText(dpy, map->types[typeNdx].name,
46270728a38Smrg                                                XkbXKBFile));
46370728a38Smrg                        }
46470728a38Smrg                    }
46570728a38Smrg                }
46670728a38Smrg                else {
46770728a38Smrg                    fprintf(file, "\n%s      type= \"%s\",", comment,
46870728a38Smrg                            XkbAtomText(dpy, map->types[typeNdx].name,
46970728a38Smrg                                        XkbXKBFile));
47070728a38Smrg                }
47170728a38Smrg                simple = False;
47270728a38Smrg            }
47370728a38Smrg            if (((srv->explicit[i] & XkbExplicitAutoRepeatMask) != 0) &&
47470728a38Smrg                (xkb->ctrls != NULL)) {
47570728a38Smrg                if (xkb->ctrls->per_key_repeat[i / 8] & (1 << (i % 8)))
47670728a38Smrg                    fprintf(file, "\n        repeat= Yes,");
47770728a38Smrg                else
47870728a38Smrg                    fprintf(file, "\n        repeat= No,");
47970728a38Smrg                simple = False;
48070728a38Smrg            }
48170728a38Smrg            if ((xkb->server != NULL) && (xkb->server->vmodmap != NULL) &&
48270728a38Smrg                (xkb->server->vmodmap[i] != 0)) {
48370728a38Smrg                if ((srv->explicit[i] & XkbExplicitVModMapMask) != 0) {
48470728a38Smrg                    fprintf(file, "\n        virtualMods= %s,",
48570728a38Smrg                            XkbVModMaskText(dpy, xkb, 0,
48670728a38Smrg                                            xkb->server->vmodmap[i],
48770728a38Smrg                                            XkbXKBFile));
48870728a38Smrg                }
48970728a38Smrg                else if (showImplicit) {
49070728a38Smrg                    fprintf(file, "\n//      virtualMods= %s,",
49170728a38Smrg                            XkbVModMaskText(dpy, xkb, 0,
49270728a38Smrg                                            xkb->server->vmodmap[i],
49370728a38Smrg                                            XkbXKBFile));
49470728a38Smrg                }
49570728a38Smrg            }
49670728a38Smrg        }
49770728a38Smrg        switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb, i))) {
49870728a38Smrg        case XkbClampIntoRange:
49970728a38Smrg            fprintf(file, "\n        groupsClamp,");
50070728a38Smrg            break;
50170728a38Smrg        case XkbRedirectIntoRange:
50270728a38Smrg            fprintf(file, "\n        groupsRedirect= Group%d,",
50370728a38Smrg                    XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb, i)) + 1);
50470728a38Smrg            break;
50570728a38Smrg        }
50670728a38Smrg        if (srv->behaviors != NULL) {
50770728a38Smrg            unsigned type;
50870728a38Smrg
50970728a38Smrg            type = srv->behaviors[i].type & XkbKB_OpMask;
51070728a38Smrg
51170728a38Smrg            if (type != XkbKB_Default) {
51270728a38Smrg                simple = False;
51370728a38Smrg                fprintf(file, "\n        %s,",
51470728a38Smrg                        XkbBehaviorText(xkb, &srv->behaviors[i], XkbXKBFile));
51570728a38Smrg            }
51670728a38Smrg        }
51770728a38Smrg        if ((srv->explicit == NULL) || showImplicit ||
51870728a38Smrg            ((srv->explicit[i] & XkbExplicitInterpretMask) != 0))
51970728a38Smrg            showActions = XkbKeyHasActions(xkb, i);
52070728a38Smrg        else
52170728a38Smrg            showActions = False;
52270728a38Smrg
52370728a38Smrg        if (((unsigned) XkbKeyNumGroups(xkb, i) > 1) || showActions)
52470728a38Smrg            simple = False;
52570728a38Smrg        if (simple) {
52670728a38Smrg            KeySym *syms;
52770728a38Smrg            unsigned s;
52870728a38Smrg
52970728a38Smrg            syms = XkbKeySymsPtr(xkb, i);
53070728a38Smrg            fprintf(file, "         [ ");
53170728a38Smrg            for (s = 0; s < XkbKeyGroupWidth(xkb, i, XkbGroup1Index); s++) {
53270728a38Smrg                if (s != 0)
53370728a38Smrg                    fprintf(file, ", ");
53470728a38Smrg                fprintf(file, "%15s", XkbKeysymText(*syms++, XkbXKBFile));
53570728a38Smrg            }
53670728a38Smrg            fprintf(file, " ] };\n");
53770728a38Smrg        }
53870728a38Smrg        else {
53970728a38Smrg            unsigned g, s;
54070728a38Smrg            KeySym *syms;
54170728a38Smrg            XkbAction *acts;
54270728a38Smrg
54370728a38Smrg            syms = XkbKeySymsPtr(xkb, i);
54470728a38Smrg            acts = XkbKeyActionsPtr(xkb, i);
54570728a38Smrg            for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) {
54670728a38Smrg                if (g != 0)
54770728a38Smrg                    fprintf(file, ",");
54870728a38Smrg                fprintf(file, "\n        symbols[Group%d]= [ ", g + 1);
54970728a38Smrg                for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) {
55070728a38Smrg                    if (s != 0)
55170728a38Smrg                        fprintf(file, ", ");
55270728a38Smrg                    fprintf(file, "%15s", XkbKeysymText(syms[s], XkbXKBFile));
55370728a38Smrg                }
55470728a38Smrg                fprintf(file, " ]");
55570728a38Smrg                syms += XkbKeyGroupsWidth(xkb, i);
55670728a38Smrg                if (showActions) {
55770728a38Smrg                    fprintf(file, ",\n        actions[Group%d]= [ ", g + 1);
55870728a38Smrg                    for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) {
55970728a38Smrg                        if (s != 0)
56070728a38Smrg                            fprintf(file, ", ");
56170728a38Smrg                        WriteXKBAction(file, result,
56270728a38Smrg                                       (XkbAnyAction *) & acts[s]);
56370728a38Smrg                    }
56470728a38Smrg                    fprintf(file, " ]");
56570728a38Smrg                    acts += XkbKeyGroupsWidth(xkb, i);
56670728a38Smrg                }
56770728a38Smrg            }
56870728a38Smrg            fprintf(file, "\n    };\n");
56970728a38Smrg        }
5708c9fbc29Smrg    }
5718c9fbc29Smrg    if (map && map->modmap) {
57270728a38Smrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
57370728a38Smrg            if (map->modmap[i] != 0) {
57470728a38Smrg                register int n, bit;
57570728a38Smrg
57670728a38Smrg                for (bit = 1, n = 0; n < XkbNumModifiers; n++, bit <<= 1) {
57770728a38Smrg                    if (map->modmap[i] & bit) {
57870728a38Smrg                        char buf[5];
57970728a38Smrg
58070728a38Smrg                        memcpy(buf, xkb->names->keys[i].name, 4);
58170728a38Smrg                        buf[4] = '\0';
58270728a38Smrg                        fprintf(file, "    modifier_map %s { <%s> };\n",
58370728a38Smrg                                XkbModIndexText(n, XkbXKBFile), buf);
58470728a38Smrg                    }
58570728a38Smrg                }
58670728a38Smrg            }
58770728a38Smrg        }
5888c9fbc29Smrg    }
5898c9fbc29Smrg    if (addOn)
59070728a38Smrg        (*addOn) (file, result, topLevel, showImplicit, XkmSymbolsIndex, priv);
59170728a38Smrg    fprintf(file, "};\n\n");
5928c9fbc29Smrg    return True;
5938c9fbc29Smrg}
5948c9fbc29Smrg
5958c9fbc29Smrgstatic Bool
59670728a38SmrgWriteXKBOutline(FILE *          file,
59770728a38Smrg                XkbShapePtr     shape,
59870728a38Smrg                XkbOutlinePtr   outline,
59970728a38Smrg                int             lastRadius,
60070728a38Smrg                int             first,
60170728a38Smrg                int             indent)
6028c9fbc29Smrg{
60370728a38Smrg    register int i;
60470728a38Smrg    XkbPointPtr pt;
60570728a38Smrg    char *iStr;
60670728a38Smrg
60770728a38Smrg    fprintf(file, "%s", iStr = XkbIndentText(first));
60870728a38Smrg    if (first != indent)
60970728a38Smrg        iStr = XkbIndentText(indent);
61070728a38Smrg    if (outline->corner_radius != lastRadius) {
61170728a38Smrg        fprintf(file, "corner= %s,",
61270728a38Smrg                XkbGeomFPText(outline->corner_radius, XkbMessage));
61370728a38Smrg        if (shape != NULL) {
61470728a38Smrg            fprintf(file, "\n%s", iStr);
61570728a38Smrg        }
6168c9fbc29Smrg    }
6178c9fbc29Smrg    if (shape) {
61870728a38Smrg        if (outline == shape->approx)
61970728a38Smrg            fprintf(file, "approx= ");
62070728a38Smrg        else if (outline == shape->primary)
62170728a38Smrg            fprintf(file, "primary= ");
6228c9fbc29Smrg    }
62370728a38Smrg    fprintf(file, "{");
62470728a38Smrg    for (pt = outline->points, i = 0; i < outline->num_points; i++, pt++) {
62570728a38Smrg        if (i == 0)
62670728a38Smrg            fprintf(file, " ");
62770728a38Smrg        else if ((i % 4) == 0)
62870728a38Smrg            fprintf(file, ",\n%s  ", iStr);
62970728a38Smrg        else
63070728a38Smrg            fprintf(file, ", ");
63170728a38Smrg        fprintf(file, "[ %3s, %3s ]", XkbGeomFPText(pt->x, XkbXKBFile),
63270728a38Smrg                XkbGeomFPText(pt->y, XkbXKBFile));
6338c9fbc29Smrg    }
63470728a38Smrg    fprintf(file, " }");
6358c9fbc29Smrg    return True;
6368c9fbc29Smrg}
6378c9fbc29Smrg
6388c9fbc29Smrgstatic Bool
63970728a38SmrgWriteXKBDoodad(FILE *           file,
64070728a38Smrg               Display *        dpy,
64170728a38Smrg               unsigned         indent,
64270728a38Smrg               XkbGeometryPtr   geom,
64370728a38Smrg               XkbDoodadPtr     doodad)
6448c9fbc29Smrg{
64570728a38Smrg    register char *i_str;
64670728a38Smrg    XkbShapePtr shape;
64770728a38Smrg    XkbColorPtr color;
64870728a38Smrg
64970728a38Smrg    i_str = XkbIndentText(indent);
65070728a38Smrg    fprintf(file, "%s%s \"%s\" {\n", i_str,
65170728a38Smrg            XkbDoodadTypeText(doodad->any.type, XkbMessage),
65270728a38Smrg            XkbAtomText(dpy, doodad->any.name, XkbMessage));
65370728a38Smrg    fprintf(file, "%s    top=      %s;\n", i_str,
65470728a38Smrg            XkbGeomFPText(doodad->any.top, XkbXKBFile));
65570728a38Smrg    fprintf(file, "%s    left=     %s;\n", i_str,
65670728a38Smrg            XkbGeomFPText(doodad->any.left, XkbXKBFile));
65770728a38Smrg    fprintf(file, "%s    priority= %d;\n", i_str, doodad->any.priority);
6588c9fbc29Smrg    switch (doodad->any.type) {
65970728a38Smrg    case XkbOutlineDoodad:
66070728a38Smrg    case XkbSolidDoodad:
66170728a38Smrg        if (doodad->shape.angle != 0) {
66270728a38Smrg            fprintf(file, "%s    angle=  %s;\n", i_str,
66370728a38Smrg                    XkbGeomFPText(doodad->shape.angle, XkbXKBFile));
66470728a38Smrg        }
66570728a38Smrg        if (doodad->shape.color_ndx != 0) {
66670728a38Smrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
66770728a38Smrg                    XkbShapeDoodadColor(geom, &doodad->shape)->spec);
66870728a38Smrg        }
66970728a38Smrg        shape = XkbShapeDoodadShape(geom, &doodad->shape);
67070728a38Smrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
67170728a38Smrg                XkbAtomText(dpy, shape->name, XkbXKBFile));
67270728a38Smrg        break;
67370728a38Smrg    case XkbTextDoodad:
67470728a38Smrg        if (doodad->text.angle != 0) {
67570728a38Smrg            fprintf(file, "%s    angle=  %s;\n", i_str,
67670728a38Smrg                    XkbGeomFPText(doodad->text.angle, XkbXKBFile));
67770728a38Smrg        }
67870728a38Smrg        if (doodad->text.width != 0) {
67970728a38Smrg            fprintf(file, "%s    width=  %s;\n", i_str,
68070728a38Smrg                    XkbGeomFPText(doodad->text.width, XkbXKBFile));
68170728a38Smrg
68270728a38Smrg        }
68370728a38Smrg        if (doodad->text.height != 0) {
68470728a38Smrg            fprintf(file, "%s    height=  %s;\n", i_str,
68570728a38Smrg                    XkbGeomFPText(doodad->text.height, XkbXKBFile));
68670728a38Smrg
68770728a38Smrg        }
68870728a38Smrg        if (doodad->text.color_ndx != 0) {
68970728a38Smrg            color = XkbTextDoodadColor(geom, &doodad->text);
69070728a38Smrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
69170728a38Smrg                    XkbStringText(color->spec, XkbXKBFile));
69270728a38Smrg        }
69370728a38Smrg        fprintf(file, "%s    XFont= \"%s\";\n", i_str,
69470728a38Smrg                XkbStringText(doodad->text.font, XkbXKBFile));
69570728a38Smrg        fprintf(file, "%s    text=  \"%s\";\n", i_str,
69670728a38Smrg                XkbStringText(doodad->text.text, XkbXKBFile));
69770728a38Smrg        break;
69870728a38Smrg    case XkbIndicatorDoodad:
69970728a38Smrg        shape = XkbIndicatorDoodadShape(geom, &doodad->indicator);
70070728a38Smrg        color = XkbIndicatorDoodadOnColor(geom, &doodad->indicator);
70170728a38Smrg        fprintf(file, "%s    onColor= \"%s\";\n", i_str,
70270728a38Smrg                XkbStringText(color->spec, XkbXKBFile));
70370728a38Smrg        color = XkbIndicatorDoodadOffColor(geom, &doodad->indicator);
70470728a38Smrg        fprintf(file, "%s    offColor= \"%s\";\n", i_str,
70570728a38Smrg                XkbStringText(color->spec, XkbXKBFile));
70670728a38Smrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
70770728a38Smrg                XkbAtomText(dpy, shape->name, XkbXKBFile));
70870728a38Smrg        break;
70970728a38Smrg    case XkbLogoDoodad:
71070728a38Smrg        fprintf(file, "%s    logoName= \"%s\";\n", i_str,
71170728a38Smrg                XkbStringText(doodad->logo.logo_name, XkbXKBFile));
71270728a38Smrg        if (doodad->shape.angle != 0) {
71370728a38Smrg            fprintf(file, "%s    angle=  %s;\n", i_str,
71470728a38Smrg                    XkbGeomFPText(doodad->logo.angle, XkbXKBFile));
71570728a38Smrg        }
71670728a38Smrg        if (doodad->shape.color_ndx != 0) {
71770728a38Smrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
71870728a38Smrg                    XkbLogoDoodadColor(geom, &doodad->logo)->spec);
71970728a38Smrg        }
72070728a38Smrg        shape = XkbLogoDoodadShape(geom, &doodad->logo);
72170728a38Smrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
72270728a38Smrg                XkbAtomText(dpy, shape->name, XkbXKBFile));
72370728a38Smrg        break;
7248c9fbc29Smrg    }
72570728a38Smrg    fprintf(file, "%s};\n", i_str);
7268c9fbc29Smrg    return True;
7278c9fbc29Smrg}
7288c9fbc29Smrg
7298c9fbc29Smrg/*ARGSUSED*/
7308c9fbc29Smrgstatic Bool
73170728a38SmrgWriteXKBOverlay(FILE *          file,
73270728a38Smrg                Display *       dpy,
73370728a38Smrg                unsigned        indent,
73470728a38Smrg                XkbGeometryPtr  geom,
73570728a38Smrg                XkbOverlayPtr   ol)
7368c9fbc29Smrg{
73770728a38Smrg    register char *i_str;
73870728a38Smrg    int r, k, nOut;
73970728a38Smrg    XkbOverlayRowPtr row;
74070728a38Smrg    XkbOverlayKeyPtr key;
74170728a38Smrg
74270728a38Smrg    i_str = XkbIndentText(indent);
74370728a38Smrg    if (ol->name != None) {
74470728a38Smrg        fprintf(file, "%soverlay \"%s\" {\n", i_str,
74570728a38Smrg                XkbAtomText(dpy, ol->name, XkbMessage));
7468c9fbc29Smrg    }
74770728a38Smrg    else
74870728a38Smrg        fprintf(file, "%soverlay {\n", i_str);
74970728a38Smrg    for (nOut = r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
75070728a38Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
75170728a38Smrg            char *over, *under;
75270728a38Smrg
75370728a38Smrg            over = XkbKeyNameText(key->over.name, XkbXKBFile);
75470728a38Smrg            under = XkbKeyNameText(key->under.name, XkbXKBFile);
75570728a38Smrg            if (nOut == 0)
75670728a38Smrg                fprintf(file, "%s    %6s=%6s", i_str, under, over);
75770728a38Smrg            else if ((nOut % 4) == 0)
75870728a38Smrg                fprintf(file, ",\n%s    %6s=%6s", i_str, under, over);
75970728a38Smrg            else
76070728a38Smrg                fprintf(file, ", %6s=%6s", under, over);
76170728a38Smrg            nOut++;
76270728a38Smrg        }
7638c9fbc29Smrg    }
76470728a38Smrg    fprintf(file, "\n%s};\n", i_str);
7658c9fbc29Smrg    return True;
7668c9fbc29Smrg}
7678c9fbc29Smrg
7688c9fbc29Smrgstatic Bool
76970728a38SmrgWriteXKBSection(FILE *          file,
77070728a38Smrg                Display *       dpy,
77170728a38Smrg                XkbSectionPtr   s,
77270728a38Smrg                XkbGeometryPtr  geom)
7738c9fbc29Smrg{
77470728a38Smrg    register int i;
77570728a38Smrg    XkbRowPtr row;
77670728a38Smrg    int dfltKeyColor = 0;
77770728a38Smrg
77870728a38Smrg    fprintf(file, "    section \"%s\" {\n",
77970728a38Smrg            XkbAtomText(dpy, s->name, XkbXKBFile));
78070728a38Smrg    if (s->rows && (s->rows->num_keys > 0)) {
78170728a38Smrg        dfltKeyColor = s->rows->keys[0].color_ndx;
78270728a38Smrg        fprintf(file, "        key.color= \"%s\";\n",
78370728a38Smrg                XkbStringText(geom->colors[dfltKeyColor].spec, XkbXKBFile));
7848c9fbc29Smrg    }
78570728a38Smrg    fprintf(file, "        priority=  %d;\n", s->priority);
78670728a38Smrg    fprintf(file, "        top=       %s;\n",
78770728a38Smrg            XkbGeomFPText(s->top, XkbXKBFile));
78870728a38Smrg    fprintf(file, "        left=      %s;\n",
78970728a38Smrg            XkbGeomFPText(s->left, XkbXKBFile));
79070728a38Smrg    fprintf(file, "        width=     %s;\n",
79170728a38Smrg            XkbGeomFPText(s->width, XkbXKBFile));
79270728a38Smrg    fprintf(file, "        height=    %s;\n",
79370728a38Smrg            XkbGeomFPText(s->height, XkbXKBFile));
79470728a38Smrg    if (s->angle != 0) {
79570728a38Smrg        fprintf(file, "        angle=  %s;\n",
79670728a38Smrg                XkbGeomFPText(s->angle, XkbXKBFile));
7978c9fbc29Smrg    }
79870728a38Smrg    for (i = 0, row = s->rows; row && i < s->num_rows; i++, row++) {
79970728a38Smrg        fprintf(file, "        row {\n");
80070728a38Smrg        fprintf(file, "            top=  %s;\n",
80170728a38Smrg                XkbGeomFPText(row->top, XkbXKBFile));
80270728a38Smrg        fprintf(file, "            left= %s;\n",
80370728a38Smrg                XkbGeomFPText(row->left, XkbXKBFile));
80470728a38Smrg        if (row->vertical)
80570728a38Smrg            fprintf(file, "            vertical;\n");
80670728a38Smrg        if (row->num_keys > 0) {
80770728a38Smrg            register int k;
80870728a38Smrg            register XkbKeyPtr key;
80970728a38Smrg            int forceNL = 0;
81070728a38Smrg            int nThisLine = 0;
81170728a38Smrg
81270728a38Smrg            fprintf(file, "            keys {\n");
81370728a38Smrg            for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
81470728a38Smrg                XkbShapePtr shape;
81570728a38Smrg
81670728a38Smrg                if (key->color_ndx != dfltKeyColor)
81770728a38Smrg                    forceNL = 1;
81870728a38Smrg                if (k == 0) {
81970728a38Smrg                    fprintf(file, "                ");
82070728a38Smrg                    nThisLine = 0;
82170728a38Smrg                }
82270728a38Smrg                else if (((nThisLine % 2) == 1) || (forceNL)) {
82370728a38Smrg                    fprintf(file, ",\n                ");
82470728a38Smrg                    forceNL = nThisLine = 0;
82570728a38Smrg                }
82670728a38Smrg                else {
82770728a38Smrg                    fprintf(file, ", ");
82870728a38Smrg                    nThisLine++;
82970728a38Smrg                }
83070728a38Smrg                shape = XkbKeyShape(geom, key);
83170728a38Smrg                fprintf(file, "{ %6s, \"%s\", %3s",
83270728a38Smrg                        XkbKeyNameText(key->name.name, XkbXKBFile),
83370728a38Smrg                        XkbAtomText(dpy, shape->name, XkbXKBFile),
83470728a38Smrg                        XkbGeomFPText(key->gap, XkbXKBFile));
83570728a38Smrg                if (key->color_ndx != dfltKeyColor) {
83670728a38Smrg                    fprintf(file, ", color=\"%s\"",
83770728a38Smrg                            XkbKeyColor(geom, key)->spec);
83870728a38Smrg                    forceNL = 1;
83970728a38Smrg                }
84070728a38Smrg                fprintf(file, " }");
84170728a38Smrg            }
84270728a38Smrg            fprintf(file, "\n            };\n");
84370728a38Smrg        }
84470728a38Smrg        fprintf(file, "        };\n");
8458c9fbc29Smrg    }
84670728a38Smrg    if (s->doodads != NULL) {
84770728a38Smrg        XkbDoodadPtr doodad;
84870728a38Smrg
84970728a38Smrg        for (i = 0, doodad = s->doodads; i < s->num_doodads; i++, doodad++) {
85070728a38Smrg            WriteXKBDoodad(file, dpy, 8, geom, doodad);
85170728a38Smrg        }
8528c9fbc29Smrg    }
85370728a38Smrg    if (s->overlays != NULL) {
85470728a38Smrg        XkbOverlayPtr ol;
85570728a38Smrg
85670728a38Smrg        for (i = 0, ol = s->overlays; i < s->num_overlays; i++, ol++) {
85770728a38Smrg            WriteXKBOverlay(file, dpy, 8, geom, ol);
85870728a38Smrg        }
8598c9fbc29Smrg    }
86070728a38Smrg    fprintf(file, "    }; // End of \"%s\" section\n\n",
86170728a38Smrg            XkbAtomText(dpy, s->name, XkbXKBFile));
8628c9fbc29Smrg    return True;
8638c9fbc29Smrg}
8648c9fbc29Smrg
8658c9fbc29SmrgBool
86670728a38SmrgXkbWriteXKBGeometry(FILE *              file,
86770728a38Smrg                    XkbFileInfo *       result,
86870728a38Smrg                    Bool                topLevel,
86970728a38Smrg                    Bool                showImplicit,
87070728a38Smrg                    XkbFileAddOnFunc    addOn,
87170728a38Smrg                    void *              priv)
8728c9fbc29Smrg{
87370728a38Smrg    Display *dpy;
87470728a38Smrg    register unsigned i, n;
87570728a38Smrg    XkbDescPtr xkb;
87670728a38Smrg    XkbGeometryPtr geom;
87770728a38Smrg
87870728a38Smrg    xkb = result->xkb;
87970728a38Smrg    if ((!xkb) || (!xkb->geom)) {
88070728a38Smrg        _XkbLibError(_XkbErrMissingGeometry, "XkbWriteXKBGeometry", 0);
88170728a38Smrg        return False;
8828c9fbc29Smrg    }
88370728a38Smrg    dpy = xkb->dpy;
88470728a38Smrg    geom = xkb->geom;
88570728a38Smrg    if (geom->name == None)
88670728a38Smrg        fprintf(file, "xkb_geometry {\n\n");
88770728a38Smrg    else
88870728a38Smrg        fprintf(file, "xkb_geometry \"%s\" {\n\n",
88970728a38Smrg                XkbAtomText(dpy, geom->name, XkbXKBFile));
89070728a38Smrg    fprintf(file, "    width=       %s;\n",
89170728a38Smrg            XkbGeomFPText(geom->width_mm, XkbXKBFile));
89270728a38Smrg    fprintf(file, "    height=      %s;\n\n",
89370728a38Smrg            XkbGeomFPText(geom->height_mm, XkbXKBFile));
89470728a38Smrg
89570728a38Smrg    if (geom->key_aliases != NULL) {
89670728a38Smrg        XkbKeyAliasPtr pAl;
89770728a38Smrg
89870728a38Smrg        pAl = geom->key_aliases;
89970728a38Smrg        for (i = 0; i < geom->num_key_aliases; i++, pAl++) {
90070728a38Smrg            fprintf(file, "    alias %6s = %6s;\n",
90170728a38Smrg                    XkbKeyNameText(pAl->alias, XkbXKBFile),
90270728a38Smrg                    XkbKeyNameText(pAl->real, XkbXKBFile));
90370728a38Smrg        }
90470728a38Smrg        fprintf(file, "\n");
9058c9fbc29Smrg    }
9068c9fbc29Smrg
90770728a38Smrg    if (geom->base_color != NULL)
90870728a38Smrg        fprintf(file, "    baseColor=   \"%s\";\n",
90970728a38Smrg                XkbStringText(geom->base_color->spec, XkbXKBFile));
91070728a38Smrg    if (geom->label_color != NULL)
91170728a38Smrg        fprintf(file, "    labelColor=  \"%s\";\n",
91270728a38Smrg                XkbStringText(geom->label_color->spec, XkbXKBFile));
91370728a38Smrg    if (geom->label_font != NULL)
91470728a38Smrg        fprintf(file, "    xfont=       \"%s\";\n",
91570728a38Smrg                XkbStringText(geom->label_font, XkbXKBFile));
91670728a38Smrg    if ((geom->num_colors > 0) && (showImplicit)) {
91770728a38Smrg        XkbColorPtr color;
91870728a38Smrg
91970728a38Smrg        for (color = geom->colors, i = 0; i < geom->num_colors; i++, color++) {
92070728a38Smrg            fprintf(file, "//     color[%d]= \"%s\"\n", i,
92170728a38Smrg                    XkbStringText(color->spec, XkbXKBFile));
92270728a38Smrg        }
92370728a38Smrg        fprintf(file, "\n");
9248c9fbc29Smrg    }
92570728a38Smrg    if (geom->num_properties > 0) {
92670728a38Smrg        XkbPropertyPtr prop;
92770728a38Smrg
92870728a38Smrg        for (prop = geom->properties, i = 0; i < geom->num_properties;
92970728a38Smrg             i++, prop++) {
93070728a38Smrg            fprintf(file, "    %s= \"%s\";\n", prop->name,
93170728a38Smrg                    XkbStringText(prop->value, XkbXKBFile));
93270728a38Smrg        }
93370728a38Smrg        fprintf(file, "\n");
9348c9fbc29Smrg    }
93570728a38Smrg    if (geom->num_shapes > 0) {
93670728a38Smrg        XkbShapePtr shape;
93770728a38Smrg        XkbOutlinePtr outline;
93870728a38Smrg        int lastR;
93970728a38Smrg
94070728a38Smrg        for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
94170728a38Smrg            lastR = 0;
94270728a38Smrg            fprintf(file, "    shape \"%s\" {",
94370728a38Smrg                    XkbAtomText(dpy, shape->name, XkbXKBFile));
94470728a38Smrg            outline = shape->outlines;
94570728a38Smrg            if (shape->num_outlines > 1) {
94670728a38Smrg                for (n = 0; n < shape->num_outlines; n++, outline++) {
94770728a38Smrg                    if (n == 0)
94870728a38Smrg                        fprintf(file, "\n");
94970728a38Smrg                    else
95070728a38Smrg                        fprintf(file, ",\n");
95170728a38Smrg                    WriteXKBOutline(file, shape, outline, lastR, 8, 8);
95270728a38Smrg                    lastR = outline->corner_radius;
95370728a38Smrg                }
95470728a38Smrg                fprintf(file, "\n    };\n");
95570728a38Smrg            }
95670728a38Smrg            else {
95770728a38Smrg                WriteXKBOutline(file, NULL, outline, lastR, 1, 8);
95870728a38Smrg                fprintf(file, " };\n");
95970728a38Smrg            }
96070728a38Smrg        }
9618c9fbc29Smrg    }
96270728a38Smrg    if (geom->num_sections > 0) {
96370728a38Smrg        XkbSectionPtr section;
96470728a38Smrg
96570728a38Smrg        for (section = geom->sections, i = 0; i < geom->num_sections;
96670728a38Smrg             i++, section++) {
96770728a38Smrg            WriteXKBSection(file, dpy, section, geom);
96870728a38Smrg        }
9698c9fbc29Smrg    }
97070728a38Smrg    if (geom->num_doodads > 0) {
97170728a38Smrg        XkbDoodadPtr doodad;
97270728a38Smrg
97370728a38Smrg        for (i = 0, doodad = geom->doodads; i < geom->num_doodads;
97470728a38Smrg             i++, doodad++) {
97570728a38Smrg            WriteXKBDoodad(file, dpy, 4, geom, doodad);
97670728a38Smrg        }
9778c9fbc29Smrg    }
9788c9fbc29Smrg    if (addOn)
97970728a38Smrg        (*addOn) (file, result, topLevel, showImplicit, XkmGeometryIndex, priv);
98070728a38Smrg    fprintf(file, "};\n\n");
9818c9fbc29Smrg    return True;
9828c9fbc29Smrg}
9838c9fbc29Smrg
9848c9fbc29Smrg/*ARGSUSED*/
9858c9fbc29SmrgBool
98670728a38SmrgXkbWriteXKBSemantics(FILE * 		file,
98770728a38Smrg                     XkbFileInfo * 	result,
98870728a38Smrg                     Bool 		topLevel,
98970728a38Smrg                     Bool 		showImplicit,
99070728a38Smrg                     XkbFileAddOnFunc	addOn,
99170728a38Smrg                     void *		priv)
9928c9fbc29Smrg{
99370728a38Smrg    Bool ok;
9948c9fbc29Smrg
99570728a38Smrg    fprintf(file, "xkb_semantics {\n");
99670728a38Smrg    ok = XkbWriteXKBKeyTypes(file, result, False, False, addOn, priv);
99770728a38Smrg    ok = ok && XkbWriteXKBCompatMap(file, result, False, False, addOn, priv);
99870728a38Smrg    fprintf(file, "};\n");
9998c9fbc29Smrg    return ok;
10008c9fbc29Smrg}
10018c9fbc29Smrg
10028c9fbc29Smrg/*ARGSUSED*/
10038c9fbc29SmrgBool
100470728a38SmrgXkbWriteXKBLayout(FILE *                file,
100570728a38Smrg                  XkbFileInfo *         result,
100670728a38Smrg                  Bool                  topLevel,
100770728a38Smrg                  Bool                  showImplicit,
100870728a38Smrg                  XkbFileAddOnFunc      addOn,
100970728a38Smrg                  void *                priv)
10108c9fbc29Smrg{
101170728a38Smrg    Bool ok;
101270728a38Smrg    XkbDescPtr xkb;
101370728a38Smrg
101470728a38Smrg    xkb = result->xkb;
101570728a38Smrg    fprintf(file, "xkb_layout {\n");
101670728a38Smrg    ok = XkbWriteXKBKeycodes(file, result, False, showImplicit, addOn, priv);
101770728a38Smrg    ok = ok &&
101870728a38Smrg        XkbWriteXKBKeyTypes(file, result, False, showImplicit, addOn, priv);
101970728a38Smrg    ok = ok &&
102070728a38Smrg        XkbWriteXKBSymbols(file, result, False, showImplicit, addOn, priv);
10218c9fbc29Smrg    if (xkb->geom)
102270728a38Smrg        ok = ok &&
102370728a38Smrg            XkbWriteXKBGeometry(file, result, False, showImplicit, addOn, priv);
102470728a38Smrg    fprintf(file, "};\n");
10258c9fbc29Smrg    return ok;
10268c9fbc29Smrg}
10278c9fbc29Smrg
10288c9fbc29Smrg/*ARGSUSED*/
10298c9fbc29SmrgBool
103070728a38SmrgXkbWriteXKBKeymap(FILE *                file,
103170728a38Smrg                  XkbFileInfo *         result,
103270728a38Smrg                  Bool                  topLevel,
103370728a38Smrg                  Bool                  showImplicit,
103470728a38Smrg                  XkbFileAddOnFunc      addOn,
103570728a38Smrg                  void *                priv)
10368c9fbc29Smrg{
103770728a38Smrg    Bool ok;
103870728a38Smrg    XkbDescPtr xkb;
103970728a38Smrg
104070728a38Smrg    xkb = result->xkb;
104170728a38Smrg    fprintf(file, "xkb_keymap {\n");
104270728a38Smrg    ok = XkbWriteXKBKeycodes(file, result, False, showImplicit, addOn, priv);
104370728a38Smrg    ok = ok &&
104470728a38Smrg        XkbWriteXKBKeyTypes(file, result, False, showImplicit, addOn, priv);
104570728a38Smrg    ok = ok &&
104670728a38Smrg        XkbWriteXKBCompatMap(file, result, False, showImplicit, addOn, priv);
104770728a38Smrg    ok = ok &&
104870728a38Smrg        XkbWriteXKBSymbols(file, result, False, showImplicit, addOn, priv);
10498c9fbc29Smrg    if (xkb->geom)
105070728a38Smrg        ok = ok &&
105170728a38Smrg            XkbWriteXKBGeometry(file, result, False, showImplicit, addOn, priv);
105270728a38Smrg    fprintf(file, "};\n");
10538c9fbc29Smrg    return ok;
10548c9fbc29Smrg}
10558c9fbc29Smrg
10568c9fbc29SmrgBool
105770728a38SmrgXkbWriteXKBFile(FILE *                  out,
105870728a38Smrg                XkbFileInfo *           result,
105970728a38Smrg                Bool                    showImplicit,
106070728a38Smrg                XkbFileAddOnFunc        addOn,
106170728a38Smrg                void *                  priv)
10628c9fbc29Smrg{
106370728a38Smrg    Bool ok = False;
106470728a38Smrg
106570728a38Smrg    Bool (*func) (FILE *                /* file */ ,
106670728a38Smrg                  XkbFileInfo *         /* result */ ,
106770728a38Smrg                  Bool                  /* topLevel */ ,
106870728a38Smrg                  Bool                  /* showImplicit */ ,
106970728a38Smrg                  XkbFileAddOnFunc      /* addOn */ ,
107070728a38Smrg                  void *                /* priv */
107170728a38Smrg        ) = NULL;
10728c9fbc29Smrg
10738c9fbc29Smrg    switch (result->type) {
107470728a38Smrg    case XkmSemanticsFile:
107570728a38Smrg        func = XkbWriteXKBSemantics;
107670728a38Smrg        break;
107770728a38Smrg    case XkmLayoutFile:
107870728a38Smrg        func = XkbWriteXKBLayout;
107970728a38Smrg        break;
108070728a38Smrg    case XkmKeymapFile:
108170728a38Smrg        func = XkbWriteXKBKeymap;
108270728a38Smrg        break;
108370728a38Smrg    case XkmTypesIndex:
108470728a38Smrg        func = XkbWriteXKBKeyTypes;
108570728a38Smrg        break;
108670728a38Smrg    case XkmCompatMapIndex:
108770728a38Smrg        func = XkbWriteXKBCompatMap;
108870728a38Smrg        break;
108970728a38Smrg    case XkmSymbolsIndex:
109070728a38Smrg        func = XkbWriteXKBSymbols;
109170728a38Smrg        break;
109270728a38Smrg    case XkmKeyNamesIndex:
109370728a38Smrg        func = XkbWriteXKBKeycodes;
109470728a38Smrg        break;
109570728a38Smrg    case XkmGeometryFile:
109670728a38Smrg    case XkmGeometryIndex:
109770728a38Smrg        func = XkbWriteXKBGeometry;
109870728a38Smrg        break;
109970728a38Smrg    case XkmVirtualModsIndex:
110070728a38Smrg    case XkmIndicatorsIndex:
110170728a38Smrg        _XkbLibError(_XkbErrBadImplementation,
110270728a38Smrg                     XkbConfigText(result->type, XkbMessage), 0);
110370728a38Smrg        return False;
11048c9fbc29Smrg    }
110570728a38Smrg    if (out == NULL) {
110670728a38Smrg        _XkbLibError(_XkbErrFileCannotOpen, "XkbWriteXkbFile", 0);
110770728a38Smrg        ok = False;
11088c9fbc29Smrg    }
11098c9fbc29Smrg    else if (func) {
111070728a38Smrg        ok = (*func) (out, result, True, showImplicit, addOn, priv);
11118c9fbc29Smrg    }
11128c9fbc29Smrg    return ok;
11138c9fbc29Smrg}
1114