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_CONFIG_H
288c9fbc29Smrg#include <config.h>
298c9fbc29Smrg#endif
308c9fbc29Smrg#include <stdio.h>
318c9fbc29Smrg#include <ctype.h>
328c9fbc29Smrg#include <stdlib.h>
338c9fbc29Smrg#include <X11/Xos.h>
348c9fbc29Smrg#include <X11/Xlib.h>
358c9fbc29Smrg#include <X11/XKBlib.h>
368c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
378c9fbc29Smrg
388c9fbc29Smrg#include "XKMformat.h"
398c9fbc29Smrg#include "XKBfileInt.h"
408c9fbc29Smrg
4187c518e6Smrg#define lowbit(x)       ((x) & (-(x)))
428c9fbc29Smrg
438c9fbc29Smrgstatic Bool
4487c518e6SmrgWriteCHdrVMods(FILE *file, Display *dpy, XkbDescPtr xkb)
458c9fbc29Smrg{
4687c518e6Smrg    register int i, nOut;
4787c518e6Smrg
4887c518e6Smrg    if ((!xkb) || (!xkb->names))
4987c518e6Smrg        return False;
5087c518e6Smrg    for (i = nOut = 0; i < XkbNumVirtualMods; i++) {
5187c518e6Smrg        if (xkb->names->vmods[i] != None) {
5287c518e6Smrg            fprintf(file, "%s#define	vmod_%s	%d\n",
5387c518e6Smrg                    (nOut < 1 ? "\n" : ""),
5487c518e6Smrg                    XkbAtomText(dpy, xkb->names->vmods[i], XkbCFile), i);
5587c518e6Smrg            nOut++;
5687c518e6Smrg        }
578c9fbc29Smrg    }
5887c518e6Smrg    for (i = nOut = 0; i < XkbNumVirtualMods; i++) {
5987c518e6Smrg        if (xkb->names->vmods[i] != None) {
6087c518e6Smrg            fprintf(file, "%s#define	vmod_%sMask	(1<<%d)\n",
6187c518e6Smrg                    (nOut < 1 ? "\n" : ""),
6287c518e6Smrg                    XkbAtomText(dpy, xkb->names->vmods[i], XkbCFile), i);
6387c518e6Smrg            nOut++;
6487c518e6Smrg        }
658c9fbc29Smrg    }
6687c518e6Smrg    if (nOut > 0)
6787c518e6Smrg        fprintf(file, "\n");
688c9fbc29Smrg    return True;
698c9fbc29Smrg}
708c9fbc29Smrg
718c9fbc29Smrgstatic Bool
7287c518e6SmrgWriteCHdrKeycodes(FILE * file, XkbDescPtr xkb)
738c9fbc29Smrg{
7487c518e6Smrg    Atom                kcName;
7587c518e6Smrg    register unsigned   i;
7687c518e6Smrg    char                buf[8];
778c9fbc29Smrg
7887c518e6Smrg    if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) {
7987c518e6Smrg        _XkbLibError(_XkbErrMissingNames, "WriteCHdrKeycodes", 0);
8087c518e6Smrg        return False;
818c9fbc29Smrg    }
8287c518e6Smrg    kcName = xkb->names->keycodes;
8387c518e6Smrg    buf[4] = '\0';
8487c518e6Smrg    if (xkb->names->keycodes != None)
8587c518e6Smrg        fprintf(file, "/* keycodes name is \"%s\" */\n",
8687c518e6Smrg                XkbAtomText(xkb->dpy, kcName, XkbMessage));
8787c518e6Smrg    fprintf(file, "static XkbKeyNameRec	keyNames[NUM_KEYS]= {\n");
8887c518e6Smrg    for (i = 0; i <= xkb->max_key_code; i++) {
8987c518e6Smrg        snprintf(buf, sizeof(buf), "\"%s\"",
9087c518e6Smrg                 XkbKeyNameText(xkb->names->keys[i].name, XkbCFile));
9187c518e6Smrg        if (i != xkb->max_key_code) {
9287c518e6Smrg            fprintf(file, "    {  %6s  },", buf);
9387c518e6Smrg            if ((i & 3) == 3)
9487c518e6Smrg                fprintf(file, "\n");
9587c518e6Smrg        }
9687c518e6Smrg        else {
9787c518e6Smrg            fprintf(file, "    {  %6s  }\n", buf);
9887c518e6Smrg        }
998c9fbc29Smrg    }
10087c518e6Smrg    fprintf(file, "};\n");
1018c9fbc29Smrg    return True;
1028c9fbc29Smrg}
1038c9fbc29Smrg
1048c9fbc29Smrgstatic void
10587c518e6SmrgWriteTypePreserve(FILE *        file,
10687c518e6Smrg                  Display *     dpy,
10787c518e6Smrg                  char *        prefix,
10887c518e6Smrg                  XkbDescPtr    xkb,
10987c518e6Smrg                  XkbKeyTypePtr type)
1108c9fbc29Smrg{
11187c518e6Smrg    register unsigned i;
11287c518e6Smrg    XkbModsPtr pre;
11387c518e6Smrg
11487c518e6Smrg    fprintf(file, "static XkbModsRec preserve_%s[%d]= {\n", prefix,
11587c518e6Smrg            type->map_count);
11687c518e6Smrg    for (i = 0, pre = type->preserve; i < type->map_count; i++, pre++) {
11787c518e6Smrg        if (i != 0)
11887c518e6Smrg            fprintf(file, ",\n");
11987c518e6Smrg        fprintf(file, "    {   %15s, ", XkbModMaskText(pre->mask, XkbCFile));
12087c518e6Smrg        fprintf(file, "%15s, ", XkbModMaskText(pre->real_mods, XkbCFile));
12187c518e6Smrg        fprintf(file, "%15s }",
12287c518e6Smrg                XkbVModMaskText(dpy, xkb, 0, pre->vmods, XkbCFile));
1238c9fbc29Smrg    }
12487c518e6Smrg    fprintf(file, "\n};\n");
1258c9fbc29Smrg    return;
1268c9fbc29Smrg}
1278c9fbc29Smrg
1288c9fbc29Smrgstatic void
12987c518e6SmrgWriteTypeInitFunc(FILE *file, Display *dpy, XkbDescPtr xkb)
1308c9fbc29Smrg{
13187c518e6Smrg    register unsigned   i, n;
13287c518e6Smrg    XkbKeyTypePtr       type;
13387c518e6Smrg    Atom *              names;
13487c518e6Smrg    char *              prefix = NULL;
13587c518e6Smrg
13687c518e6Smrg    fprintf(file, "\n\nstatic void\n");
13787c518e6Smrg    fprintf(file, "initTypeNames(DPYTYPE dpy)\n");
13887c518e6Smrg    fprintf(file, "{\n");
13987c518e6Smrg    for (i = 0, type = xkb->map->types; i < xkb->map->num_types; i++, type++) {
14087c518e6Smrg        if (!(prefix = strdup(XkbAtomText(dpy, type->name, XkbCFile)))) {
14187c518e6Smrg            _XkbLibError(_XkbErrBadAlloc, "WriteTypeInitFunc", 0);
14287c518e6Smrg            fprintf(file, "#error XkbErrBadAlloc WriteTypeInitFunc\n");
14387c518e6Smrg            break;
14487c518e6Smrg        }
14587c518e6Smrg        if (type->name != None)
14687c518e6Smrg            fprintf(file, "    dflt_types[%d].name= GET_ATOM(dpy,\"%s\");\n",
14787c518e6Smrg                    i, XkbAtomText(dpy, type->name, XkbCFile));
14887c518e6Smrg        names = type->level_names;
14987c518e6Smrg        if (names != NULL) {
15087c518e6Smrg            char *tmp;
15187c518e6Smrg
15287c518e6Smrg            for (n = 0; n < type->num_levels; n++) {
15387c518e6Smrg                if (names[n] == None)
15487c518e6Smrg                    continue;
15587c518e6Smrg                tmp = XkbAtomText(dpy, names[n], XkbCFile);
15687c518e6Smrg                if (tmp == NULL)
15787c518e6Smrg                    continue;
15887c518e6Smrg                fprintf(file, "    lnames_%s[%d]=	", prefix, n);
15987c518e6Smrg                fprintf(file, "GET_ATOM(dpy,\"%s\");\n", tmp);
16087c518e6Smrg            }
16187c518e6Smrg        }
16287c518e6Smrg        free(prefix);
16387c518e6Smrg        prefix = NULL;
1648c9fbc29Smrg    }
16587c518e6Smrg    fprintf(file, "}\n");
1668c9fbc29Smrg    return;
1678c9fbc29Smrg}
1688c9fbc29Smrg
1698c9fbc29Smrgstatic Bool
17087c518e6SmrgWriteCHdrKeyTypes(FILE *file, Display *dpy, XkbDescPtr xkb)
1718c9fbc29Smrg{
17287c518e6Smrg    register unsigned   i, n;
17387c518e6Smrg    XkbClientMapPtr     map;
17487c518e6Smrg    XkbKeyTypePtr       type;
17587c518e6Smrg    char *              prefix = NULL;
17687c518e6Smrg
17787c518e6Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->types)) {
17887c518e6Smrg        _XkbLibError(_XkbErrMissingTypes, "WriteCHdrKeyTypes", 0);
17987c518e6Smrg        return False;
1808c9fbc29Smrg    }
18187c518e6Smrg    if (xkb->map->num_types < XkbNumRequiredTypes) {
18287c518e6Smrg        _XkbLibError(_XkbErrMissingReqTypes, "WriteCHdrKeyTypes", 0);
18387c518e6Smrg        return 0;
1848c9fbc29Smrg    }
18587c518e6Smrg    map = xkb->map;
18687c518e6Smrg    if ((xkb->names != NULL) && (xkb->names->types != None)) {
18787c518e6Smrg        fprintf(file, "/* types name is \"%s\" */\n",
18887c518e6Smrg                XkbAtomText(dpy, xkb->names->types, XkbCFile));
1898c9fbc29Smrg    }
19087c518e6Smrg    for (i = 0, type = map->types; i < map->num_types; i++, type++) {
19187c518e6Smrg        if (!(prefix = strdup(XkbAtomText(dpy, type->name, XkbCFile)))) {
19287c518e6Smrg            _XkbLibError(_XkbErrBadAlloc, "WriteCHdrKeyTypes", 0);
19387c518e6Smrg            return False;
19487c518e6Smrg        }
19587c518e6Smrg
19687c518e6Smrg        if (type->map_count > 0) {
19787c518e6Smrg            XkbKTMapEntryPtr entry;
19887c518e6Smrg
19987c518e6Smrg            entry = type->map;
20087c518e6Smrg            fprintf(file, "static XkbKTMapEntryRec map_%s[%d]= {\n", prefix,
20187c518e6Smrg                    type->map_count);
20287c518e6Smrg            for (n = 0; n < (unsigned) type->map_count; n++, entry++) {
20387c518e6Smrg                if (n != 0)
20487c518e6Smrg                    fprintf(file, ",\n");
20587c518e6Smrg                fprintf(file, "    { %d, %6d, { %15s, %15s, %15s } }",
20687c518e6Smrg                        entry->active,
20787c518e6Smrg                        entry->level,
20887c518e6Smrg                        XkbModMaskText(entry->mods.mask, XkbCFile),
20987c518e6Smrg                        XkbModMaskText(entry->mods.real_mods, XkbCFile),
21087c518e6Smrg                        XkbVModMaskText(dpy, xkb, 0, entry->mods.vmods,
21187c518e6Smrg                                        XkbCFile));
21287c518e6Smrg            }
21387c518e6Smrg            fprintf(file, "\n};\n");
21487c518e6Smrg
21587c518e6Smrg            if (type->preserve)
21687c518e6Smrg                WriteTypePreserve(file, dpy, prefix, xkb, type);
21787c518e6Smrg        }
21887c518e6Smrg        if (type->level_names != NULL) {
21987c518e6Smrg            fprintf(file, "static Atom lnames_%s[%d];\n", prefix,
22087c518e6Smrg                    type->num_levels);
22187c518e6Smrg        }
22287c518e6Smrg        fprintf(file, "\n");
22387c518e6Smrg        free(prefix);
22487c518e6Smrg        prefix = NULL;
2258c9fbc29Smrg    }
22687c518e6Smrg    fprintf(file, "static XkbKeyTypeRec dflt_types[]= {\n");
22787c518e6Smrg    for (i = 0, type = map->types; i < (unsigned) map->num_types; i++, type++) {
22887c518e6Smrg        if (!(prefix = strdup(XkbAtomText(dpy, type->name, XkbCFile)))) {
22987c518e6Smrg            _XkbLibError(_XkbErrBadAlloc, "WriteCHdrKeyTypes", 0);
23087c518e6Smrg            return False;
23187c518e6Smrg        }
23287c518e6Smrg        if (i != 0)
23387c518e6Smrg            fprintf(file, ",\n");
23487c518e6Smrg        fprintf(file, "    {\n	{ %15s, %15s, %15s },\n",
23587c518e6Smrg                XkbModMaskText(type->mods.mask, XkbCFile),
23687c518e6Smrg                XkbModMaskText(type->mods.real_mods, XkbCFile),
23787c518e6Smrg                XkbVModMaskText(dpy, xkb, 0, type->mods.vmods, XkbCFile));
23887c518e6Smrg        fprintf(file, "	%d,\n", type->num_levels);
23987c518e6Smrg        fprintf(file, "	%d,", type->map_count);
24087c518e6Smrg        if (type->map_count > 0)
24187c518e6Smrg            fprintf(file, "	map_%s,", prefix);
24287c518e6Smrg        else
24387c518e6Smrg            fprintf(file, "	NULL,");
24487c518e6Smrg        if (type->preserve)
24587c518e6Smrg            fprintf(file, "	preserve_%s,\n", prefix);
24687c518e6Smrg        else
24787c518e6Smrg            fprintf(file, "	NULL,\n");
24887c518e6Smrg        if (type->level_names != NULL)
24987c518e6Smrg            fprintf(file, "	None,	lnames_%s\n    }", prefix);
25087c518e6Smrg        else
25187c518e6Smrg            fprintf(file, "	None,	NULL\n    }");
25287c518e6Smrg        free(prefix);
25387c518e6Smrg        prefix = NULL;
2548c9fbc29Smrg    }
25587c518e6Smrg    fprintf(file, "\n};\n");
25687c518e6Smrg    fprintf(file,
25787c518e6Smrg            "#define num_dflt_types (sizeof(dflt_types)/sizeof(XkbKeyTypeRec))\n");
25887c518e6Smrg    WriteTypeInitFunc(file, dpy, xkb);
2598c9fbc29Smrg    return True;
2608c9fbc29Smrg}
2618c9fbc29Smrg
2628c9fbc29Smrgstatic Bool
26387c518e6SmrgWriteCHdrCompatMap(FILE *file, Display *dpy, XkbDescPtr xkb)
2648c9fbc29Smrg{
26587c518e6Smrg    register unsigned   i;
26687c518e6Smrg    XkbCompatMapPtr     compat;
26787c518e6Smrg    XkbSymInterpretPtr  interp;
2688c9fbc29Smrg
26987c518e6Smrg    if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) {
27087c518e6Smrg        _XkbLibError(_XkbErrMissingSymInterps, "WriteCHdrInterp", 0);
27187c518e6Smrg        return False;
2728c9fbc29Smrg    }
27387c518e6Smrg    compat = xkb->compat;
27487c518e6Smrg    if ((xkb->names != NULL) && (xkb->names->compat != None)) {
27587c518e6Smrg        fprintf(file, "/* compat name is \"%s\" */\n",
27687c518e6Smrg                XkbAtomText(dpy, xkb->names->compat, XkbCFile));
2778c9fbc29Smrg    }
27887c518e6Smrg    fprintf(file, "static XkbSymInterpretRec dfltSI[%d]= {\n", compat->num_si);
27987c518e6Smrg    interp = compat->sym_interpret;
28087c518e6Smrg    for (i = 0; i < compat->num_si; i++, interp++) {
28187c518e6Smrg        XkbAction *act;
28287c518e6Smrg
28387c518e6Smrg        act = (XkbAction *) &interp->act;
28487c518e6Smrg        if (i != 0)
28587c518e6Smrg            fprintf(file, ",\n");
28687c518e6Smrg        fprintf(file, "    {    %s, ", XkbKeysymText(interp->sym, XkbCFile));
28787c518e6Smrg        fprintf(file, "0x%04x,\n", interp->flags);
28887c518e6Smrg        fprintf(file, "         %s, ", XkbSIMatchText(interp->match, XkbCFile));
28987c518e6Smrg        fprintf(file, "%s,\n", XkbModMaskText(interp->mods, XkbCFile));
29087c518e6Smrg        fprintf(file, "         %d,\n", interp->virtual_mod);
29187c518e6Smrg        fprintf(file, "       %s }", XkbActionText(dpy, xkb, act, XkbCFile));
2928c9fbc29Smrg    }
29387c518e6Smrg    fprintf(file, "\n};\n");
2948c9fbc29Smrg    fprintf(file,
29587c518e6Smrg            "#define num_dfltSI (sizeof(dfltSI)/sizeof(XkbSymInterpretRec))\n");
29687c518e6Smrg    fprintf(file, "\nstatic XkbCompatMapRec compatMap= {\n");
29787c518e6Smrg    fprintf(file, "    dfltSI,\n");
29887c518e6Smrg    fprintf(file, "    {   /* group compatibility */\n        ");
29987c518e6Smrg    for (i = 0; i < XkbNumKbdGroups; i++) {
30087c518e6Smrg        XkbModsPtr gc;
30187c518e6Smrg
30287c518e6Smrg        gc = &xkb->compat->groups[i];
30387c518e6Smrg        fprintf(file, "%s{ %12s, %12s, %12s }",
30487c518e6Smrg                ((i == 0) ? "" : ",\n        "),
30587c518e6Smrg                XkbModMaskText(gc->mask, XkbCFile),
30687c518e6Smrg                XkbModMaskText(gc->real_mods, XkbCFile),
30787c518e6Smrg                XkbVModMaskText(xkb->dpy, xkb, 0, gc->vmods, XkbCFile));
3088c9fbc29Smrg    }
30987c518e6Smrg    fprintf(file, "\n    },\n");
31087c518e6Smrg    fprintf(file, "    num_dfltSI, num_dfltSI\n");
31187c518e6Smrg    fprintf(file, "};\n\n");
3128c9fbc29Smrg    return True;
3138c9fbc29Smrg}
3148c9fbc29Smrg
3158c9fbc29Smrgstatic Bool
31687c518e6SmrgWriteCHdrSymbols(FILE *file, XkbDescPtr xkb)
3178c9fbc29Smrg{
31887c518e6Smrg    register unsigned i;
3198c9fbc29Smrg
32087c518e6Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->syms) || (!xkb->map->key_sym_map)) {
32187c518e6Smrg        _XkbLibError(_XkbErrMissingSymbols, "WriteCHdrSymbols", 0);
32287c518e6Smrg        return False;
3238c9fbc29Smrg    }
32487c518e6Smrg    fprintf(file, "#define NUM_SYMBOLS	%d\n", xkb->map->num_syms);
32587c518e6Smrg    if (xkb->map->num_syms > 0) {
32687c518e6Smrg        register KeySym *sym;
32787c518e6Smrg
32887c518e6Smrg        sym = xkb->map->syms;
32987c518e6Smrg        fprintf(file, "static KeySym	symCache[NUM_SYMBOLS]= {\n");
33087c518e6Smrg        for (i = 0; i < xkb->map->num_syms; i++, sym++) {
33187c518e6Smrg            if (i == 0)
33287c518e6Smrg                fprintf(file, "    ");
33387c518e6Smrg            else if (i % 4 == 0)
33487c518e6Smrg                fprintf(file, ",\n    ");
33587c518e6Smrg            else
33687c518e6Smrg                fprintf(file, ", ");
33787c518e6Smrg            fprintf(file, "%15s", XkbKeysymText(*sym, XkbCFile));
33887c518e6Smrg        }
33987c518e6Smrg        fprintf(file, "\n};\n");
3408c9fbc29Smrg    }
34187c518e6Smrg    if (xkb->max_key_code > 0) {
34287c518e6Smrg        register XkbSymMapPtr map;
34387c518e6Smrg
34487c518e6Smrg        map = xkb->map->key_sym_map;
34587c518e6Smrg        fprintf(file, "static XkbSymMapRec	symMap[NUM_KEYS]= {\n");
34687c518e6Smrg        for (i = 0; i <= xkb->max_key_code; i++, map++) {
34787c518e6Smrg            if (i == 0)
34887c518e6Smrg                fprintf(file, "    ");
34987c518e6Smrg            else if ((i & 3) == 0)
35087c518e6Smrg                fprintf(file, ",\n    ");
35187c518e6Smrg            else
35287c518e6Smrg                fprintf(file, ", ");
35387c518e6Smrg            fprintf(file, "{ %2d, 0x%x, %3d }",
35487c518e6Smrg                    map->kt_index[0], map->group_info, map->offset);
35587c518e6Smrg        }
35687c518e6Smrg        fprintf(file, "\n};\n");
3578c9fbc29Smrg    }
3588c9fbc29Smrg    return True;
3598c9fbc29Smrg}
3608c9fbc29Smrg
3618c9fbc29Smrgstatic Bool
36287c518e6SmrgWriteCHdrClientMap(FILE *file, Display *dpy, XkbDescPtr xkb)
3638c9fbc29Smrg{
36487c518e6Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->syms) || (!xkb->map->key_sym_map)) {
36587c518e6Smrg        _XkbLibError(_XkbErrMissingSymbols, "WriteCHdrClientMap", 0);
36687c518e6Smrg        return False;
3678c9fbc29Smrg    }
36887c518e6Smrg    if (!WriteCHdrKeyTypes(file, dpy, xkb))
36987c518e6Smrg        return False;
37087c518e6Smrg    if (!WriteCHdrSymbols(file, xkb))
37187c518e6Smrg        return False;
37287c518e6Smrg    fprintf(file, "static XkbClientMapRec clientMap= {\n");
37387c518e6Smrg    fprintf(file, "    NUM_TYPES,   NUM_TYPES,   types, \n");
37487c518e6Smrg    fprintf(file, "    NUM_SYMBOLS, NUM_SYMBOLS, symCache, symMap\n");
37587c518e6Smrg    fprintf(file, "};\n\n");
3768c9fbc29Smrg    return True;
3778c9fbc29Smrg}
3788c9fbc29Smrg
3798c9fbc29Smrgstatic Bool
38087c518e6SmrgWriteCHdrServerMap(FILE *file, Display *dpy, XkbDescPtr xkb)
3818c9fbc29Smrg{
38287c518e6Smrg    register unsigned i;
3838c9fbc29Smrg
38487c518e6Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->syms) || (!xkb->map->key_sym_map)) {
38587c518e6Smrg        _XkbLibError(_XkbErrMissingSymbols, "WriteCHdrServerMap", 0);
38687c518e6Smrg        return False;
3878c9fbc29Smrg    }
38887c518e6Smrg    if (xkb->server->num_acts > 0) {
38987c518e6Smrg        register XkbAnyAction *act;
39087c518e6Smrg
39187c518e6Smrg        act = (XkbAnyAction *) xkb->server->acts;
39287c518e6Smrg        fprintf(file, "#define NUM_ACTIONS	%d\n", xkb->server->num_acts);
39387c518e6Smrg        fprintf(file, "static XkbAnyAction 	actionCache[NUM_ACTIONS]= {\n");
39487c518e6Smrg        for (i = 0; i < xkb->server->num_acts; i++, act++) {
39587c518e6Smrg            if (i == 0)
39687c518e6Smrg                fprintf(file, "    ");
39787c518e6Smrg            else
39887c518e6Smrg                fprintf(file, ",\n    ");
39987c518e6Smrg            fprintf(file, "%s",
40087c518e6Smrg                    XkbActionText(dpy, xkb, (XkbAction *) act, XkbCFile));
40187c518e6Smrg        }
40287c518e6Smrg        fprintf(file, "\n};\n");
4038c9fbc29Smrg    }
40487c518e6Smrg    fprintf(file, "static unsigned short	keyActions[NUM_KEYS]= {\n");
40587c518e6Smrg    for (i = 0; i <= xkb->max_key_code; i++) {
40687c518e6Smrg        if (i == 0)
40787c518e6Smrg            fprintf(file, "    ");
40887c518e6Smrg        else if ((i & 0xf) == 0)
40987c518e6Smrg            fprintf(file, ",\n    ");
41087c518e6Smrg        else
41187c518e6Smrg            fprintf(file, ", ");
41287c518e6Smrg        fprintf(file, "%2d", xkb->server->key_acts[i]);
4138c9fbc29Smrg    }
41487c518e6Smrg    fprintf(file, "\n};\n");
41587c518e6Smrg    fprintf(file, "static XkbBehavior behaviors[NUM_KEYS]= {\n");
41687c518e6Smrg    for (i = 0; i <= xkb->max_key_code; i++) {
41787c518e6Smrg        if (i == 0)
41887c518e6Smrg            fprintf(file, "    ");
41987c518e6Smrg        else if ((i & 0x3) == 0)
42087c518e6Smrg            fprintf(file, ",\n    ");
42187c518e6Smrg        else
42287c518e6Smrg            fprintf(file, ", ");
42387c518e6Smrg        if (xkb->server->behaviors) {
42487c518e6Smrg            fprintf(file, "%s",
42587c518e6Smrg                    XkbBehaviorText(xkb, &xkb->server->behaviors[i], XkbCFile));
42687c518e6Smrg        }
42787c518e6Smrg        else
42887c518e6Smrg            fprintf(file, "{    0,    0 }");
4298c9fbc29Smrg    }
43087c518e6Smrg    fprintf(file, "\n};\n");
43187c518e6Smrg    fprintf(file, "static unsigned char explicit_parts[NUM_KEYS]= {\n");
43287c518e6Smrg    for (i = 0; i <= xkb->max_key_code; i++) {
43387c518e6Smrg        if (i == 0)
43487c518e6Smrg            fprintf(file, "    ");
43587c518e6Smrg        else if ((i & 0x7) == 0)
43687c518e6Smrg            fprintf(file, ",\n    ");
43787c518e6Smrg        else
43887c518e6Smrg            fprintf(file, ", ");
43987c518e6Smrg        if ((xkb->server->explicit == NULL) || (xkb->server->explicit[i] == 0))
44087c518e6Smrg            fprintf(file, "   0");
44187c518e6Smrg        else
44287c518e6Smrg            fprintf(file, "0x%02x", xkb->server->explicit[i]);
4438c9fbc29Smrg    }
44487c518e6Smrg    fprintf(file, "\n};\n");
44587c518e6Smrg    fprintf(file, "static unsigned short vmodmap[NUM_KEYS]= {\n");
44687c518e6Smrg    for (i = 0; i < xkb->max_key_code; i++) {
44787c518e6Smrg        if (i == 0)
44887c518e6Smrg            fprintf(file, "    ");
44987c518e6Smrg        else if ((i & 0x7) == 0)
45087c518e6Smrg            fprintf(file, ",\n    ");
45187c518e6Smrg        else
45287c518e6Smrg            fprintf(file, ", ");
45387c518e6Smrg        if ((xkb->server->vmodmap == NULL) || (xkb->server->vmodmap[i] == 0))
45487c518e6Smrg            fprintf(file, "     0");
45587c518e6Smrg        else
45687c518e6Smrg            fprintf(file, "0x%04x", xkb->server->vmodmap[i]);
4578c9fbc29Smrg    }
45887c518e6Smrg    fprintf(file, "};\n");
45987c518e6Smrg    fprintf(file, "static XkbServerMapRec serverMap= {\n");
46087c518e6Smrg    fprintf(file, "    %d, %d, (XkbAction *)actionCache,\n",
46187c518e6Smrg            xkb->server->num_acts, xkb->server->num_acts);
46287c518e6Smrg    fprintf(file, "    behaviors, keyActions, explicit_parts,\n");
46387c518e6Smrg    for (i = 0; i < XkbNumVirtualMods; i++) {
46487c518e6Smrg        if (i == 0)
46587c518e6Smrg            fprintf(file, "    { ");
46687c518e6Smrg        else if (i == 8)
46787c518e6Smrg            fprintf(file, ",\n      ");
46887c518e6Smrg        else
46987c518e6Smrg            fprintf(file, ", ");
47087c518e6Smrg        fprintf(file, "%3d", xkb->server->vmods[i]);
4718c9fbc29Smrg    }
47287c518e6Smrg    fprintf(file, " },\n");
47387c518e6Smrg    fprintf(file, "    vmodmap\n");
47487c518e6Smrg    fprintf(file, "};\n\n");
4758c9fbc29Smrg    return True;
4768c9fbc29Smrg}
4778c9fbc29Smrg
4788c9fbc29Smrgstatic Bool
47987c518e6SmrgWriteCHdrIndicators(FILE *file, Display *dpy, XkbDescPtr xkb)
4808c9fbc29Smrg{
48187c518e6Smrg    register int i, nNames;
48287c518e6Smrg    XkbIndicatorMapPtr imap;
4838c9fbc29Smrg
48487c518e6Smrg    if (xkb->indicators == NULL)
48587c518e6Smrg        return True;
4868c9fbc29Smrg    fprintf(file, "static XkbIndicatorRec indicators= {\n");
4878c9fbc29Smrg    fprintf(file, "    0x%lx,\n    {\n",
48887c518e6Smrg            (long) xkb->indicators->phys_indicators);
48987c518e6Smrg    for (imap = xkb->indicators->maps, i = nNames = 0; i < XkbNumIndicators;
49087c518e6Smrg         i++, imap++) {
49187c518e6Smrg        fprintf(file, "%s        { 0x%02x, %s, 0x%02x, %s, { %s, ",
49287c518e6Smrg                (i != 0 ? ",\n" : ""), imap->flags,
49387c518e6Smrg                XkbIMWhichStateMaskText(imap->which_groups, XkbCFile),
49487c518e6Smrg                imap->groups, XkbIMWhichStateMaskText(imap->which_mods,
49587c518e6Smrg                                                      XkbCFile),
49687c518e6Smrg                XkbModMaskText(imap->mods.mask, XkbCFile));
49787c518e6Smrg        fprintf(file, " %s, %s }, %s }",
49887c518e6Smrg                XkbModMaskText(imap->mods.real_mods, XkbCFile),
49987c518e6Smrg                XkbVModMaskText(dpy, xkb, 0, imap->mods.vmods, XkbCFile),
50087c518e6Smrg                XkbControlsMaskText(imap->ctrls, XkbCFile));
50187c518e6Smrg        if (xkb->names && (xkb->names->indicators[i] != None))
50287c518e6Smrg            nNames++;
5038c9fbc29Smrg    }
50487c518e6Smrg    fprintf(file, "\n    }\n};\n");
50587c518e6Smrg    if (nNames > 0) {
50687c518e6Smrg        fprintf(file, "static void\n");
50787c518e6Smrg        fprintf(file, "initIndicatorNames(DPYTYPE dpy,XkbDescPtr xkb)\n");
50887c518e6Smrg        fprintf(file, "{\n");
50987c518e6Smrg        for (i = 0; i < XkbNumIndicators; i++) {
51087c518e6Smrg            Atom name;
51187c518e6Smrg
51287c518e6Smrg            if (xkb->names->indicators[i] == None)
51387c518e6Smrg                continue;
51487c518e6Smrg            name = xkb->names->indicators[i];
51587c518e6Smrg            fprintf(file, "    xkb->names->indicators[%2d]=	", i);
51687c518e6Smrg            fprintf(file, "GET_ATOM(dpy,\"%s\");\n",
51787c518e6Smrg                    XkbAtomText(dpy, name, XkbCFile));
51887c518e6Smrg        }
51987c518e6Smrg        fprintf(file, "}\n");
5208c9fbc29Smrg    }
5218c9fbc29Smrg    return True;
5228c9fbc29Smrg}
5238c9fbc29Smrg
5248c9fbc29Smrgstatic Bool
52587c518e6SmrgWriteCHdrGeomProps(FILE *file, XkbDescPtr xkb, XkbGeometryPtr geom)
5268c9fbc29Smrg{
52787c518e6Smrg    if (geom->num_properties > 0) {
52887c518e6Smrg        register int i;
52987c518e6Smrg
53087c518e6Smrg        fprintf(file, "\nstatic XkbPropertyRec g_props[%d]= {\n",
53187c518e6Smrg                geom->num_properties);
53287c518e6Smrg        for (i = 0; i < geom->num_properties; i++) {
53387c518e6Smrg            fprintf(file, "%s	{	\"%s\", \"%s\"	}",
53487c518e6Smrg                    (i == 0 ? "" : ",\n"),
53587c518e6Smrg                    XkbStringText(geom->properties[i].name, XkbCFile),
53687c518e6Smrg                    XkbStringText(geom->properties[i].value, XkbCFile));
53787c518e6Smrg        }
53887c518e6Smrg        fprintf(file, "\n};\n");
5398c9fbc29Smrg    }
5408c9fbc29Smrg    return True;
5418c9fbc29Smrg}
5428c9fbc29Smrg
5438c9fbc29Smrgstatic Bool
54487c518e6SmrgWriteCHdrGeomColors(FILE *file, XkbDescPtr xkb, XkbGeometryPtr geom)
5458c9fbc29Smrg{
54687c518e6Smrg    if (geom->num_colors > 0) {
54787c518e6Smrg        register int i;
54887c518e6Smrg
54987c518e6Smrg        fprintf(file, "\nstatic XkbColorRec g_colors[%d]= {\n",
55087c518e6Smrg                geom->num_colors);
55187c518e6Smrg        for (i = 0; i < geom->num_colors; i++) {
55287c518e6Smrg            fprintf(file, "%s	{	%3d, \"%s\"	}",
55387c518e6Smrg                    (i == 0 ? "" : ",\n"), geom->colors[i].pixel,
55487c518e6Smrg                    XkbStringText(geom->colors[i].spec, XkbCFile));
55587c518e6Smrg        }
55687c518e6Smrg        fprintf(file, "\n};\n");
5578c9fbc29Smrg    }
5588c9fbc29Smrg    return True;
5598c9fbc29Smrg}
5608c9fbc29Smrg
5618c9fbc29Smrgstatic Bool
56287c518e6SmrgWriteCHdrGeomOutlines(FILE *file, int nOL, XkbOutlinePtr ol, int shapeNdx)
5638c9fbc29Smrg{
56487c518e6Smrg    register int o, p;
56587c518e6Smrg
56687c518e6Smrg    for (o = 0; o < nOL; o++) {
56787c518e6Smrg        fprintf(file, "\nstatic XkbPointRec pts_sh%02do%02d[]= {\n", shapeNdx,
56887c518e6Smrg                o);
56987c518e6Smrg        for (p = 0; p < ol[o].num_points; p++) {
57087c518e6Smrg            if (p == 0)
57187c518e6Smrg                fprintf(file, "	");
57287c518e6Smrg            else if ((p & 0x3) == 0)
57387c518e6Smrg                fprintf(file, ",\n	");
57487c518e6Smrg            else
57587c518e6Smrg                fprintf(file, ", ");
57687c518e6Smrg            fprintf(file, "{ %4d, %4d }", ol[o].points[p].x, ol[o].points[p].y);
57787c518e6Smrg        }
57887c518e6Smrg        fprintf(file, "\n};");
5798c9fbc29Smrg    }
58087c518e6Smrg    fprintf(file, "\n\nstatic XkbOutlineRec ol_sh%02d[]= {\n", shapeNdx);
58187c518e6Smrg    for (o = 0; o < nOL; o++) {
58287c518e6Smrg        fprintf(file, "%s	{ %d,	%d,	%d,	pts_sh%02do%02d	}",
58387c518e6Smrg                (o == 0 ? "" : ",\n"),
58487c518e6Smrg                ol[o].num_points, ol[o].num_points,
58587c518e6Smrg                ol[o].corner_radius, shapeNdx, o);
5868c9fbc29Smrg    }
58787c518e6Smrg    fprintf(file, "\n};\n");
5888c9fbc29Smrg    return True;
5898c9fbc29Smrg}
5908c9fbc29Smrg
5918c9fbc29Smrgstatic Bool
59287c518e6SmrgWriteCHdrGeomShapes(FILE *file, XkbDescPtr xkb, XkbGeometryPtr geom)
5938c9fbc29Smrg{
59487c518e6Smrg    register int s;
59587c518e6Smrg    register XkbShapePtr shape;
5968c9fbc29Smrg
59787c518e6Smrg    for (s = 0, shape = geom->shapes; s < geom->num_shapes; s++, shape++) {
59887c518e6Smrg        WriteCHdrGeomOutlines(file, shape->num_outlines, shape->outlines, s);
5998c9fbc29Smrg    }
60087c518e6Smrg    fprintf(file, "\n\nstatic XkbShapeRec g_shapes[%d]= {\n", geom->num_shapes);
60187c518e6Smrg    for (s = 0, shape = geom->shapes; s < geom->num_shapes; s++, shape++) {
60287c518e6Smrg        fprintf(file, "%s	{ None, %3d, %3d, ol_sh%02d, ",
60387c518e6Smrg                (s == 0 ? "" : ",\n"), shape->num_outlines,
60487c518e6Smrg                shape->num_outlines, s);
60587c518e6Smrg        if (shape->approx) {
60687c518e6Smrg            fprintf(file, "&ol_sh%02d[%2d],	", s,
60787c518e6Smrg                    XkbOutlineIndex(shape, shape->approx));
60887c518e6Smrg        }
60987c518e6Smrg        else
61087c518e6Smrg            fprintf(file, "        NULL,	");
61187c518e6Smrg        if (shape->primary) {
61287c518e6Smrg            fprintf(file, "&ol_sh%02d[%2d],\n", s,
61387c518e6Smrg                    XkbOutlineIndex(shape, shape->primary));
61487c518e6Smrg        }
61587c518e6Smrg        else
61687c518e6Smrg            fprintf(file, "        NULL,\n");
61787c518e6Smrg        fprintf(file,
61887c518e6Smrg                "					{ %4d, %4d, %4d, %4d } }",
61987c518e6Smrg                shape->bounds.x1, shape->bounds.y1,
62087c518e6Smrg                shape->bounds.x2, shape->bounds.y2);
6218c9fbc29Smrg    }
62287c518e6Smrg    fprintf(file, "\n};\n");
6238c9fbc29Smrg    return True;
6248c9fbc29Smrg}
6258c9fbc29Smrg
6268c9fbc29Smrgstatic Bool
62787c518e6SmrgWriteCHdrGeomDoodads(FILE *             file,
62887c518e6Smrg                     XkbDescPtr         xkb,
62987c518e6Smrg                     XkbGeometryPtr     geom,
63087c518e6Smrg                     XkbSectionPtr      section,
63187c518e6Smrg                     int                section_num)
6328c9fbc29Smrg{
63387c518e6Smrg    int                 nd, d;
63487c518e6Smrg    XkbDoodadPtr        doodad;
63587c518e6Smrg    Display *           dpy;
63687c518e6Smrg
63787c518e6Smrg    dpy = xkb->dpy;
63887c518e6Smrg    if (section == NULL) {
63987c518e6Smrg        if (geom->num_doodads > 0) {
64087c518e6Smrg            fprintf(file, "static XkbDoodadRec g_doodads[%d];\n",
64187c518e6Smrg                    geom->num_doodads);
64287c518e6Smrg        }
64387c518e6Smrg        fprintf(file, "static void\n");
64487c518e6Smrg        fprintf(file, "_InitGeomDoodads(DPYTYPE dpy,XkbGeometryPtr geom)\n");
64587c518e6Smrg        fprintf(file, "{\n");
64687c518e6Smrg        fprintf(file, "register XkbDoodadPtr doodads;\n\n");
64787c518e6Smrg        fprintf(file, "    doodads= geom->doodads;\n");
64887c518e6Smrg        nd = geom->num_doodads;
64987c518e6Smrg        doodad = geom->doodads;
6508c9fbc29Smrg    }
6518c9fbc29Smrg    else {
65287c518e6Smrg        if (section->num_doodads > 0) {
65387c518e6Smrg            fprintf(file, "static XkbDoodadRec doodads_s%02d[%d];\n",
65487c518e6Smrg                    section_num, section->num_doodads);
65587c518e6Smrg        }
65687c518e6Smrg        fprintf(file, "static void\n");
65787c518e6Smrg        fprintf(file, "_InitS%02dDoodads(", section_num);
65887c518e6Smrg        fprintf(file, "    DPYTYPE		dpy,\n");
65987c518e6Smrg        fprintf(file, "    XkbGeometryPtr 	geom,\n");
66087c518e6Smrg        fprintf(file, "    XkbSectionPtr 	section)\n");
66187c518e6Smrg        fprintf(file, "{\n");
66287c518e6Smrg        fprintf(file, "register XkbDoodadPtr doodads;\n\n");
66387c518e6Smrg        fprintf(file, "    doodads= section->doodads;\n");
66487c518e6Smrg        nd = geom->num_doodads;
66587c518e6Smrg        doodad = geom->doodads;
6668c9fbc29Smrg    }
66787c518e6Smrg    for (d = 0; d < nd; d++, doodad++) {
66887c518e6Smrg        if (d != 0)
66987c518e6Smrg            fprintf(file, "\n");
67087c518e6Smrg        fprintf(file, "    doodads[%d].any.name= GET_ATOM(dpy,\"%s\");\n",
67187c518e6Smrg                d, XkbAtomText(dpy, doodad->any.name, XkbCFile));
67287c518e6Smrg        fprintf(file, "    doodads[%d].any.type= %s;\n",
67387c518e6Smrg                d, XkbDoodadTypeText(doodad->any.type, XkbCFile));
67487c518e6Smrg        fprintf(file, "    doodads[%d].any.priority= %d;\n",
67587c518e6Smrg                d, doodad->any.priority);
67687c518e6Smrg        fprintf(file, "    doodads[%d].any.top= %d;\n", d, doodad->any.top);
67787c518e6Smrg        fprintf(file, "    doodads[%d].any.left= %d;\n", d, doodad->any.left);
67887c518e6Smrg        fprintf(file, "    doodads[%d].any.angle= %d;\n", d, doodad->any.angle);
67987c518e6Smrg        switch (doodad->any.type) {
68087c518e6Smrg        case XkbOutlineDoodad:
68187c518e6Smrg        case XkbSolidDoodad:
68287c518e6Smrg            fprintf(file, "    doodads[%d].shape.color_ndx= %d;\n",
68387c518e6Smrg                    d, doodad->shape.color_ndx);
68487c518e6Smrg            fprintf(file, "    doodads[%d].shape.shape_ndx= %d;\n",
68587c518e6Smrg                    d, doodad->shape.shape_ndx);
68687c518e6Smrg            break;
68787c518e6Smrg        case XkbTextDoodad:
68887c518e6Smrg            fprintf(file, "    doodads[%d].text.width= %d;\n",
68987c518e6Smrg                    d, doodad->text.width);
69087c518e6Smrg            fprintf(file, "    doodads[%d].text.height= %d;\n",
69187c518e6Smrg                    d, doodad->text.height);
69287c518e6Smrg            fprintf(file, "    doodads[%d].text.color_ndx= %d;\n",
69387c518e6Smrg                    d, doodad->text.color_ndx);
69487c518e6Smrg            fprintf(file, "    doodads[%d].text.text= \"%s\";\n",
69587c518e6Smrg                    d, XkbStringText(doodad->text.text, XkbCFile));
69687c518e6Smrg            fprintf(file, "    doodads[%d].text.font= \"%s\";\n",
69787c518e6Smrg                    d, XkbStringText(doodad->text.font, XkbCFile));
69887c518e6Smrg            break;
69987c518e6Smrg        case XkbIndicatorDoodad:
70087c518e6Smrg            fprintf(file, "    doodads[%d].indicator.shape_ndx= %d;\n",
70187c518e6Smrg                    d, doodad->indicator.shape_ndx);
70287c518e6Smrg            fprintf(file, "    doodads[%d].indicator.on_color_ndx= %d;\n",
70387c518e6Smrg                    d, doodad->indicator.on_color_ndx);
70487c518e6Smrg            fprintf(file, "    doodads[%d].indicator.off_color_ndx= %d;\n",
70587c518e6Smrg                    d, doodad->indicator.off_color_ndx);
70687c518e6Smrg            break;
70787c518e6Smrg        case XkbLogoDoodad:
70887c518e6Smrg            fprintf(file, "    doodads[%d].logo.color_ndx= %d;\n",
70987c518e6Smrg                    d, doodad->logo.color_ndx);
71087c518e6Smrg            fprintf(file, "    doodads[%d].logo.shape_ndx= %d;\n",
71187c518e6Smrg                    d, doodad->logo.shape_ndx);
71287c518e6Smrg            fprintf(file, "    doodads[%d].logo.logo_name= \"%s\";\n",
71387c518e6Smrg                    d, XkbStringText(doodad->logo.logo_name, XkbCFile));
71487c518e6Smrg            break;
71587c518e6Smrg        }
7168c9fbc29Smrg    }
71787c518e6Smrg    fprintf(file, "}\n");
7188c9fbc29Smrg    return True;
7198c9fbc29Smrg}
7208c9fbc29Smrg
7218c9fbc29Smrgstatic Bool
72287c518e6SmrgWriteCHdrGeomOverlays(FILE *            file,
72387c518e6Smrg                      XkbDescPtr        xkb,
72487c518e6Smrg                      XkbSectionPtr     section,
72587c518e6Smrg                      int               section_num)
7268c9fbc29Smrg{
72787c518e6Smrg    register int        o, r, k;
72887c518e6Smrg    XkbOverlayPtr       ol;
72987c518e6Smrg    XkbOverlayRowPtr    row;
73087c518e6Smrg    XkbOverlayKeyPtr    key;
73187c518e6Smrg
73287c518e6Smrg    if (section->num_overlays < 1)
73387c518e6Smrg        return True;
73487c518e6Smrg    for (o = 0, ol = section->overlays; o < section->num_overlays; o++, ol++) {
73587c518e6Smrg        for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
73687c518e6Smrg            fprintf(file, "static XkbOverlayKeyRec olkeys_s%02dr%02d[%d]= {\n",
73787c518e6Smrg                    section_num, r, row->num_keys);
73887c518e6Smrg            for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
73987c518e6Smrg                fprintf(file, "%s	{ {\"%s\"},	{\"%s\"}	}",
74087c518e6Smrg                        (k == 0 ? "" : ",\n"),
74187c518e6Smrg                        XkbKeyNameText(key->over.name, XkbCFile),
74287c518e6Smrg                        XkbKeyNameText(key->under.name, XkbCFile));
74387c518e6Smrg            }
74487c518e6Smrg            fprintf(file, "\n};\n");
74587c518e6Smrg        }
74687c518e6Smrg        fprintf(file, "static XkbOverlayRowRec olrows_s%02d[%d]= {\n",
74787c518e6Smrg                section_num, section->num_rows);
74887c518e6Smrg        for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
74987c518e6Smrg            fprintf(file, "%s	{ %4d, %4d, %4d, olkeys_s%02dr%02d }",
75087c518e6Smrg                    (r == 0 ? "" : ",\n"),
75187c518e6Smrg                    row->row_under, row->num_keys, row->num_keys,
75287c518e6Smrg                    section_num, r);
75387c518e6Smrg        }
75487c518e6Smrg        fprintf(file, "\n};\n");
7558c9fbc29Smrg    }
75687c518e6Smrg    fprintf(file, "static XkbOverlayRec overlays_s%02d[%d]= {\n", section_num,
75787c518e6Smrg            section->num_overlays);
75887c518e6Smrg    for (o = 0, ol = section->overlays; o < section->num_overlays; o++, ol++) {
75987c518e6Smrg        fprintf(file, "%s	{\n", (o == 0 ? "" : ",\n"));
76087c518e6Smrg        fprintf(file, "	    None, 	/* name */\n");
76187c518e6Smrg        fprintf(file, "	    NULL,	/* section_under */\n");
76287c518e6Smrg        fprintf(file, "	    %4d,	/* num_rows */\n", ol->num_rows);
76387c518e6Smrg        fprintf(file, "	    %4d,	/* sz_rows */\n", ol->num_rows);
76487c518e6Smrg        fprintf(file, "	    olrows_s%02d,\n", section_num);
76587c518e6Smrg        fprintf(file, "	    NULL	/* bounds */\n");
76687c518e6Smrg        fprintf(file, "	}");
7678c9fbc29Smrg    }
76887c518e6Smrg    fprintf(file, "\n};\n");
76987c518e6Smrg    fprintf(file, "static void\n");
77087c518e6Smrg    fprintf(file, "_InitS%02dOverlay(", section_num);
77187c518e6Smrg    fprintf(file, "    DPYTYPE		dpy,\n");
77287c518e6Smrg    fprintf(file, "    XkbGeometryPtr 	geom,\n");
77387c518e6Smrg    fprintf(file, "    XkbSectionPtr 	section)\n");
77487c518e6Smrg    fprintf(file, "{\n");
77587c518e6Smrg    fprintf(file, "XkbOverlayPtr	ol;\n\n");
77687c518e6Smrg    fprintf(file, "    ol= section->overlays;\n");
77787c518e6Smrg    for (o = 0, ol = section->overlays; o < section->num_overlays; o++, ol++) {
77887c518e6Smrg        fprintf(file, "    ol[%2d].name= GET_ATOM(dpy,\"%s\");\n",
77987c518e6Smrg                o, XkbAtomText(xkb->dpy, ol->name, XkbCFile));
78087c518e6Smrg        fprintf(file, "    ol[%2d].section_under= section;\n", o);
7818c9fbc29Smrg    }
78287c518e6Smrg    fprintf(file, "}\n");
7838c9fbc29Smrg    return True;
7848c9fbc29Smrg}
7858c9fbc29Smrg
7868c9fbc29Smrgstatic Bool
78787c518e6SmrgWriteCHdrGeomRows(FILE *        file,
78887c518e6Smrg                  XkbDescPtr    xkb,
78987c518e6Smrg                  XkbSectionPtr section,
79087c518e6Smrg                  int           section_num)
7918c9fbc29Smrg{
79287c518e6Smrg    register int        k, r;
79387c518e6Smrg    register XkbRowPtr  row;
79487c518e6Smrg    register XkbKeyPtr  key;
79587c518e6Smrg
79687c518e6Smrg    for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
79787c518e6Smrg        fprintf(file, "static XkbKeyRec keys_s%02dr%02d[]= {\n",
79887c518e6Smrg                section_num, r);
79987c518e6Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
80087c518e6Smrg            fprintf(file, "%s	{ { \"%s\" },	%4d, %4d, %4d }",
80187c518e6Smrg                    (k == 0 ? "" : ",\n"),
80287c518e6Smrg                    XkbKeyNameText(key->name.name, XkbCFile),
80387c518e6Smrg                    key->gap, key->shape_ndx, key->color_ndx);
80487c518e6Smrg        }
80587c518e6Smrg        fprintf(file, "\n};\n");
8068c9fbc29Smrg    }
80787c518e6Smrg    fprintf(file, "static XkbRowRec rows_s%02d[]= {\n", section_num);
80887c518e6Smrg    for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
80987c518e6Smrg        fprintf(file, "%s	{ %4d, %4d, %2d, %2d, %1d, keys_s%02dr%02d, ",
81087c518e6Smrg                (r == 0 ? "" : ",\n"),
81187c518e6Smrg                row->top, row->left, row->num_keys, row->num_keys,
81287c518e6Smrg                (row->vertical != 0), section_num, r);
81387c518e6Smrg        fprintf(file, " { %4d, %4d, %4d, %4d } }",
81487c518e6Smrg                row->bounds.x1, row->bounds.y1, row->bounds.x2, row->bounds.y2);
8158c9fbc29Smrg    }
81687c518e6Smrg    fprintf(file, "\n};\n");
8178c9fbc29Smrg    return True;
8188c9fbc29Smrg}
8198c9fbc29Smrg
8208c9fbc29Smrgstatic Bool
82187c518e6SmrgWriteCHdrGeomSections(FILE *file, XkbDescPtr xkb, XkbGeometryPtr geom)
8228c9fbc29Smrg{
82387c518e6Smrg    register int s;
82487c518e6Smrg    register XkbSectionPtr section;
8258c9fbc29Smrg
82687c518e6Smrg    for (s = 0, section = geom->sections; s < geom->num_sections;
82787c518e6Smrg         s++, section++) {
82887c518e6Smrg        WriteCHdrGeomRows(file, xkb, section, s);
82987c518e6Smrg        if (section->num_overlays > 0)
83087c518e6Smrg            WriteCHdrGeomOverlays(file, xkb, section, s);
8318c9fbc29Smrg    }
83287c518e6Smrg    fprintf(file, "\nstatic XkbSectionRec g_sections[%d]= {\n",
83387c518e6Smrg            geom->num_sections);
83487c518e6Smrg    for (s = 0, section = geom->sections; s < geom->num_sections;
83587c518e6Smrg         s++, section++) {
83687c518e6Smrg        if (s != 0)
83787c518e6Smrg            fprintf(file, ",\n");
83887c518e6Smrg        fprintf(file, "	{\n	    None, /* name */\n");
83987c518e6Smrg        fprintf(file, "	    %4d, /* priority */\n", section->priority);
84087c518e6Smrg        fprintf(file, "	    %4d, /* top */\n", section->top);
84187c518e6Smrg        fprintf(file, "	    %4d, /* left */\n", section->left);
84287c518e6Smrg        fprintf(file, "	    %4d, /* width */\n", section->width);
84387c518e6Smrg        fprintf(file, "	    %4d, /* height */\n", section->height);
84487c518e6Smrg        fprintf(file, "	    %4d, /* angle */\n", section->angle);
84587c518e6Smrg        fprintf(file, "	    %4d, /* num_rows */\n", section->num_rows);
84687c518e6Smrg        fprintf(file, "	    %4d, /* num_doodads */\n", section->num_doodads);
84787c518e6Smrg        fprintf(file, "	    %4d, /* num_overlays */\n", section->num_overlays);
84887c518e6Smrg        fprintf(file, "	    %4d, /* sz_rows */\n", section->num_rows);
84987c518e6Smrg        fprintf(file, "	    %4d, /* sz_doodads */\n", section->num_doodads);
85087c518e6Smrg        fprintf(file, "	    %4d, /* sz_overlays */\n", section->num_overlays);
85187c518e6Smrg        if (section->num_rows > 0)
85287c518e6Smrg            fprintf(file, "	    rows_s%02d,\n", s);
85387c518e6Smrg        else
85487c518e6Smrg            fprintf(file, "	    NULL, /* rows */\n");
85587c518e6Smrg        if (section->num_doodads > 0)
85687c518e6Smrg            fprintf(file, "	    doodads_s%02d,\n", s);
85787c518e6Smrg        else
85887c518e6Smrg            fprintf(file, "	    NULL, /* doodads */\n");
85987c518e6Smrg        fprintf(file, "	    { %4d, %4d, %4d, %4d }, /* bounds */\n",
86087c518e6Smrg                section->bounds.x1, section->bounds.y1,
86187c518e6Smrg                section->bounds.x2, section->bounds.y2);
86287c518e6Smrg        if (section->num_overlays > 0)
86387c518e6Smrg            fprintf(file, "	    overlays_s%02d\n", s);
86487c518e6Smrg        else
86587c518e6Smrg            fprintf(file, "	    NULL /* overlays */\n");
86687c518e6Smrg        fprintf(file, "	}");
8678c9fbc29Smrg    }
86887c518e6Smrg    fprintf(file, "\n};\n");
86987c518e6Smrg    fprintf(file, "\nstatic Bool\n");
87087c518e6Smrg    fprintf(file, "_InitSections(DPYTYPE dpy,XkbGeometryPtr geom)\n");
87187c518e6Smrg    fprintf(file, "{\nXkbSectionPtr	sections;\n\n");
87287c518e6Smrg    fprintf(file, "    sections= geom->sections;\n");
87387c518e6Smrg    for (s = 0, section = geom->sections; s < geom->num_sections;
87487c518e6Smrg         s++, section++) {
87587c518e6Smrg        if (section->num_doodads > 0) {
87687c518e6Smrg            fprintf(file, "    _InitS%02dDoodads(dpy,geom,&sections[%d]);\n",
87787c518e6Smrg                    s, s);
87887c518e6Smrg        }
87987c518e6Smrg        if (section->num_overlays > 0) {
88087c518e6Smrg            fprintf(file, "    _InitS%02dOverlays(dpy,geom,&sections[%d]);\n",
88187c518e6Smrg                    s, s);
88287c518e6Smrg        }
8838c9fbc29Smrg    }
88487c518e6Smrg    fprintf(file, "}\n");
8858c9fbc29Smrg    return True;
8868c9fbc29Smrg}
8878c9fbc29Smrg
8888c9fbc29Smrgstatic Bool
88987c518e6SmrgWriteCHdrGeomAliases(FILE *file, XkbDescPtr xkb, XkbGeometryPtr geom)
8908c9fbc29Smrg{
89187c518e6Smrg    if (geom->num_key_aliases > 0) {
89287c518e6Smrg        register int i;
89387c518e6Smrg
89487c518e6Smrg        fprintf(file, "\nstatic XkbKeyAliasRec g_aliases[%d]= {\n",
89587c518e6Smrg                geom->num_key_aliases);
89687c518e6Smrg        for (i = 0; i < geom->num_key_aliases; i++) {
89787c518e6Smrg            fprintf(file, "%s	{	\"%s\", \"%s\"	}",
89887c518e6Smrg                    (i == 0 ? "" : ",\n"),
89987c518e6Smrg                    XkbKeyNameText(geom->key_aliases[i].real, XkbCFile),
90087c518e6Smrg                    XkbKeyNameText(geom->key_aliases[i].alias, XkbCFile));
90187c518e6Smrg        }
90287c518e6Smrg        fprintf(file, "\n};\n");
9038c9fbc29Smrg    }
9048c9fbc29Smrg    return True;
9058c9fbc29Smrg}
9068c9fbc29Smrg
9078c9fbc29Smrgstatic Bool
90887c518e6SmrgWriteCHdrGeometry(FILE *file, XkbDescPtr xkb)
9098c9fbc29Smrg{
91087c518e6Smrg    XkbGeometryPtr geom;
91187c518e6Smrg    register int i;
9128c9fbc29Smrg
91387c518e6Smrg    if ((!xkb) || (!xkb->geom)) {
91487c518e6Smrg        _XkbLibError(_XkbErrMissingGeometry, "WriteCHdrGeometry", 0);
91587c518e6Smrg        return False;
9168c9fbc29Smrg    }
91787c518e6Smrg    geom = xkb->geom;
91887c518e6Smrg    WriteCHdrGeomProps(file, xkb, geom);
91987c518e6Smrg    WriteCHdrGeomColors(file, xkb, geom);
92087c518e6Smrg    WriteCHdrGeomShapes(file, xkb, geom);
92187c518e6Smrg    WriteCHdrGeomSections(file, xkb, geom);
92287c518e6Smrg    WriteCHdrGeomDoodads(file, xkb, geom, NULL, 0);
92387c518e6Smrg    WriteCHdrGeomAliases(file, xkb, geom);
92487c518e6Smrg    fprintf(file, "\nstatic XkbGeometryRec	geom= {\n");
92587c518e6Smrg    fprintf(file, "	None,			/* name */\n");
92687c518e6Smrg    fprintf(file, "	%d, %d,		/* width, height */\n",
92787c518e6Smrg            geom->width_mm, geom->height_mm);
92887c518e6Smrg    if (geom->label_font)
92987c518e6Smrg        fprintf(file, "	\"%s\",/* label font */\n",
93087c518e6Smrg                XkbStringText(geom->label_font, XkbCFile));
93187c518e6Smrg    else
93287c518e6Smrg        fprintf(file, "	NULL,		/* label font */\n");
93387c518e6Smrg    if (geom->label_color)
93487c518e6Smrg        fprintf(file, "	&g_colors[%d],		/* label color */\n",
93587c518e6Smrg                XkbGeomColorIndex(geom, geom->label_color));
93687c518e6Smrg    else
93787c518e6Smrg        fprintf(file, "	NULL,			/* label color */\n");
93887c518e6Smrg    if (geom->base_color)
93987c518e6Smrg        fprintf(file, "	&g_colors[%d],		/* base color */\n",
94087c518e6Smrg                XkbGeomColorIndex(geom, geom->base_color));
94187c518e6Smrg    else
94287c518e6Smrg        fprintf(file, "	NULL,			/* base color */\n");
94387c518e6Smrg    fprintf(file,
94487c518e6Smrg            "	%d,	%d,	%d,	/*  sz: props, colors, shapes */\n",
94587c518e6Smrg            geom->num_properties, geom->num_colors, geom->num_shapes);
94687c518e6Smrg    fprintf(file,
94787c518e6Smrg            "	%d,	%d,	%d,	/*  sz: sections, doodads, aliases */\n",
94887c518e6Smrg            geom->num_sections, geom->num_doodads, geom->num_key_aliases);
94987c518e6Smrg    fprintf(file,
95087c518e6Smrg            "	%d,	%d,	%d,	/* num: props, colors, shapes */\n",
95187c518e6Smrg            geom->num_properties, geom->num_colors, geom->num_shapes);
95287c518e6Smrg    fprintf(file,
95387c518e6Smrg            "	%d,	%d,	%d,	/* num: sections, doodads, aliases */\n",
95487c518e6Smrg            geom->num_sections, geom->num_doodads, geom->num_key_aliases);
95587c518e6Smrg    fprintf(file, "	%s,	%s,	%s,\n",
95687c518e6Smrg            (geom->num_properties > 0 ? "g_props" : "NULL"),
95787c518e6Smrg            (geom->num_colors > 0 ? "g_colors" : "NULL"),
95887c518e6Smrg            (geom->num_shapes > 0 ? "g_shapes" : "NULL"));
95987c518e6Smrg    fprintf(file, "	%s,	%s,	%s\n",
96087c518e6Smrg            (geom->num_sections > 0 ? "g_sections" : "NULL"),
96187c518e6Smrg            (geom->num_doodads > 0 ? "g_doodads" : "NULL"),
96287c518e6Smrg            (geom->num_key_aliases > 0 ? "g_aliases" : "NULL"));
96387c518e6Smrg    fprintf(file, "};\n\n");
96487c518e6Smrg    fprintf(file, "static Bool\n");
96587c518e6Smrg    fprintf(file, "_InitHdrGeom(DPYTYPE dpy,XkbGeometryPtr geom)\n");
96687c518e6Smrg    fprintf(file, "{\n");
96787c518e6Smrg    if (geom->name != None) {
96887c518e6Smrg        fprintf(file, "    geom->name= GET_ATOM(dpy,\"%s\");\n",
96987c518e6Smrg                XkbAtomText(xkb->dpy, geom->name, XkbCFile));
9708c9fbc29Smrg    }
97187c518e6Smrg    for (i = 0; i < geom->num_shapes; i++) {
97287c518e6Smrg        fprintf(file, "    geom->shapes[%2d].name= GET_ATOM(dpy,\"%s\");\n", i,
97387c518e6Smrg                XkbAtomText(xkb->dpy, geom->shapes[i].name, XkbCFile));
9748c9fbc29Smrg    }
97587c518e6Smrg    if (geom->num_doodads > 0)
97687c518e6Smrg        fprintf(file, "    _InitGeomDoodads(dpy,geom);\n");
97787c518e6Smrg    fprintf(file, "    _InitSections(dpy,geom);\n");
97887c518e6Smrg    fprintf(file, "}\n\n");
9798c9fbc29Smrg    return True;
9808c9fbc29Smrg}
9818c9fbc29Smrg
9828c9fbc29Smrgstatic Bool
98387c518e6SmrgWriteCHdrGeomFile(FILE *file, XkbFileInfo *result)
9848c9fbc29Smrg{
98587c518e6Smrg    Bool ok;
9868c9fbc29Smrg
98787c518e6Smrg    ok = WriteCHdrGeometry(file, result->xkb);
9888c9fbc29Smrg    return ok;
9898c9fbc29Smrg}
9908c9fbc29Smrg
9918c9fbc29Smrgstatic Bool
99287c518e6SmrgWriteCHdrLayout(FILE *file, XkbFileInfo *result)
9938c9fbc29Smrg{
99487c518e6Smrg    Bool ok;
99587c518e6Smrg    XkbDescPtr xkb;
99687c518e6Smrg
99787c518e6Smrg    xkb = result->xkb;
99887c518e6Smrg    ok = WriteCHdrVMods(file, xkb->dpy, xkb);
99987c518e6Smrg    ok = WriteCHdrKeycodes(file, xkb) && ok;
100087c518e6Smrg    ok = WriteCHdrSymbols(file, xkb) && ok;
100187c518e6Smrg    ok = WriteCHdrGeometry(file, xkb) && ok;
10028c9fbc29Smrg    return ok;
10038c9fbc29Smrg}
10048c9fbc29Smrg
10058c9fbc29Smrgstatic Bool
100687c518e6SmrgWriteCHdrSemantics(FILE *file, XkbFileInfo *result)
10078c9fbc29Smrg{
100887c518e6Smrg    Bool ok;
100987c518e6Smrg    XkbDescPtr xkb;
101087c518e6Smrg
101187c518e6Smrg    xkb = result->xkb;
101287c518e6Smrg    ok = WriteCHdrVMods(file, xkb->dpy, xkb);
101387c518e6Smrg    ok = WriteCHdrKeyTypes(file, xkb->dpy, xkb) && ok;
101487c518e6Smrg    ok = WriteCHdrCompatMap(file, xkb->dpy, xkb) && ok;
101587c518e6Smrg    ok = WriteCHdrIndicators(file, xkb->dpy, xkb) && ok;
10168c9fbc29Smrg    return ok;
10178c9fbc29Smrg}
10188c9fbc29Smrg
10198c9fbc29Smrgstatic Bool
102087c518e6SmrgWriteCHdrKeymap(FILE *file, XkbFileInfo *result)
10218c9fbc29Smrg{
102287c518e6Smrg    Bool ok;
102387c518e6Smrg    XkbDescPtr xkb;
102487c518e6Smrg
102587c518e6Smrg    xkb = result->xkb;
102687c518e6Smrg    ok = WriteCHdrVMods(file, xkb->dpy, xkb);
102787c518e6Smrg    ok = ok && WriteCHdrKeycodes(file, xkb);
102887c518e6Smrg    ok = ok && WriteCHdrClientMap(file, xkb->dpy, xkb);
102987c518e6Smrg    ok = ok && WriteCHdrServerMap(file, xkb->dpy, xkb);
103087c518e6Smrg    ok = ok && WriteCHdrCompatMap(file, xkb->dpy, xkb);
103187c518e6Smrg    ok = WriteCHdrIndicators(file, xkb->dpy, xkb) && ok;
103287c518e6Smrg    ok = ok && WriteCHdrGeometry(file, xkb);
10338c9fbc29Smrg    return ok;
10348c9fbc29Smrg}
10358c9fbc29Smrg
10368c9fbc29SmrgBool
103787c518e6SmrgXkbWriteCFile(FILE *out, char *name, XkbFileInfo *result)
10388c9fbc29Smrg{
103987c518e6Smrg    Bool ok;
104087c518e6Smrg    XkbDescPtr xkb;
104187c518e6Smrg
104287c518e6Smrg    Bool (*func) (FILE *        /* file */,
104387c518e6Smrg                  XkbFileInfo * /* result */
104487c518e6Smrg        );
10458c9fbc29Smrg
10468c9fbc29Smrg    switch (result->type) {
104787c518e6Smrg    case XkmSemanticsFile:
104887c518e6Smrg        func = WriteCHdrSemantics;
104987c518e6Smrg        break;
105087c518e6Smrg    case XkmLayoutFile:
105187c518e6Smrg        func = WriteCHdrLayout;
105287c518e6Smrg        break;
105387c518e6Smrg    case XkmKeymapFile:
105487c518e6Smrg        func = WriteCHdrKeymap;
105587c518e6Smrg        break;
105687c518e6Smrg    case XkmGeometryIndex:
105787c518e6Smrg    case XkmGeometryFile:
105887c518e6Smrg        func = WriteCHdrGeomFile;
105987c518e6Smrg        break;
106087c518e6Smrg    default:
106187c518e6Smrg        _XkbLibError(_XkbErrIllegalContents, "XkbWriteCFile", result->type);
106287c518e6Smrg        return False;
10638c9fbc29Smrg    }
106487c518e6Smrg    xkb = result->xkb;
106587c518e6Smrg    if (out == NULL) {
106687c518e6Smrg        _XkbLibError(_XkbErrFileCannotOpen, "XkbWriteCFile", 0);
106787c518e6Smrg        ok = False;
10688c9fbc29Smrg    }
10698c9fbc29Smrg    else {
107087c518e6Smrg        char *tmp, *hdrdef;
107187c518e6Smrg
107287c518e6Smrg        tmp = (char *) strrchr(name, '/');
107387c518e6Smrg        if (tmp == NULL)
107487c518e6Smrg            tmp = name;
107587c518e6Smrg        else
107687c518e6Smrg            tmp++;
107787c518e6Smrg        hdrdef = (char *) _XkbCalloc(strlen(tmp) + 1, sizeof(char));
107887c518e6Smrg        if (hdrdef) {
107987c518e6Smrg            strcpy(hdrdef, tmp);
108087c518e6Smrg            tmp = hdrdef;
108187c518e6Smrg            while (*tmp) {
108287c518e6Smrg                if (islower(*tmp))
108387c518e6Smrg                    *tmp = toupper(*tmp);
108487c518e6Smrg                else if (!isalnum(*tmp))
108587c518e6Smrg                    *tmp = '_';
108687c518e6Smrg                tmp++;
108787c518e6Smrg            }
108887c518e6Smrg            fprintf(out, "/* This file generated automatically by xkbcomp */\n");
108987c518e6Smrg            fprintf(out, "/* DO  NOT EDIT */\n");
109087c518e6Smrg            fprintf(out, "#ifndef %s\n", hdrdef);
109187c518e6Smrg            fprintf(out, "#define %s 1\n\n", hdrdef);
109287c518e6Smrg        }
109387c518e6Smrg        fprintf(out, "#ifndef XKB_IN_SERVER\n");
109487c518e6Smrg        fprintf(out, "#define GET_ATOM(d,s)	XInternAtom(d,s,0)\n");
109587c518e6Smrg        fprintf(out, "#define DPYTYPE	Display *\n");
109687c518e6Smrg        fprintf(out, "#else\n");
109787c518e6Smrg        fprintf(out, "#define GET_ATOM(d,s)	MakeAtom(s,strlen(s),1)\n");
109887c518e6Smrg        fprintf(out, "#define DPYTYPE	char *\n");
109987c518e6Smrg        fprintf(out, "#endif\n");
110087c518e6Smrg        fprintf(out, "#define NUM_KEYS	%d\n", xkb->max_key_code + 1);
110187c518e6Smrg        ok = (*func) (out, result);
110287c518e6Smrg        if (hdrdef)
110387c518e6Smrg            fprintf(out, "#endif /* %s */\n", hdrdef);
11048c9fbc29Smrg    }
11058c9fbc29Smrg
11068c9fbc29Smrg    if (!ok) {
110787c518e6Smrg        return False;
11088c9fbc29Smrg    }
11098c9fbc29Smrg    return True;
11108c9fbc29Smrg}
1111