105b261ecSmrg/************************************************************
205b261ecSmrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrg Permission to use, copy, modify, and distribute this
505b261ecSmrg software and its documentation for any purpose and without
605b261ecSmrg fee is hereby granted, provided that the above copyright
705b261ecSmrg notice appear in all copies and that both that copyright
805b261ecSmrg notice and this permission notice appear in supporting
935c4bbdfSmrg documentation, and that the name of Silicon Graphics not be
1035c4bbdfSmrg used in advertising or publicity pertaining to distribution
1105b261ecSmrg of the software without specific prior written permission.
1235c4bbdfSmrg Silicon Graphics makes no representation about the suitability
1305b261ecSmrg of this software for any purpose. It is provided "as is"
1405b261ecSmrg without any express or implied warranty.
1535c4bbdfSmrg
1635c4bbdfSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1735c4bbdfSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1935c4bbdfSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2035c4bbdfSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2135c4bbdfSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg ********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <ctype.h>
3305b261ecSmrg#include <stdlib.h>
3405b261ecSmrg#include <X11/Xfuncs.h>
3505b261ecSmrg
3605b261ecSmrg#include <X11/X.h>
3705b261ecSmrg#include <X11/keysym.h>
3805b261ecSmrg#include <X11/Xproto.h>
396747b715Smrg#include <X11/extensions/XKMformat.h>
4005b261ecSmrg#include "misc.h"
4105b261ecSmrg#include "inputstr.h"
4205b261ecSmrg#include "dix.h"
434642e01fSmrg#include "xkbstr.h"
4405b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS	1
4505b261ecSmrg#include <xkbsrv.h>
4605b261ecSmrg
474642e01fSmrg#include "xkbgeom.h"
484642e01fSmrg#include "xkbfile.h"
4905b261ecSmrg
5005b261ecSmrg#define	VMOD_HIDE_VALUE	0
5105b261ecSmrg#define	VMOD_SHOW_VALUE	1
5205b261ecSmrg#define	VMOD_COMMENT_VALUE 2
5305b261ecSmrg
5405b261ecSmrgstatic Bool
5535c4bbdfSmrgWriteXKBVModDecl(FILE * file, XkbDescPtr xkb, int showValue)
5605b261ecSmrg{
5735c4bbdfSmrg    register int i, nMods;
5835c4bbdfSmrg    Atom *vmodNames;
5935c4bbdfSmrg
6035c4bbdfSmrg    if (xkb == NULL)
6135c4bbdfSmrg        return FALSE;
6235c4bbdfSmrg    if (xkb->names != NULL)
6335c4bbdfSmrg        vmodNames = xkb->names->vmods;
6435c4bbdfSmrg    else
6535c4bbdfSmrg        vmodNames = NULL;
6635c4bbdfSmrg
6735c4bbdfSmrg    for (i = nMods = 0; i < XkbNumVirtualMods; i++) {
6835c4bbdfSmrg        if ((vmodNames != NULL) && (vmodNames[i] != None)) {
6935c4bbdfSmrg            if (nMods == 0)
7035c4bbdfSmrg                fprintf(file, "    virtual_modifiers ");
7135c4bbdfSmrg            else
7235c4bbdfSmrg                fprintf(file, ",");
7335c4bbdfSmrg            fprintf(file, "%s", XkbAtomText(vmodNames[i], XkbXKBFile));
7435c4bbdfSmrg            if ((showValue != VMOD_HIDE_VALUE) &&
7535c4bbdfSmrg                (xkb->server) && (xkb->server->vmods[i] != XkbNoModifierMask)) {
7635c4bbdfSmrg                if (showValue == VMOD_COMMENT_VALUE) {
7735c4bbdfSmrg                    fprintf(file, "/* = %s */",
7835c4bbdfSmrg                            XkbModMaskText(xkb->server->vmods[i], XkbXKBFile));
7935c4bbdfSmrg                }
8035c4bbdfSmrg                else {
8135c4bbdfSmrg                    fprintf(file, "= %s",
8235c4bbdfSmrg                            XkbModMaskText(xkb->server->vmods[i], XkbXKBFile));
8335c4bbdfSmrg                }
8435c4bbdfSmrg            }
8535c4bbdfSmrg            nMods++;
8635c4bbdfSmrg        }
8735c4bbdfSmrg    }
8835c4bbdfSmrg    if (nMods > 0)
8935c4bbdfSmrg        fprintf(file, ";\n\n");
906747b715Smrg    return TRUE;
9105b261ecSmrg}
9205b261ecSmrg
9305b261ecSmrg/***====================================================================***/
9405b261ecSmrg
9505b261ecSmrgstatic Bool
9635c4bbdfSmrgWriteXKBAction(FILE * file, XkbDescPtr xkb, XkbAnyAction * action)
9705b261ecSmrg{
9835c4bbdfSmrg    fprintf(file, "%s", XkbActionText(xkb, (XkbAction *) action, XkbXKBFile));
996747b715Smrg    return TRUE;
10005b261ecSmrg}
10105b261ecSmrg
10205b261ecSmrg/***====================================================================***/
10305b261ecSmrg
10405b261ecSmrgBool
10535c4bbdfSmrgXkbWriteXKBKeycodes(FILE * file,
10635c4bbdfSmrg                    XkbDescPtr xkb,
10735c4bbdfSmrg                    Bool topLevel,
10835c4bbdfSmrg                    Bool showImplicit, XkbFileAddOnFunc addOn, void *priv)
10905b261ecSmrg{
11035c4bbdfSmrg    Atom kcName;
11135c4bbdfSmrg    register unsigned i;
11235c4bbdfSmrg    const char *alternate;
11335c4bbdfSmrg
11435c4bbdfSmrg    if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) {
11535c4bbdfSmrg        _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBKeycodes", 0);
11635c4bbdfSmrg        return FALSE;
11735c4bbdfSmrg    }
11835c4bbdfSmrg    kcName = xkb->names->keycodes;
11935c4bbdfSmrg    if (kcName != None)
12035c4bbdfSmrg        fprintf(file, "xkb_keycodes \"%s\" {\n",
12135c4bbdfSmrg                XkbAtomText(kcName, XkbXKBFile));
12235c4bbdfSmrg    else
12335c4bbdfSmrg        fprintf(file, "xkb_keycodes {\n");
12435c4bbdfSmrg    fprintf(file, "    minimum = %d;\n", xkb->min_key_code);
12535c4bbdfSmrg    fprintf(file, "    maximum = %d;\n", xkb->max_key_code);
12635c4bbdfSmrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
12735c4bbdfSmrg        if (xkb->names->keys[i].name[0] != '\0') {
12835c4bbdfSmrg            if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, TRUE) != i)
12935c4bbdfSmrg                alternate = "alternate ";
13035c4bbdfSmrg            else
13135c4bbdfSmrg                alternate = "";
13235c4bbdfSmrg            fprintf(file, "    %s%6s = %d;\n", alternate,
13335c4bbdfSmrg                    XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile), i);
13435c4bbdfSmrg        }
13535c4bbdfSmrg    }
13635c4bbdfSmrg    if (xkb->indicators != NULL) {
13735c4bbdfSmrg        for (i = 0; i < XkbNumIndicators; i++) {
13835c4bbdfSmrg            const char *type;
13935c4bbdfSmrg
14035c4bbdfSmrg            if (xkb->indicators->phys_indicators & (1 << i))
14135c4bbdfSmrg                type = "    ";
14235c4bbdfSmrg            else
14335c4bbdfSmrg                type = "    virtual ";
14435c4bbdfSmrg            if (xkb->names->indicators[i] != None) {
14535c4bbdfSmrg                fprintf(file, "%sindicator %d = \"%s\";\n", type, i + 1,
14635c4bbdfSmrg                        XkbAtomText(xkb->names->indicators[i], XkbXKBFile));
14735c4bbdfSmrg            }
14835c4bbdfSmrg        }
14935c4bbdfSmrg    }
15035c4bbdfSmrg    if (xkb->names->key_aliases != NULL) {
15135c4bbdfSmrg        XkbKeyAliasPtr pAl;
15235c4bbdfSmrg
15335c4bbdfSmrg        pAl = xkb->names->key_aliases;
15435c4bbdfSmrg        for (i = 0; i < xkb->names->num_key_aliases; i++, pAl++) {
15535c4bbdfSmrg            fprintf(file, "    alias %6s = %6s;\n",
15635c4bbdfSmrg                    XkbKeyNameText(pAl->alias, XkbXKBFile),
15735c4bbdfSmrg                    XkbKeyNameText(pAl->real, XkbXKBFile));
15835c4bbdfSmrg        }
15905b261ecSmrg    }
16005b261ecSmrg    if (addOn)
16135c4bbdfSmrg        (*addOn) (file, xkb, topLevel, showImplicit, XkmKeyNamesIndex, priv);
16235c4bbdfSmrg    fprintf(file, "};\n\n");
1636747b715Smrg    return TRUE;
16405b261ecSmrg}
16505b261ecSmrg
16605b261ecSmrgBool
16735c4bbdfSmrgXkbWriteXKBKeyTypes(FILE * file,
16835c4bbdfSmrg                    XkbDescPtr xkb,
16935c4bbdfSmrg                    Bool topLevel,
17035c4bbdfSmrg                    Bool showImplicit, XkbFileAddOnFunc addOn, void *priv)
17105b261ecSmrg{
17235c4bbdfSmrg    register unsigned i, n;
17335c4bbdfSmrg    XkbKeyTypePtr type;
17435c4bbdfSmrg    XkbKTMapEntryPtr entry;
17535c4bbdfSmrg
17635c4bbdfSmrg    if ((!xkb) || (!xkb->map) || (!xkb->map->types)) {
17735c4bbdfSmrg        _XkbLibError(_XkbErrMissingTypes, "XkbWriteXKBKeyTypes", 0);
17835c4bbdfSmrg        return FALSE;
17935c4bbdfSmrg    }
18035c4bbdfSmrg    if (xkb->map->num_types < XkbNumRequiredTypes) {
18135c4bbdfSmrg        _XkbLibError(_XkbErrMissingReqTypes, "XkbWriteXKBKeyTypes", 0);
18235c4bbdfSmrg        return 0;
18335c4bbdfSmrg    }
18435c4bbdfSmrg    if ((xkb->names == NULL) || (xkb->names->types == None))
18535c4bbdfSmrg        fprintf(file, "xkb_types {\n\n");
18635c4bbdfSmrg    else
18735c4bbdfSmrg        fprintf(file, "xkb_types \"%s\" {\n\n",
18835c4bbdfSmrg                XkbAtomText(xkb->names->types, XkbXKBFile));
18935c4bbdfSmrg    WriteXKBVModDecl(file, xkb,
19035c4bbdfSmrg                     (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE));
19135c4bbdfSmrg
19235c4bbdfSmrg    type = xkb->map->types;
19335c4bbdfSmrg    for (i = 0; i < xkb->map->num_types; i++, type++) {
19435c4bbdfSmrg        fprintf(file, "    type \"%s\" {\n",
19535c4bbdfSmrg                XkbAtomText(type->name, XkbXKBFile));
19635c4bbdfSmrg        fprintf(file, "        modifiers= %s;\n",
19735c4bbdfSmrg                XkbVModMaskText(xkb, type->mods.real_mods, type->mods.vmods,
19835c4bbdfSmrg                                XkbXKBFile));
19935c4bbdfSmrg        entry = type->map;
20035c4bbdfSmrg        for (n = 0; n < type->map_count; n++, entry++) {
20135c4bbdfSmrg            char *str;
20235c4bbdfSmrg
20335c4bbdfSmrg            str = XkbVModMaskText(xkb, entry->mods.real_mods, entry->mods.vmods,
20435c4bbdfSmrg                                  XkbXKBFile);
20535c4bbdfSmrg            fprintf(file, "        map[%s]= Level%d;\n", str, entry->level + 1);
20635c4bbdfSmrg            if ((type->preserve) && ((type->preserve[n].real_mods) ||
20735c4bbdfSmrg                                     (type->preserve[n].vmods))) {
20835c4bbdfSmrg                fprintf(file, "        preserve[%s]= ", str);
20935c4bbdfSmrg                fprintf(file, "%s;\n", XkbVModMaskText(xkb,
21035c4bbdfSmrg                                                       type->preserve[n].
21135c4bbdfSmrg                                                       real_mods,
21235c4bbdfSmrg                                                       type->preserve[n].vmods,
21335c4bbdfSmrg                                                       XkbXKBFile));
21435c4bbdfSmrg            }
21535c4bbdfSmrg        }
21635c4bbdfSmrg        if (type->level_names != NULL) {
21735c4bbdfSmrg            Atom *name = type->level_names;
21835c4bbdfSmrg
21935c4bbdfSmrg            for (n = 0; n < type->num_levels; n++, name++) {
22035c4bbdfSmrg                if ((*name) == None)
22135c4bbdfSmrg                    continue;
22235c4bbdfSmrg                fprintf(file, "        level_name[Level%d]= \"%s\";\n", n + 1,
22335c4bbdfSmrg                        XkbAtomText(*name, XkbXKBFile));
22435c4bbdfSmrg            }
22535c4bbdfSmrg        }
22635c4bbdfSmrg        fprintf(file, "    };\n");
22705b261ecSmrg    }
22805b261ecSmrg    if (addOn)
22935c4bbdfSmrg        (*addOn) (file, xkb, topLevel, showImplicit, XkmTypesIndex, priv);
23035c4bbdfSmrg    fprintf(file, "};\n\n");
2316747b715Smrg    return TRUE;
23205b261ecSmrg}
23305b261ecSmrg
23405b261ecSmrgstatic Bool
23535c4bbdfSmrgWriteXKBIndicatorMap(FILE * file,
23635c4bbdfSmrg                     XkbDescPtr xkb,
23735c4bbdfSmrg                     Atom name,
23835c4bbdfSmrg                     XkbIndicatorMapPtr led, XkbFileAddOnFunc addOn, void *priv)
23905b261ecSmrg{
24005b261ecSmrg
24135c4bbdfSmrg    fprintf(file, "    indicator \"%s\" {\n", NameForAtom(name));
24235c4bbdfSmrg    if (led->flags & XkbIM_NoExplicit)
24335c4bbdfSmrg        fprintf(file, "        !allowExplicit;\n");
24435c4bbdfSmrg    if (led->flags & XkbIM_LEDDrivesKB)
24535c4bbdfSmrg        fprintf(file, "        indicatorDrivesKeyboard;\n");
24635c4bbdfSmrg    if (led->which_groups != 0) {
24735c4bbdfSmrg        if (led->which_groups != XkbIM_UseEffective) {
24835c4bbdfSmrg            fprintf(file, "        whichGroupState= %s;\n",
24935c4bbdfSmrg                    XkbIMWhichStateMaskText(led->which_groups, XkbXKBFile));
25035c4bbdfSmrg        }
25135c4bbdfSmrg        fprintf(file, "        groups= 0x%02x;\n", led->groups);
25235c4bbdfSmrg    }
25335c4bbdfSmrg    if (led->which_mods != 0) {
25435c4bbdfSmrg        if (led->which_mods != XkbIM_UseEffective) {
25535c4bbdfSmrg            fprintf(file, "        whichModState= %s;\n",
25635c4bbdfSmrg                    XkbIMWhichStateMaskText(led->which_mods, XkbXKBFile));
25735c4bbdfSmrg        }
25835c4bbdfSmrg        fprintf(file, "        modifiers= %s;\n",
25935c4bbdfSmrg                XkbVModMaskText(xkb,
26035c4bbdfSmrg                                led->mods.real_mods, led->mods.vmods,
26135c4bbdfSmrg                                XkbXKBFile));
26235c4bbdfSmrg    }
26335c4bbdfSmrg    if (led->ctrls != 0) {
26435c4bbdfSmrg        fprintf(file, "        controls= %s;\n",
26535c4bbdfSmrg                XkbControlsMaskText(led->ctrls, XkbXKBFile));
26605b261ecSmrg    }
26705b261ecSmrg    if (addOn)
26835c4bbdfSmrg        (*addOn) (file, xkb, FALSE, TRUE, XkmIndicatorsIndex, priv);
26935c4bbdfSmrg    fprintf(file, "    };\n");
2706747b715Smrg    return TRUE;
27105b261ecSmrg}
27205b261ecSmrg
27305b261ecSmrgBool
27435c4bbdfSmrgXkbWriteXKBCompatMap(FILE * file,
27535c4bbdfSmrg                     XkbDescPtr xkb,
27635c4bbdfSmrg                     Bool topLevel,
27735c4bbdfSmrg                     Bool showImplicit, XkbFileAddOnFunc addOn, void *priv)
27805b261ecSmrg{
27935c4bbdfSmrg    register unsigned i;
28035c4bbdfSmrg    XkbSymInterpretPtr interp;
28135c4bbdfSmrg
28235c4bbdfSmrg    if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) {
28335c4bbdfSmrg        _XkbLibError(_XkbErrMissingCompatMap, "XkbWriteXKBCompatMap", 0);
28435c4bbdfSmrg        return FALSE;
28535c4bbdfSmrg    }
28635c4bbdfSmrg    if ((xkb->names == NULL) || (xkb->names->compat == None))
28735c4bbdfSmrg        fprintf(file, "xkb_compatibility {\n\n");
28835c4bbdfSmrg    else
28935c4bbdfSmrg        fprintf(file, "xkb_compatibility \"%s\" {\n\n",
29035c4bbdfSmrg                XkbAtomText(xkb->names->compat, XkbXKBFile));
29135c4bbdfSmrg    WriteXKBVModDecl(file, xkb,
29235c4bbdfSmrg                     (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE));
29335c4bbdfSmrg
29435c4bbdfSmrg    fprintf(file, "    interpret.useModMapMods= AnyLevel;\n");
29535c4bbdfSmrg    fprintf(file, "    interpret.repeat= FALSE;\n");
29635c4bbdfSmrg    fprintf(file, "    interpret.locking= FALSE;\n");
29735c4bbdfSmrg    interp = xkb->compat->sym_interpret;
29835c4bbdfSmrg    for (i = 0; i < xkb->compat->num_si; i++, interp++) {
29935c4bbdfSmrg        fprintf(file, "    interpret %s+%s(%s) {\n",
30035c4bbdfSmrg                ((interp->sym == NoSymbol) ? "Any" :
30135c4bbdfSmrg                 XkbKeysymText(interp->sym, XkbXKBFile)),
30235c4bbdfSmrg                XkbSIMatchText(interp->match, XkbXKBFile),
30335c4bbdfSmrg                XkbModMaskText(interp->mods, XkbXKBFile));
30435c4bbdfSmrg        if (interp->virtual_mod != XkbNoModifier) {
30535c4bbdfSmrg            fprintf(file, "        virtualModifier= %s;\n",
30635c4bbdfSmrg                    XkbVModIndexText(xkb, interp->virtual_mod, XkbXKBFile));
30735c4bbdfSmrg        }
30835c4bbdfSmrg        if (interp->match & XkbSI_LevelOneOnly)
30935c4bbdfSmrg            fprintf(file, "        useModMapMods=level1;\n");
31035c4bbdfSmrg        if (interp->flags & XkbSI_LockingKey)
31135c4bbdfSmrg            fprintf(file, "        locking= TRUE;\n");
31235c4bbdfSmrg        if (interp->flags & XkbSI_AutoRepeat)
31335c4bbdfSmrg            fprintf(file, "        repeat= TRUE;\n");
31435c4bbdfSmrg        fprintf(file, "        action= ");
31535c4bbdfSmrg        WriteXKBAction(file, xkb, &interp->act);
31635c4bbdfSmrg        fprintf(file, ";\n");
31735c4bbdfSmrg        fprintf(file, "    };\n");
31835c4bbdfSmrg    }
31935c4bbdfSmrg    for (i = 0; i < XkbNumKbdGroups; i++) {
32035c4bbdfSmrg        XkbModsPtr gc;
32135c4bbdfSmrg
32235c4bbdfSmrg        gc = &xkb->compat->groups[i];
32335c4bbdfSmrg        if ((gc->real_mods == 0) && (gc->vmods == 0))
32435c4bbdfSmrg            continue;
32535c4bbdfSmrg        fprintf(file, "    group %d = %s;\n", i + 1, XkbVModMaskText(xkb,
32635c4bbdfSmrg                                                                     gc->
32735c4bbdfSmrg                                                                     real_mods,
32835c4bbdfSmrg                                                                     gc->vmods,
32935c4bbdfSmrg                                                                     XkbXKBFile));
33005b261ecSmrg    }
33105b261ecSmrg    if (xkb->indicators) {
33235c4bbdfSmrg        for (i = 0; i < XkbNumIndicators; i++) {
33335c4bbdfSmrg            XkbIndicatorMapPtr map = &xkb->indicators->maps[i];
33435c4bbdfSmrg
33535c4bbdfSmrg            if ((map->flags != 0) || (map->which_groups != 0) ||
33635c4bbdfSmrg                (map->groups != 0) || (map->which_mods != 0) ||
33735c4bbdfSmrg                (map->mods.real_mods != 0) || (map->mods.vmods != 0) ||
33835c4bbdfSmrg                (map->ctrls != 0)) {
33935c4bbdfSmrg                WriteXKBIndicatorMap(file, xkb, xkb->names->indicators[i], map,
34035c4bbdfSmrg                                     addOn, priv);
34135c4bbdfSmrg            }
34235c4bbdfSmrg        }
34305b261ecSmrg    }
34405b261ecSmrg    if (addOn)
34535c4bbdfSmrg        (*addOn) (file, xkb, topLevel, showImplicit, XkmCompatMapIndex, priv);
34635c4bbdfSmrg    fprintf(file, "};\n\n");
3476747b715Smrg    return TRUE;
34805b261ecSmrg}
34905b261ecSmrg
35005b261ecSmrgBool
35135c4bbdfSmrgXkbWriteXKBSymbols(FILE * file,
35235c4bbdfSmrg                   XkbDescPtr xkb,
35335c4bbdfSmrg                   Bool topLevel,
35435c4bbdfSmrg                   Bool showImplicit, XkbFileAddOnFunc addOn, void *priv)
35505b261ecSmrg{
35635c4bbdfSmrg    register unsigned i, tmp;
35735c4bbdfSmrg    XkbClientMapPtr map;
35835c4bbdfSmrg    XkbServerMapPtr srv;
35935c4bbdfSmrg    Bool showActions;
36005b261ecSmrg
3616747b715Smrg    if (!xkb) {
36235c4bbdfSmrg        _XkbLibError(_XkbErrMissingSymbols, "XkbWriteXKBSymbols", 0);
36335c4bbdfSmrg        return FALSE;
36435c4bbdfSmrg    }
36535c4bbdfSmrg
36635c4bbdfSmrg    map = xkb->map;
36735c4bbdfSmrg    if ((!map) || (!map->syms) || (!map->key_sym_map)) {
36835c4bbdfSmrg        _XkbLibError(_XkbErrMissingSymbols, "XkbWriteXKBSymbols", 0);
36935c4bbdfSmrg        return FALSE;
37035c4bbdfSmrg    }
37135c4bbdfSmrg    if ((!xkb->names) || (!xkb->names->keys)) {
37235c4bbdfSmrg        _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBSymbols", 0);
37335c4bbdfSmrg        return FALSE;
37435c4bbdfSmrg    }
37535c4bbdfSmrg    if ((xkb->names == NULL) || (xkb->names->symbols == None))
37635c4bbdfSmrg        fprintf(file, "xkb_symbols {\n\n");
37735c4bbdfSmrg    else
37835c4bbdfSmrg        fprintf(file, "xkb_symbols \"%s\" {\n\n",
37935c4bbdfSmrg                XkbAtomText(xkb->names->symbols, XkbXKBFile));
38035c4bbdfSmrg    for (tmp = i = 0; i < XkbNumKbdGroups; i++) {
38135c4bbdfSmrg        if (xkb->names->groups[i] != None) {
38235c4bbdfSmrg            fprintf(file, "    name[group%d]=\"%s\";\n", i + 1,
38335c4bbdfSmrg                    XkbAtomText(xkb->names->groups[i], XkbXKBFile));
38435c4bbdfSmrg            tmp++;
38535c4bbdfSmrg        }
38635c4bbdfSmrg    }
38735c4bbdfSmrg    if (tmp > 0)
38835c4bbdfSmrg        fprintf(file, "\n");
38935c4bbdfSmrg    srv = xkb->server;
39035c4bbdfSmrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
39135c4bbdfSmrg        Bool simple;
39235c4bbdfSmrg
39335c4bbdfSmrg        if ((int) XkbKeyNumSyms(xkb, i) < 1)
39435c4bbdfSmrg            continue;
39535c4bbdfSmrg        if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, TRUE) != i)
39635c4bbdfSmrg            continue;
39735c4bbdfSmrg        simple = TRUE;
39835c4bbdfSmrg        fprintf(file, "    key %6s {",
39935c4bbdfSmrg                XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile));
40035c4bbdfSmrg        if (srv->explicit) {
40135c4bbdfSmrg            if (((srv->explicit[i] & XkbExplicitKeyTypesMask) != 0) ||
40235c4bbdfSmrg                (showImplicit)) {
40335c4bbdfSmrg                int typeNdx, g;
40435c4bbdfSmrg                Bool multi;
40535c4bbdfSmrg                const char *comment = "  ";
40635c4bbdfSmrg
40735c4bbdfSmrg                if ((srv->explicit[i] & XkbExplicitKeyTypesMask) == 0)
40835c4bbdfSmrg                    comment = "//";
40935c4bbdfSmrg                multi = FALSE;
41035c4bbdfSmrg                typeNdx = XkbKeyKeyTypeIndex(xkb, i, 0);
41135c4bbdfSmrg                for (g = 1; (g < XkbKeyNumGroups(xkb, i)) && (!multi); g++) {
41235c4bbdfSmrg                    if (XkbKeyKeyTypeIndex(xkb, i, g) != typeNdx)
41335c4bbdfSmrg                        multi = TRUE;
41435c4bbdfSmrg                }
41535c4bbdfSmrg                if (multi) {
41635c4bbdfSmrg                    for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) {
41735c4bbdfSmrg                        typeNdx = XkbKeyKeyTypeIndex(xkb, i, g);
41835c4bbdfSmrg                        if (srv->explicit[i] & (1 << g)) {
41935c4bbdfSmrg                            fprintf(file, "\n%s      type[group%d]= \"%s\",",
42035c4bbdfSmrg                                    comment, g + 1,
42135c4bbdfSmrg                                    XkbAtomText(map->types[typeNdx].name,
42235c4bbdfSmrg                                                XkbXKBFile));
42335c4bbdfSmrg                        }
42435c4bbdfSmrg                        else if (showImplicit) {
42535c4bbdfSmrg                            fprintf(file, "\n//      type[group%d]= \"%s\",",
42635c4bbdfSmrg                                    g + 1, XkbAtomText(map->types[typeNdx].name,
42735c4bbdfSmrg                                                       XkbXKBFile));
42835c4bbdfSmrg                        }
42935c4bbdfSmrg                    }
43035c4bbdfSmrg                }
43135c4bbdfSmrg                else {
43235c4bbdfSmrg                    fprintf(file, "\n%s      type= \"%s\",", comment,
43335c4bbdfSmrg                            XkbAtomText(map->types[typeNdx].name, XkbXKBFile));
43435c4bbdfSmrg                }
43535c4bbdfSmrg                simple = FALSE;
43635c4bbdfSmrg            }
43735c4bbdfSmrg            if (((srv->explicit[i] & XkbExplicitAutoRepeatMask) != 0) &&
43835c4bbdfSmrg                (xkb->ctrls != NULL)) {
43935c4bbdfSmrg                if (xkb->ctrls->per_key_repeat[i / 8] & (1 << (i % 8)))
44035c4bbdfSmrg                    fprintf(file, "\n        repeat= Yes,");
44135c4bbdfSmrg                else
44235c4bbdfSmrg                    fprintf(file, "\n        repeat= No,");
44335c4bbdfSmrg                simple = FALSE;
44435c4bbdfSmrg            }
44535c4bbdfSmrg            if ((xkb->server != NULL) && (xkb->server->vmodmap != NULL) &&
44635c4bbdfSmrg                (xkb->server->vmodmap[i] != 0)) {
44735c4bbdfSmrg                if ((srv->explicit[i] & XkbExplicitVModMapMask) != 0) {
44835c4bbdfSmrg                    fprintf(file, "\n        virtualMods= %s,",
44935c4bbdfSmrg                            XkbVModMaskText(xkb, 0,
45035c4bbdfSmrg                                            xkb->server->vmodmap[i],
45135c4bbdfSmrg                                            XkbXKBFile));
45235c4bbdfSmrg                }
45335c4bbdfSmrg                else if (showImplicit) {
45435c4bbdfSmrg                    fprintf(file, "\n//      virtualMods= %s,",
45535c4bbdfSmrg                            XkbVModMaskText(xkb, 0,
45635c4bbdfSmrg                                            xkb->server->vmodmap[i],
45735c4bbdfSmrg                                            XkbXKBFile));
45835c4bbdfSmrg                }
45935c4bbdfSmrg            }
46035c4bbdfSmrg        }
46135c4bbdfSmrg        switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb, i))) {
46235c4bbdfSmrg        case XkbClampIntoRange:
46335c4bbdfSmrg            fprintf(file, "\n        groupsClamp,");
46435c4bbdfSmrg            break;
46535c4bbdfSmrg        case XkbRedirectIntoRange:
46635c4bbdfSmrg            fprintf(file, "\n        groupsRedirect= Group%d,",
46735c4bbdfSmrg                    XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb, i)) + 1);
46835c4bbdfSmrg            break;
46935c4bbdfSmrg        }
47035c4bbdfSmrg        if (srv->behaviors != NULL) {
47135c4bbdfSmrg            unsigned type;
47235c4bbdfSmrg
47335c4bbdfSmrg            type = srv->behaviors[i].type & XkbKB_OpMask;
47435c4bbdfSmrg
47535c4bbdfSmrg            if (type != XkbKB_Default) {
47635c4bbdfSmrg                simple = FALSE;
47735c4bbdfSmrg                fprintf(file, "\n        %s,",
47835c4bbdfSmrg                        XkbBehaviorText(xkb, &srv->behaviors[i], XkbXKBFile));
47935c4bbdfSmrg            }
48035c4bbdfSmrg        }
48135c4bbdfSmrg        if ((srv->explicit == NULL) || showImplicit ||
48235c4bbdfSmrg            ((srv->explicit[i] & XkbExplicitInterpretMask) != 0))
48335c4bbdfSmrg            showActions = XkbKeyHasActions(xkb, i);
48435c4bbdfSmrg        else
48535c4bbdfSmrg            showActions = FALSE;
48635c4bbdfSmrg
48735c4bbdfSmrg        if (((unsigned) XkbKeyNumGroups(xkb, i) > 1) || showActions)
48835c4bbdfSmrg            simple = FALSE;
48935c4bbdfSmrg        if (simple) {
49035c4bbdfSmrg            KeySym *syms;
49135c4bbdfSmrg            unsigned s;
49235c4bbdfSmrg
49335c4bbdfSmrg            syms = XkbKeySymsPtr(xkb, i);
49435c4bbdfSmrg            fprintf(file, "         [ ");
49535c4bbdfSmrg            for (s = 0; s < XkbKeyGroupWidth(xkb, i, XkbGroup1Index); s++) {
49635c4bbdfSmrg                if (s != 0)
49735c4bbdfSmrg                    fprintf(file, ", ");
49835c4bbdfSmrg                fprintf(file, "%15s", XkbKeysymText(*syms++, XkbXKBFile));
49935c4bbdfSmrg            }
50035c4bbdfSmrg            fprintf(file, " ] };\n");
50135c4bbdfSmrg        }
50235c4bbdfSmrg        else {
50335c4bbdfSmrg            unsigned g, s;
50435c4bbdfSmrg            KeySym *syms;
50535c4bbdfSmrg            XkbAction *acts;
50635c4bbdfSmrg
50735c4bbdfSmrg            syms = XkbKeySymsPtr(xkb, i);
50835c4bbdfSmrg            acts = XkbKeyActionsPtr(xkb, i);
50935c4bbdfSmrg            for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) {
51035c4bbdfSmrg                if (g != 0)
51135c4bbdfSmrg                    fprintf(file, ",");
51235c4bbdfSmrg                fprintf(file, "\n        symbols[Group%d]= [ ", g + 1);
51335c4bbdfSmrg                for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) {
51435c4bbdfSmrg                    if (s != 0)
51535c4bbdfSmrg                        fprintf(file, ", ");
51635c4bbdfSmrg                    fprintf(file, "%15s", XkbKeysymText(syms[s], XkbXKBFile));
51735c4bbdfSmrg                }
51835c4bbdfSmrg                fprintf(file, " ]");
51935c4bbdfSmrg                syms += XkbKeyGroupsWidth(xkb, i);
52035c4bbdfSmrg                if (showActions) {
52135c4bbdfSmrg                    fprintf(file, ",\n        actions[Group%d]= [ ", g + 1);
52235c4bbdfSmrg                    for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) {
52335c4bbdfSmrg                        if (s != 0)
52435c4bbdfSmrg                            fprintf(file, ", ");
52535c4bbdfSmrg                        WriteXKBAction(file, xkb, (XkbAnyAction *) &acts[s]);
52635c4bbdfSmrg                    }
52735c4bbdfSmrg                    fprintf(file, " ]");
52835c4bbdfSmrg                    acts += XkbKeyGroupsWidth(xkb, i);
52935c4bbdfSmrg                }
53035c4bbdfSmrg            }
53135c4bbdfSmrg            fprintf(file, "\n    };\n");
53235c4bbdfSmrg        }
53305b261ecSmrg    }
53405b261ecSmrg    if (map && map->modmap) {
53535c4bbdfSmrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
53635c4bbdfSmrg            if (map->modmap[i] != 0) {
53735c4bbdfSmrg                register int n, bit;
53835c4bbdfSmrg
53935c4bbdfSmrg                for (bit = 1, n = 0; n < XkbNumModifiers; n++, bit <<= 1) {
54035c4bbdfSmrg                    if (map->modmap[i] & bit) {
54135c4bbdfSmrg                        char buf[5];
54235c4bbdfSmrg
54335c4bbdfSmrg                        memcpy(buf, xkb->names->keys[i].name, 4);
54435c4bbdfSmrg                        buf[4] = '\0';
54535c4bbdfSmrg                        fprintf(file, "    modifier_map %s { <%s> };\n",
54635c4bbdfSmrg                                XkbModIndexText(n, XkbXKBFile), buf);
54735c4bbdfSmrg                    }
54835c4bbdfSmrg                }
54935c4bbdfSmrg            }
55035c4bbdfSmrg        }
55105b261ecSmrg    }
55205b261ecSmrg    if (addOn)
55335c4bbdfSmrg        (*addOn) (file, xkb, topLevel, showImplicit, XkmSymbolsIndex, priv);
55435c4bbdfSmrg    fprintf(file, "};\n\n");
5556747b715Smrg    return TRUE;
55605b261ecSmrg}
55705b261ecSmrg
55805b261ecSmrgstatic Bool
55935c4bbdfSmrgWriteXKBOutline(FILE * file,
56035c4bbdfSmrg                XkbShapePtr shape,
56135c4bbdfSmrg                XkbOutlinePtr outline, int lastRadius, int first, int indent)
56205b261ecSmrg{
56335c4bbdfSmrg    register int i;
56435c4bbdfSmrg    XkbPointPtr pt;
56535c4bbdfSmrg    char *iStr;
56635c4bbdfSmrg
56735c4bbdfSmrg    fprintf(file, "%s", iStr = XkbIndentText(first));
56835c4bbdfSmrg    if (first != indent)
56935c4bbdfSmrg        iStr = XkbIndentText(indent);
57035c4bbdfSmrg    if (outline->corner_radius != lastRadius) {
57135c4bbdfSmrg        fprintf(file, "corner= %s,",
57235c4bbdfSmrg                XkbGeomFPText(outline->corner_radius, XkbMessage));
57335c4bbdfSmrg        if (shape != NULL) {
57435c4bbdfSmrg            fprintf(file, "\n%s", iStr);
57535c4bbdfSmrg        }
57605b261ecSmrg    }
57705b261ecSmrg    if (shape) {
57835c4bbdfSmrg        if (outline == shape->approx)
57935c4bbdfSmrg            fprintf(file, "approx= ");
58035c4bbdfSmrg        else if (outline == shape->primary)
58135c4bbdfSmrg            fprintf(file, "primary= ");
58235c4bbdfSmrg    }
58335c4bbdfSmrg    fprintf(file, "{");
58435c4bbdfSmrg    for (pt = outline->points, i = 0; i < outline->num_points; i++, pt++) {
58535c4bbdfSmrg        if (i == 0)
58635c4bbdfSmrg            fprintf(file, " ");
58735c4bbdfSmrg        else if ((i % 4) == 0)
58835c4bbdfSmrg            fprintf(file, ",\n%s  ", iStr);
58935c4bbdfSmrg        else
59035c4bbdfSmrg            fprintf(file, ", ");
59135c4bbdfSmrg        fprintf(file, "[ %3s, %3s ]", XkbGeomFPText(pt->x, XkbXKBFile),
59235c4bbdfSmrg                XkbGeomFPText(pt->y, XkbXKBFile));
59335c4bbdfSmrg    }
59435c4bbdfSmrg    fprintf(file, " }");
5956747b715Smrg    return TRUE;
59605b261ecSmrg}
59705b261ecSmrg
59805b261ecSmrgstatic Bool
59935c4bbdfSmrgWriteXKBDoodad(FILE * file,
60035c4bbdfSmrg               unsigned indent, XkbGeometryPtr geom, XkbDoodadPtr doodad)
60105b261ecSmrg{
60235c4bbdfSmrg    register char *i_str;
60335c4bbdfSmrg    XkbShapePtr shape;
60435c4bbdfSmrg    XkbColorPtr color;
60535c4bbdfSmrg
60635c4bbdfSmrg    i_str = XkbIndentText(indent);
60735c4bbdfSmrg    fprintf(file, "%s%s \"%s\" {\n", i_str,
60835c4bbdfSmrg            XkbDoodadTypeText(doodad->any.type, XkbMessage),
60935c4bbdfSmrg            XkbAtomText(doodad->any.name, XkbMessage));
61035c4bbdfSmrg    fprintf(file, "%s    top=      %s;\n", i_str,
61135c4bbdfSmrg            XkbGeomFPText(doodad->any.top, XkbXKBFile));
61235c4bbdfSmrg    fprintf(file, "%s    left=     %s;\n", i_str,
61335c4bbdfSmrg            XkbGeomFPText(doodad->any.left, XkbXKBFile));
61435c4bbdfSmrg    fprintf(file, "%s    priority= %d;\n", i_str, doodad->any.priority);
61505b261ecSmrg    switch (doodad->any.type) {
61635c4bbdfSmrg    case XkbOutlineDoodad:
61735c4bbdfSmrg    case XkbSolidDoodad:
61835c4bbdfSmrg        if (doodad->shape.angle != 0) {
61935c4bbdfSmrg            fprintf(file, "%s    angle=  %s;\n", i_str,
62035c4bbdfSmrg                    XkbGeomFPText(doodad->shape.angle, XkbXKBFile));
62135c4bbdfSmrg        }
62235c4bbdfSmrg        if (doodad->shape.color_ndx != 0) {
62335c4bbdfSmrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
62435c4bbdfSmrg                    XkbShapeDoodadColor(geom, &doodad->shape)->spec);
62535c4bbdfSmrg        }
62635c4bbdfSmrg        shape = XkbShapeDoodadShape(geom, &doodad->shape);
62735c4bbdfSmrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
62835c4bbdfSmrg                XkbAtomText(shape->name, XkbXKBFile));
62935c4bbdfSmrg        break;
63035c4bbdfSmrg    case XkbTextDoodad:
63135c4bbdfSmrg        if (doodad->text.angle != 0) {
63235c4bbdfSmrg            fprintf(file, "%s    angle=  %s;\n", i_str,
63335c4bbdfSmrg                    XkbGeomFPText(doodad->text.angle, XkbXKBFile));
63435c4bbdfSmrg        }
63535c4bbdfSmrg        if (doodad->text.width != 0) {
63635c4bbdfSmrg            fprintf(file, "%s    width=  %s;\n", i_str,
63735c4bbdfSmrg                    XkbGeomFPText(doodad->text.width, XkbXKBFile));
63835c4bbdfSmrg
63935c4bbdfSmrg        }
64035c4bbdfSmrg        if (doodad->text.height != 0) {
64135c4bbdfSmrg            fprintf(file, "%s    height=  %s;\n", i_str,
64235c4bbdfSmrg                    XkbGeomFPText(doodad->text.height, XkbXKBFile));
64335c4bbdfSmrg
64435c4bbdfSmrg        }
64535c4bbdfSmrg        if (doodad->text.color_ndx != 0) {
64635c4bbdfSmrg            color = XkbTextDoodadColor(geom, &doodad->text);
64735c4bbdfSmrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
64835c4bbdfSmrg                    XkbStringText(color->spec, XkbXKBFile));
64935c4bbdfSmrg        }
65035c4bbdfSmrg        fprintf(file, "%s    XFont= \"%s\";\n", i_str,
65135c4bbdfSmrg                XkbStringText(doodad->text.font, XkbXKBFile));
65235c4bbdfSmrg        fprintf(file, "%s    text=  \"%s\";\n", i_str,
65335c4bbdfSmrg                XkbStringText(doodad->text.text, XkbXKBFile));
65435c4bbdfSmrg        break;
65535c4bbdfSmrg    case XkbIndicatorDoodad:
65635c4bbdfSmrg        shape = XkbIndicatorDoodadShape(geom, &doodad->indicator);
65735c4bbdfSmrg        color = XkbIndicatorDoodadOnColor(geom, &doodad->indicator);
65835c4bbdfSmrg        fprintf(file, "%s    onColor= \"%s\";\n", i_str,
65935c4bbdfSmrg                XkbStringText(color->spec, XkbXKBFile));
66035c4bbdfSmrg        color = XkbIndicatorDoodadOffColor(geom, &doodad->indicator);
66135c4bbdfSmrg        fprintf(file, "%s    offColor= \"%s\";\n", i_str,
66235c4bbdfSmrg                XkbStringText(color->spec, XkbXKBFile));
66335c4bbdfSmrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
66435c4bbdfSmrg                XkbAtomText(shape->name, XkbXKBFile));
66535c4bbdfSmrg        break;
66635c4bbdfSmrg    case XkbLogoDoodad:
66735c4bbdfSmrg        fprintf(file, "%s    logoName= \"%s\";\n", i_str,
66835c4bbdfSmrg                XkbStringText(doodad->logo.logo_name, XkbXKBFile));
66935c4bbdfSmrg        if (doodad->shape.angle != 0) {
67035c4bbdfSmrg            fprintf(file, "%s    angle=  %s;\n", i_str,
67135c4bbdfSmrg                    XkbGeomFPText(doodad->logo.angle, XkbXKBFile));
67235c4bbdfSmrg        }
67335c4bbdfSmrg        if (doodad->shape.color_ndx != 0) {
67435c4bbdfSmrg            fprintf(file, "%s    color= \"%s\";\n", i_str,
67535c4bbdfSmrg                    XkbLogoDoodadColor(geom, &doodad->logo)->spec);
67635c4bbdfSmrg        }
67735c4bbdfSmrg        shape = XkbLogoDoodadShape(geom, &doodad->logo);
67835c4bbdfSmrg        fprintf(file, "%s    shape= \"%s\";\n", i_str,
67935c4bbdfSmrg                XkbAtomText(shape->name, XkbXKBFile));
68035c4bbdfSmrg        break;
68135c4bbdfSmrg    }
68235c4bbdfSmrg    fprintf(file, "%s};\n", i_str);
6836747b715Smrg    return TRUE;
68405b261ecSmrg}
68505b261ecSmrg
68635c4bbdfSmrg /*ARGSUSED*/ static Bool
68735c4bbdfSmrgWriteXKBOverlay(FILE * file,
68835c4bbdfSmrg                unsigned indent, XkbGeometryPtr geom, XkbOverlayPtr ol)
68905b261ecSmrg{
69035c4bbdfSmrg    register char *i_str;
69135c4bbdfSmrg    int r, k, nOut;
69235c4bbdfSmrg    XkbOverlayRowPtr row;
69335c4bbdfSmrg    XkbOverlayKeyPtr key;
69435c4bbdfSmrg
69535c4bbdfSmrg    i_str = XkbIndentText(indent);
69635c4bbdfSmrg    if (ol->name != None) {
69735c4bbdfSmrg        fprintf(file, "%soverlay \"%s\" {\n", i_str,
69835c4bbdfSmrg                XkbAtomText(ol->name, XkbMessage));
69935c4bbdfSmrg    }
70035c4bbdfSmrg    else
70135c4bbdfSmrg        fprintf(file, "%soverlay {\n", i_str);
70235c4bbdfSmrg    for (nOut = r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
70335c4bbdfSmrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
70435c4bbdfSmrg            char *over, *under;
70535c4bbdfSmrg
70635c4bbdfSmrg            over = XkbKeyNameText(key->over.name, XkbXKBFile);
70735c4bbdfSmrg            under = XkbKeyNameText(key->under.name, XkbXKBFile);
70835c4bbdfSmrg            if (nOut == 0)
70935c4bbdfSmrg                fprintf(file, "%s    %6s=%6s", i_str, under, over);
71035c4bbdfSmrg            else if ((nOut % 4) == 0)
71135c4bbdfSmrg                fprintf(file, ",\n%s    %6s=%6s", i_str, under, over);
71235c4bbdfSmrg            else
71335c4bbdfSmrg                fprintf(file, ", %6s=%6s", under, over);
71435c4bbdfSmrg            nOut++;
71535c4bbdfSmrg        }
71635c4bbdfSmrg    }
71735c4bbdfSmrg    fprintf(file, "\n%s};\n", i_str);
7186747b715Smrg    return TRUE;
71905b261ecSmrg}
72005b261ecSmrg
72105b261ecSmrgstatic Bool
72235c4bbdfSmrgWriteXKBSection(FILE * file, XkbSectionPtr s, XkbGeometryPtr geom)
72305b261ecSmrg{
72435c4bbdfSmrg    register int i;
72535c4bbdfSmrg    XkbRowPtr row;
72635c4bbdfSmrg    int dfltKeyColor = 0;
72735c4bbdfSmrg
72835c4bbdfSmrg    fprintf(file, "    section \"%s\" {\n", XkbAtomText(s->name, XkbXKBFile));
72935c4bbdfSmrg    if (s->rows && (s->rows->num_keys > 0)) {
73035c4bbdfSmrg        dfltKeyColor = s->rows->keys[0].color_ndx;
73135c4bbdfSmrg        fprintf(file, "        key.color= \"%s\";\n",
73235c4bbdfSmrg                XkbStringText(geom->colors[dfltKeyColor].spec, XkbXKBFile));
73335c4bbdfSmrg    }
73435c4bbdfSmrg    fprintf(file, "        priority=  %d;\n", s->priority);
73535c4bbdfSmrg    fprintf(file, "        top=       %s;\n",
73635c4bbdfSmrg            XkbGeomFPText(s->top, XkbXKBFile));
73735c4bbdfSmrg    fprintf(file, "        left=      %s;\n",
73835c4bbdfSmrg            XkbGeomFPText(s->left, XkbXKBFile));
73935c4bbdfSmrg    fprintf(file, "        width=     %s;\n",
74035c4bbdfSmrg            XkbGeomFPText(s->width, XkbXKBFile));
74135c4bbdfSmrg    fprintf(file, "        height=    %s;\n",
74235c4bbdfSmrg            XkbGeomFPText(s->height, XkbXKBFile));
74335c4bbdfSmrg    if (s->angle != 0) {
74435c4bbdfSmrg        fprintf(file, "        angle=  %s;\n",
74535c4bbdfSmrg                XkbGeomFPText(s->angle, XkbXKBFile));
74635c4bbdfSmrg    }
74735c4bbdfSmrg    for (i = 0, row = s->rows; i < s->num_rows; i++, row++) {
74835c4bbdfSmrg        fprintf(file, "        row {\n");
74935c4bbdfSmrg        fprintf(file, "            top=  %s;\n",
75035c4bbdfSmrg                XkbGeomFPText(row->top, XkbXKBFile));
75135c4bbdfSmrg        fprintf(file, "            left= %s;\n",
75235c4bbdfSmrg                XkbGeomFPText(row->left, XkbXKBFile));
75335c4bbdfSmrg        if (row->vertical)
75435c4bbdfSmrg            fprintf(file, "            vertical;\n");
75535c4bbdfSmrg        if (row->num_keys > 0) {
75635c4bbdfSmrg            register int k;
75735c4bbdfSmrg            register XkbKeyPtr key;
75835c4bbdfSmrg            int forceNL = 0;
75935c4bbdfSmrg            int nThisLine = 0;
76035c4bbdfSmrg
76135c4bbdfSmrg            fprintf(file, "            keys {\n");
76235c4bbdfSmrg            for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
76335c4bbdfSmrg                XkbShapePtr shape;
76435c4bbdfSmrg
76535c4bbdfSmrg                if (key->color_ndx != dfltKeyColor)
76635c4bbdfSmrg                    forceNL = 1;
76735c4bbdfSmrg                if (k == 0) {
76835c4bbdfSmrg                    fprintf(file, "                ");
76935c4bbdfSmrg                    nThisLine = 0;
77035c4bbdfSmrg                }
77135c4bbdfSmrg                else if (((nThisLine % 2) == 1) || (forceNL)) {
77235c4bbdfSmrg                    fprintf(file, ",\n                ");
77335c4bbdfSmrg                    forceNL = nThisLine = 0;
77435c4bbdfSmrg                }
77535c4bbdfSmrg                else {
77635c4bbdfSmrg                    fprintf(file, ", ");
77735c4bbdfSmrg                    nThisLine++;
77835c4bbdfSmrg                }
77935c4bbdfSmrg                shape = XkbKeyShape(geom, key);
78035c4bbdfSmrg                fprintf(file, "{ %6s, \"%s\", %3s",
78135c4bbdfSmrg                        XkbKeyNameText(key->name.name, XkbXKBFile),
78235c4bbdfSmrg                        XkbAtomText(shape->name, XkbXKBFile),
78335c4bbdfSmrg                        XkbGeomFPText(key->gap, XkbXKBFile));
78435c4bbdfSmrg                if (key->color_ndx != dfltKeyColor) {
78535c4bbdfSmrg                    fprintf(file, ", color=\"%s\"",
78635c4bbdfSmrg                            XkbKeyColor(geom, key)->spec);
78735c4bbdfSmrg                    forceNL = 1;
78835c4bbdfSmrg                }
78935c4bbdfSmrg                fprintf(file, " }");
79035c4bbdfSmrg            }
79135c4bbdfSmrg            fprintf(file, "\n            };\n");
79235c4bbdfSmrg        }
79335c4bbdfSmrg        fprintf(file, "        };\n");
79435c4bbdfSmrg    }
79535c4bbdfSmrg    if (s->doodads != NULL) {
79635c4bbdfSmrg        XkbDoodadPtr doodad;
79735c4bbdfSmrg
79835c4bbdfSmrg        for (i = 0, doodad = s->doodads; i < s->num_doodads; i++, doodad++) {
79935c4bbdfSmrg            WriteXKBDoodad(file, 8, geom, doodad);
80035c4bbdfSmrg        }
80135c4bbdfSmrg    }
80235c4bbdfSmrg    if (s->overlays != NULL) {
80335c4bbdfSmrg        XkbOverlayPtr ol;
80435c4bbdfSmrg
80535c4bbdfSmrg        for (i = 0, ol = s->overlays; i < s->num_overlays; i++, ol++) {
80635c4bbdfSmrg            WriteXKBOverlay(file, 8, geom, ol);
80735c4bbdfSmrg        }
80835c4bbdfSmrg    }
80935c4bbdfSmrg    fprintf(file, "    }; // End of \"%s\" section\n\n",
81035c4bbdfSmrg            XkbAtomText(s->name, XkbXKBFile));
8116747b715Smrg    return TRUE;
81205b261ecSmrg}
81305b261ecSmrg
81405b261ecSmrgBool
81535c4bbdfSmrgXkbWriteXKBGeometry(FILE * file,
81635c4bbdfSmrg                    XkbDescPtr xkb,
81735c4bbdfSmrg                    Bool topLevel,
81835c4bbdfSmrg                    Bool showImplicit, XkbFileAddOnFunc addOn, void *priv)
81905b261ecSmrg{
82035c4bbdfSmrg    register unsigned i, n;
82135c4bbdfSmrg    XkbGeometryPtr geom;
82235c4bbdfSmrg
82335c4bbdfSmrg    if ((!xkb) || (!xkb->geom)) {
82435c4bbdfSmrg        _XkbLibError(_XkbErrMissingGeometry, "XkbWriteXKBGeometry", 0);
82535c4bbdfSmrg        return FALSE;
82635c4bbdfSmrg    }
82735c4bbdfSmrg    geom = xkb->geom;
82835c4bbdfSmrg    if (geom->name == None)
82935c4bbdfSmrg        fprintf(file, "xkb_geometry {\n\n");
83035c4bbdfSmrg    else
83135c4bbdfSmrg        fprintf(file, "xkb_geometry \"%s\" {\n\n",
83235c4bbdfSmrg                XkbAtomText(geom->name, XkbXKBFile));
83335c4bbdfSmrg    fprintf(file, "    width=       %s;\n",
83435c4bbdfSmrg            XkbGeomFPText(geom->width_mm, XkbXKBFile));
83535c4bbdfSmrg    fprintf(file, "    height=      %s;\n\n",
83635c4bbdfSmrg            XkbGeomFPText(geom->height_mm, XkbXKBFile));
83735c4bbdfSmrg
83835c4bbdfSmrg    if (geom->key_aliases != NULL) {
83935c4bbdfSmrg        XkbKeyAliasPtr pAl;
84035c4bbdfSmrg
84135c4bbdfSmrg        pAl = geom->key_aliases;
84235c4bbdfSmrg        for (i = 0; i < geom->num_key_aliases; i++, pAl++) {
84335c4bbdfSmrg            fprintf(file, "    alias %6s = %6s;\n",
84435c4bbdfSmrg                    XkbKeyNameText(pAl->alias, XkbXKBFile),
84535c4bbdfSmrg                    XkbKeyNameText(pAl->real, XkbXKBFile));
84635c4bbdfSmrg        }
84735c4bbdfSmrg        fprintf(file, "\n");
84835c4bbdfSmrg    }
84935c4bbdfSmrg
85035c4bbdfSmrg    if (geom->base_color != NULL)
85135c4bbdfSmrg        fprintf(file, "    baseColor=   \"%s\";\n",
85235c4bbdfSmrg                XkbStringText(geom->base_color->spec, XkbXKBFile));
85335c4bbdfSmrg    if (geom->label_color != NULL)
85435c4bbdfSmrg        fprintf(file, "    labelColor=  \"%s\";\n",
85535c4bbdfSmrg                XkbStringText(geom->label_color->spec, XkbXKBFile));
85635c4bbdfSmrg    if (geom->label_font != NULL)
85735c4bbdfSmrg        fprintf(file, "    xfont=       \"%s\";\n",
85835c4bbdfSmrg                XkbStringText(geom->label_font, XkbXKBFile));
85935c4bbdfSmrg    if ((geom->num_colors > 0) && (showImplicit)) {
86035c4bbdfSmrg        XkbColorPtr color;
86135c4bbdfSmrg
86235c4bbdfSmrg        for (color = geom->colors, i = 0; i < geom->num_colors; i++, color++) {
86335c4bbdfSmrg            fprintf(file, "//     color[%d]= \"%s\"\n", i,
86435c4bbdfSmrg                    XkbStringText(color->spec, XkbXKBFile));
86535c4bbdfSmrg        }
86635c4bbdfSmrg        fprintf(file, "\n");
86735c4bbdfSmrg    }
86835c4bbdfSmrg    if (geom->num_properties > 0) {
86935c4bbdfSmrg        XkbPropertyPtr prop;
87035c4bbdfSmrg
87135c4bbdfSmrg        for (prop = geom->properties, i = 0; i < geom->num_properties;
87235c4bbdfSmrg             i++, prop++) {
87335c4bbdfSmrg            fprintf(file, "    %s= \"%s\";\n", prop->name,
87435c4bbdfSmrg                    XkbStringText(prop->value, XkbXKBFile));
87535c4bbdfSmrg        }
87635c4bbdfSmrg        fprintf(file, "\n");
87735c4bbdfSmrg    }
87835c4bbdfSmrg    if (geom->num_shapes > 0) {
87935c4bbdfSmrg        XkbShapePtr shape;
88035c4bbdfSmrg        XkbOutlinePtr outline;
88135c4bbdfSmrg        int lastR;
88235c4bbdfSmrg
88335c4bbdfSmrg        for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) {
88435c4bbdfSmrg            lastR = 0;
88535c4bbdfSmrg            fprintf(file, "    shape \"%s\" {",
88635c4bbdfSmrg                    XkbAtomText(shape->name, XkbXKBFile));
88735c4bbdfSmrg            outline = shape->outlines;
88835c4bbdfSmrg            if (shape->num_outlines > 1) {
88935c4bbdfSmrg                for (n = 0; n < shape->num_outlines; n++, outline++) {
89035c4bbdfSmrg                    if (n == 0)
89135c4bbdfSmrg                        fprintf(file, "\n");
89235c4bbdfSmrg                    else
89335c4bbdfSmrg                        fprintf(file, ",\n");
89435c4bbdfSmrg                    WriteXKBOutline(file, shape, outline, lastR, 8, 8);
89535c4bbdfSmrg                    lastR = outline->corner_radius;
89635c4bbdfSmrg                }
89735c4bbdfSmrg                fprintf(file, "\n    };\n");
89835c4bbdfSmrg            }
89935c4bbdfSmrg            else {
90035c4bbdfSmrg                WriteXKBOutline(file, NULL, outline, lastR, 1, 8);
90135c4bbdfSmrg                fprintf(file, " };\n");
90235c4bbdfSmrg            }
90335c4bbdfSmrg        }
90435c4bbdfSmrg    }
90535c4bbdfSmrg    if (geom->num_sections > 0) {
90635c4bbdfSmrg        XkbSectionPtr section;
90735c4bbdfSmrg
90835c4bbdfSmrg        for (section = geom->sections, i = 0; i < geom->num_sections;
90935c4bbdfSmrg             i++, section++) {
91035c4bbdfSmrg            WriteXKBSection(file, section, geom);
91135c4bbdfSmrg        }
91235c4bbdfSmrg    }
91335c4bbdfSmrg    if (geom->num_doodads > 0) {
91435c4bbdfSmrg        XkbDoodadPtr doodad;
91535c4bbdfSmrg
91635c4bbdfSmrg        for (i = 0, doodad = geom->doodads; i < geom->num_doodads;
91735c4bbdfSmrg             i++, doodad++) {
91835c4bbdfSmrg            WriteXKBDoodad(file, 4, geom, doodad);
91935c4bbdfSmrg        }
92005b261ecSmrg    }
92105b261ecSmrg    if (addOn)
92235c4bbdfSmrg        (*addOn) (file, xkb, topLevel, showImplicit, XkmGeometryIndex, priv);
92335c4bbdfSmrg    fprintf(file, "};\n\n");
9246747b715Smrg    return TRUE;
92505b261ecSmrg}
926