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/Xfuncs.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
418c9fbc29Smrgtypedef struct _XkmInfo {
4270728a38Smrg    unsigned short bound_vmods;
4370728a38Smrg    unsigned short named_vmods;
4470728a38Smrg    unsigned char  num_bound;
4570728a38Smrg    unsigned char  group_compat;
4670728a38Smrg    unsigned short num_group_compat;
4770728a38Smrg    unsigned short num_leds;
4870728a38Smrg    int            total_vmodmaps;
498c9fbc29Smrg} XkmInfo;
508c9fbc29Smrg
518c9fbc29Smrg/***====================================================================***/
528c9fbc29Smrg
538c9fbc29Smrg#define	xkmPutCARD8(f,v)	(putc(v,f),1)
548c9fbc29Smrg
558c9fbc29Smrgstatic int
5670728a38SmrgxkmPutCARD16(FILE *file, unsigned val)
578c9fbc29Smrg{
5870728a38Smrg    CARD16 tmp = val;
598c9fbc29Smrg
6070728a38Smrg    fwrite(&tmp, 2, 1, file);
618c9fbc29Smrg    return 2;
628c9fbc29Smrg}
638c9fbc29Smrg
648c9fbc29Smrgstatic int
6570728a38SmrgxkmPutCARD32(FILE *file, unsigned long val)
668c9fbc29Smrg{
6770728a38Smrg    CARD32 tmp = val;
688c9fbc29Smrg
6970728a38Smrg    fwrite(&tmp, 4, 1, file);
708c9fbc29Smrg    return 4;
718c9fbc29Smrg}
728c9fbc29Smrg
738c9fbc29Smrgstatic int
7470728a38SmrgxkmPutPadding(FILE *file, unsigned pad)
758c9fbc29Smrg{
7670728a38Smrg    int i;
7770728a38Smrg
7870728a38Smrg    for (i = 0; i < pad; i++) {
7970728a38Smrg        putc('\0', file);
808c9fbc29Smrg    }
818c9fbc29Smrg    return pad;
828c9fbc29Smrg}
838c9fbc29Smrg
848c9fbc29Smrgstatic int
8570728a38SmrgxkmPutCountedBytes(FILE *file, char *ptr, unsigned count)
868c9fbc29Smrg{
8770728a38Smrg    register int nOut;
8870728a38Smrg    register unsigned pad;
8970728a38Smrg
9070728a38Smrg    if (count == 0)
9170728a38Smrg        return xkmPutCARD32(file, (unsigned long) 0);
9270728a38Smrg
9370728a38Smrg    xkmPutCARD16(file, count);
9470728a38Smrg    nOut = fwrite(ptr, 1, count, file);
9570728a38Smrg    if (nOut < 0)
9670728a38Smrg        return 2;
9770728a38Smrg    nOut = count + 2;
9870728a38Smrg    pad = XkbPaddedSize(nOut) - nOut;
998c9fbc29Smrg    if (pad)
10070728a38Smrg        xkmPutPadding(file, pad);
10170728a38Smrg    return nOut + pad;
1028c9fbc29Smrg}
1038c9fbc29Smrg
1048c9fbc29Smrgstatic unsigned
1058c9fbc29SmrgxkmSizeCountedString(char *str)
1068c9fbc29Smrg{
10770728a38Smrg    if (str == NULL)
10870728a38Smrg        return 4;
10970728a38Smrg    return XkbPaddedSize(strlen(str) + 2);
1108c9fbc29Smrg}
1118c9fbc29Smrg
1128c9fbc29Smrgstatic int
11370728a38SmrgxkmPutCountedString(FILE *file, char *str)
1148c9fbc29Smrg{
11570728a38Smrg    if (str == NULL)
11670728a38Smrg        return xkmPutCARD32(file, (unsigned long) 0);
11770728a38Smrg    return xkmPutCountedBytes(file, str, strlen(str));
1188c9fbc29Smrg}
1198c9fbc29Smrg
1208c9fbc29Smrg#define	xkmSizeCountedAtomString(d,a)	\
1218c9fbc29Smrg	xkmSizeCountedString(XkbAtomGetString((d),(a)))
1228c9fbc29Smrg
1238c9fbc29Smrg#define	xkmPutCountedAtomString(d,f,a)	\
1248c9fbc29Smrg	xkmPutCountedString((f),XkbAtomGetString((d),(a)))
1258c9fbc29Smrg
1268c9fbc29Smrg/***====================================================================***/
1278c9fbc29Smrg
1288c9fbc29Smrgstatic unsigned
12970728a38SmrgSizeXKMVirtualMods(XkbFileInfo *result, XkmInfo *info,
13070728a38Smrg                   xkmSectionInfo *toc, int *offset_inout)
1318c9fbc29Smrg{
13270728a38Smrg    Display *dpy;
13370728a38Smrg    XkbDescPtr xkb;
13470728a38Smrg    unsigned nBound, bound;
13570728a38Smrg    unsigned nNamed, named, szNames;
13670728a38Smrg    register unsigned i, bit;
13770728a38Smrg
13870728a38Smrg    xkb = result->xkb;
13970728a38Smrg    if ((!xkb) || (!xkb->names) || (!xkb->server)) {
14070728a38Smrg        _XkbLibError(_XkbErrMissingVMods, "SizeXKMVirtualMods", 0);
14170728a38Smrg        return 0;
1428c9fbc29Smrg    }
14370728a38Smrg    dpy = xkb->dpy;
14470728a38Smrg    bound = named = 0;
14570728a38Smrg    for (i = nBound = nNamed = szNames = 0, bit = 1; i < XkbNumVirtualMods;
14670728a38Smrg         i++, bit <<= 1) {
14770728a38Smrg        if (xkb->server->vmods[i] != XkbNoModifierMask) {
14870728a38Smrg            bound |= bit;
14970728a38Smrg            nBound++;
15070728a38Smrg        }
15170728a38Smrg        if (xkb->names->vmods[i] != None) {
15270728a38Smrg            named |= bit;
15370728a38Smrg            szNames += xkmSizeCountedAtomString(dpy, xkb->names->vmods[i]);
15470728a38Smrg            nNamed++;
15570728a38Smrg        }
1568c9fbc29Smrg    }
15770728a38Smrg    info->num_bound = nBound;
15870728a38Smrg    info->bound_vmods = bound;
15970728a38Smrg    info->named_vmods = named;
16070728a38Smrg    if ((nBound == 0) && (nNamed == 0))
16170728a38Smrg        return 0;
16270728a38Smrg    toc->type = XkmVirtualModsIndex;
16370728a38Smrg    toc->format = MSBFirst;
16470728a38Smrg    toc->size = 4 + XkbPaddedSize(nBound) + szNames + SIZEOF(xkmSectionInfo);
16570728a38Smrg    toc->offset = *offset_inout;
16670728a38Smrg    (*offset_inout) += toc->size;
1678c9fbc29Smrg    return 1;
1688c9fbc29Smrg}
1698c9fbc29Smrg
1708c9fbc29Smrgstatic unsigned
17170728a38SmrgWriteXKMVirtualMods(FILE *file, XkbFileInfo *result, XkmInfo *info)
1728c9fbc29Smrg{
17370728a38Smrg    register unsigned int i, bit;
17470728a38Smrg    XkbDescPtr xkb;
17570728a38Smrg    Display *dpy;
17670728a38Smrg    unsigned size = 0;
17770728a38Smrg
17870728a38Smrg    xkb = result->xkb;
17970728a38Smrg    dpy = xkb->dpy;
18070728a38Smrg    size += xkmPutCARD16(file, info->bound_vmods);
18170728a38Smrg    size += xkmPutCARD16(file, info->named_vmods);
18270728a38Smrg    for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
18370728a38Smrg        if (info->bound_vmods & bit)
18470728a38Smrg            size += xkmPutCARD8(file, xkb->server->vmods[i]);
1858c9fbc29Smrg    }
18670728a38Smrg    if ((i = XkbPaddedSize(info->num_bound) - info->num_bound) > 0)
18770728a38Smrg        size += xkmPutPadding(file, i);
18870728a38Smrg    for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
18970728a38Smrg        if (info->named_vmods & bit) {
19070728a38Smrg            register char *name;
19170728a38Smrg
19270728a38Smrg            name = XkbAtomGetString(dpy, xkb->names->vmods[i]);
19370728a38Smrg            size += xkmPutCountedString(file, name);
19470728a38Smrg        }
1958c9fbc29Smrg    }
1968c9fbc29Smrg    return size;
1978c9fbc29Smrg}
1988c9fbc29Smrg
1998c9fbc29Smrg/***====================================================================***/
2008c9fbc29Smrg
2018c9fbc29Smrgstatic unsigned
20270728a38SmrgSizeXKMKeycodes(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout)
2038c9fbc29Smrg{
20470728a38Smrg    XkbDescPtr xkb;
20570728a38Smrg    Atom kcName;
20670728a38Smrg    int size = 0;
20770728a38Smrg    Display *dpy;
20870728a38Smrg
20970728a38Smrg    xkb = result->xkb;
21070728a38Smrg    if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) {
21170728a38Smrg        _XkbLibError(_XkbErrMissingNames, "SizeXKMKeycodes", 0);
21270728a38Smrg        return 0;
2138c9fbc29Smrg    }
21470728a38Smrg    dpy = xkb->dpy;
21570728a38Smrg    kcName = xkb->names->keycodes;
21670728a38Smrg    size += 4;                  /* min and max keycode */
21770728a38Smrg    size += xkmSizeCountedAtomString(dpy, kcName);
21870728a38Smrg    size += XkbNumKeys(xkb) * sizeof(XkbKeyNameRec);
21970728a38Smrg    if (xkb->names->num_key_aliases > 0) {
22070728a38Smrg        if (xkb->names->key_aliases != NULL)
22170728a38Smrg            size += xkb->names->num_key_aliases * sizeof(XkbKeyAliasRec);
22270728a38Smrg        else
22370728a38Smrg            xkb->names->num_key_aliases = 0;
2248c9fbc29Smrg    }
22570728a38Smrg    toc->type = XkmKeyNamesIndex;
22670728a38Smrg    toc->format = MSBFirst;
22770728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
22870728a38Smrg    toc->offset = (*offset_inout);
22970728a38Smrg    (*offset_inout) += toc->size;
2308c9fbc29Smrg    return 1;
2318c9fbc29Smrg}
2328c9fbc29Smrg
2338c9fbc29Smrgstatic unsigned
23470728a38SmrgWriteXKMKeycodes(FILE *file, XkbFileInfo *result)
2358c9fbc29Smrg{
23670728a38Smrg    XkbDescPtr xkb;
23770728a38Smrg    Atom kcName;
23870728a38Smrg    char *start;
23970728a38Smrg    Display *dpy;
24070728a38Smrg    unsigned tmp, size = 0;
24170728a38Smrg
24270728a38Smrg    xkb = result->xkb;
24370728a38Smrg    dpy = xkb->dpy;
24470728a38Smrg    kcName = xkb->names->keycodes;
24570728a38Smrg    start = xkb->names->keys[xkb->min_key_code].name;
24670728a38Smrg
24770728a38Smrg    size += xkmPutCountedString(file, XkbAtomGetString(dpy, kcName));
24870728a38Smrg    size += xkmPutCARD8(file, xkb->min_key_code);
24970728a38Smrg    size += xkmPutCARD8(file, xkb->max_key_code);
25070728a38Smrg    size += xkmPutCARD8(file, xkb->names->num_key_aliases);
25170728a38Smrg    size += xkmPutPadding(file, 1);
25270728a38Smrg    tmp = fwrite(start, sizeof(XkbKeyNameRec), XkbNumKeys(xkb), file);
25370728a38Smrg    size += tmp * sizeof(XkbKeyNameRec);
25470728a38Smrg    if (xkb->names->num_key_aliases > 0) {
25570728a38Smrg        tmp = fwrite((char *) xkb->names->key_aliases,
25670728a38Smrg                     sizeof(XkbKeyAliasRec), xkb->names->num_key_aliases, file);
25770728a38Smrg        size += tmp * sizeof(XkbKeyAliasRec);
2588c9fbc29Smrg    }
2598c9fbc29Smrg    return size;
2608c9fbc29Smrg}
2618c9fbc29Smrg
2628c9fbc29Smrg/***====================================================================***/
2638c9fbc29Smrg
2648c9fbc29Smrgstatic unsigned
26570728a38SmrgSizeXKMKeyTypes(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout)
2668c9fbc29Smrg{
26770728a38Smrg    register unsigned i, n, size;
26870728a38Smrg    XkbKeyTypePtr type;
26970728a38Smrg    XkbDescPtr xkb;
27070728a38Smrg    Display *dpy;
27170728a38Smrg    char *name;
27270728a38Smrg
27370728a38Smrg    xkb = result->xkb;
27470728a38Smrg    if ((!xkb) || (!xkb->map) || (!xkb->map->types)) {
27570728a38Smrg        _XkbLibError(_XkbErrMissingTypes, "SizeXKBKeyTypes", 0);
27670728a38Smrg        return 0;
2778c9fbc29Smrg    }
27870728a38Smrg    dpy = xkb->dpy;
27970728a38Smrg    if (xkb->map->num_types < XkbNumRequiredTypes) {
28070728a38Smrg        _XkbLibError(_XkbErrMissingReqTypes, "SizeXKBKeyTypes", 0);
28170728a38Smrg        return 0;
2828c9fbc29Smrg    }
28370728a38Smrg    if (xkb->names)
28470728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->types);
28570728a38Smrg    else
28670728a38Smrg        name = NULL;
28770728a38Smrg    size = xkmSizeCountedString(name);
28870728a38Smrg    size += 4;                  /* room for # of key types + padding */
28970728a38Smrg    for (i = 0, type = xkb->map->types; i < xkb->map->num_types; i++, type++) {
29070728a38Smrg        size += SIZEOF(xkmKeyTypeDesc);
29170728a38Smrg        size += SIZEOF(xkmKTMapEntryDesc) * type->map_count;
29270728a38Smrg        size += xkmSizeCountedAtomString(dpy, type->name);
29370728a38Smrg        if (type->preserve)
29470728a38Smrg            size += SIZEOF(xkmModsDesc) * type->map_count;
29570728a38Smrg        if (type->level_names) {
29670728a38Smrg            Atom *names;
29770728a38Smrg
29870728a38Smrg            names = type->level_names;
29970728a38Smrg            for (n = 0; n < (unsigned) type->num_levels; n++) {
30070728a38Smrg                size += xkmSizeCountedAtomString(dpy, names[n]);
30170728a38Smrg            }
30270728a38Smrg        }
3038c9fbc29Smrg    }
30470728a38Smrg    toc->type = XkmTypesIndex;
30570728a38Smrg    toc->format = MSBFirst;
30670728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
30770728a38Smrg    toc->offset = (*offset_inout);
30870728a38Smrg    (*offset_inout) += toc->size;
3098c9fbc29Smrg    return 1;
3108c9fbc29Smrg}
3118c9fbc29Smrg
3128c9fbc29Smrgstatic unsigned
31370728a38SmrgWriteXKMKeyTypes(FILE *file, XkbFileInfo *result)
3148c9fbc29Smrg{
31570728a38Smrg    register unsigned i, n;
31670728a38Smrg    XkbDescPtr xkb;
31770728a38Smrg    XkbKeyTypePtr type;
31870728a38Smrg    xkmKeyTypeDesc wire;
31970728a38Smrg    XkbKTMapEntryPtr entry;
32070728a38Smrg    xkmKTMapEntryDesc wire_entry;
32170728a38Smrg    Atom *names;
32270728a38Smrg    Display *dpy;
32370728a38Smrg    unsigned tmp, size = 0;
32470728a38Smrg    char *name;
32570728a38Smrg
32670728a38Smrg    xkb = result->xkb;
32770728a38Smrg    dpy = xkb->dpy;
32870728a38Smrg    if (xkb->names)
32970728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->types);
33070728a38Smrg    else
33170728a38Smrg        name = NULL;
33270728a38Smrg    size += xkmPutCountedString(file, name);
33370728a38Smrg    size += xkmPutCARD16(file, xkb->map->num_types);
33470728a38Smrg    size += xkmPutPadding(file, 2);
33570728a38Smrg    type = xkb->map->types;
33670728a38Smrg    for (i = 0; i < xkb->map->num_types; i++, type++) {
33770728a38Smrg        wire.realMods = type->mods.real_mods;
33870728a38Smrg        wire.virtualMods = type->mods.vmods;
33970728a38Smrg        wire.numLevels = type->num_levels;
34070728a38Smrg        wire.nMapEntries = type->map_count;
34170728a38Smrg        wire.preserve = (type->preserve != NULL);
34270728a38Smrg        if (type->level_names != NULL)
34370728a38Smrg            wire.nLevelNames = type->num_levels;
34470728a38Smrg        else
34570728a38Smrg            wire.nLevelNames = 0;
34670728a38Smrg        tmp = fwrite(&wire, SIZEOF(xkmKeyTypeDesc), 1, file);
34770728a38Smrg        size += tmp * SIZEOF(xkmKeyTypeDesc);
34870728a38Smrg        for (n = 0, entry = type->map; n < type->map_count; n++, entry++) {
34970728a38Smrg            wire_entry.level = entry->level;
35070728a38Smrg            wire_entry.realMods = entry->mods.real_mods;
35170728a38Smrg            wire_entry.virtualMods = entry->mods.vmods;
35270728a38Smrg            tmp = fwrite(&wire_entry, SIZEOF(xkmKTMapEntryDesc), 1, file);
35370728a38Smrg            size += tmp * SIZEOF(xkmKTMapEntryDesc);
35470728a38Smrg        }
35570728a38Smrg        size += xkmPutCountedString(file, XkbAtomGetString(dpy, type->name));
35670728a38Smrg        if (type->preserve) {
35770728a38Smrg            xkmModsDesc p_entry;
35870728a38Smrg
35970728a38Smrg            XkbModsPtr pre;
36070728a38Smrg
36170728a38Smrg            for (n = 0, pre = type->preserve; n < type->map_count; n++, pre++) {
36270728a38Smrg                p_entry.realMods = pre->real_mods;
36370728a38Smrg                p_entry.virtualMods = pre->vmods;
36470728a38Smrg                tmp = fwrite(&p_entry, SIZEOF(xkmModsDesc), 1, file);
36570728a38Smrg                size += tmp * SIZEOF(xkmModsDesc);
36670728a38Smrg            }
36770728a38Smrg        }
36870728a38Smrg        if (type->level_names != NULL) {
36970728a38Smrg            names = type->level_names;
37070728a38Smrg            for (n = 0; n < wire.nLevelNames; n++) {
37170728a38Smrg                size +=
37270728a38Smrg                    xkmPutCountedString(file, XkbAtomGetString(dpy, names[n]));
37370728a38Smrg            }
37470728a38Smrg        }
3758c9fbc29Smrg    }
3768c9fbc29Smrg    return size;
3778c9fbc29Smrg}
3788c9fbc29Smrg
3798c9fbc29Smrg/***====================================================================***/
3808c9fbc29Smrg
3818c9fbc29Smrgstatic unsigned
38270728a38SmrgSizeXKMCompatMap(XkbFileInfo *result, XkmInfo *info,
38370728a38Smrg                 xkmSectionInfo *toc, int *offset_inout)
3848c9fbc29Smrg{
38570728a38Smrg    XkbDescPtr xkb;
38670728a38Smrg    char *name;
38770728a38Smrg    int size;
38870728a38Smrg    register int i;
38970728a38Smrg    unsigned groups, nGroups;
39070728a38Smrg    Display *dpy;
39170728a38Smrg
39270728a38Smrg    xkb = result->xkb;
39370728a38Smrg    if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) {
39470728a38Smrg        _XkbLibError(_XkbErrMissingCompatMap, "SizeXKMCompatMap", 0);
39570728a38Smrg        return 0;
3968c9fbc29Smrg    }
39770728a38Smrg    dpy = xkb->dpy;
39870728a38Smrg    if (xkb->names)
39970728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->compat);
40070728a38Smrg    else
40170728a38Smrg        name = NULL;
40270728a38Smrg
40370728a38Smrg    for (i = groups = nGroups = 0; i < XkbNumKbdGroups; i++) {
40470728a38Smrg        if ((xkb->compat->groups[i].real_mods != 0) ||
40570728a38Smrg            (xkb->compat->groups[i].vmods != 0)) {
40670728a38Smrg            groups |= (1 << i);
40770728a38Smrg            nGroups++;
40870728a38Smrg        }
4098c9fbc29Smrg    }
41070728a38Smrg    info->group_compat = groups;
41170728a38Smrg    info->num_group_compat = nGroups;
41270728a38Smrg    size = 4;                   /* room for num_si and group_compat mask */
41370728a38Smrg    size += xkmSizeCountedString(name);
41470728a38Smrg    size += (SIZEOF(xkmSymInterpretDesc) * xkb->compat->num_si);
41570728a38Smrg    size += (SIZEOF(xkmModsDesc) * nGroups);
41670728a38Smrg    toc->type = XkmCompatMapIndex;
41770728a38Smrg    toc->format = MSBFirst;
41870728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
41970728a38Smrg    toc->offset = (*offset_inout);
42070728a38Smrg    (*offset_inout) += toc->size;
4218c9fbc29Smrg    return 1;
4228c9fbc29Smrg}
4238c9fbc29Smrg
4248c9fbc29Smrgstatic unsigned
42570728a38SmrgWriteXKMCompatMap(FILE *file, XkbFileInfo *result, XkmInfo *info)
4268c9fbc29Smrg{
42770728a38Smrg    register unsigned i;
42870728a38Smrg    char *name;
42970728a38Smrg    XkbDescPtr xkb;
43070728a38Smrg    XkbSymInterpretPtr interp;
43170728a38Smrg    xkmSymInterpretDesc wire;
43270728a38Smrg    Display *dpy;
43370728a38Smrg    unsigned tmp, size = 0;
43470728a38Smrg
43570728a38Smrg    xkb = result->xkb;
43670728a38Smrg    dpy = xkb->dpy;
43770728a38Smrg    if (xkb->names)
43870728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->compat);
43970728a38Smrg    else
44070728a38Smrg        name = NULL;
44170728a38Smrg    size += xkmPutCountedString(file, name);
44270728a38Smrg    size += xkmPutCARD16(file, xkb->compat->num_si);
44370728a38Smrg    size += xkmPutCARD8(file, info->group_compat);
44470728a38Smrg    size += xkmPutPadding(file, 1);
44570728a38Smrg    interp = xkb->compat->sym_interpret;
44670728a38Smrg    for (i = 0; i < xkb->compat->num_si; i++, interp++) {
44770728a38Smrg        wire.sym = interp->sym;
44870728a38Smrg        wire.mods = interp->mods;
44970728a38Smrg        wire.match = interp->match;
45070728a38Smrg        wire.virtualMod = interp->virtual_mod;
45170728a38Smrg        wire.flags = interp->flags;
45270728a38Smrg        wire.actionType = interp->act.type;
45370728a38Smrg        wire.actionData[0] = interp->act.data[0];
45470728a38Smrg        wire.actionData[1] = interp->act.data[1];
45570728a38Smrg        wire.actionData[2] = interp->act.data[2];
45670728a38Smrg        wire.actionData[3] = interp->act.data[3];
45770728a38Smrg        wire.actionData[4] = interp->act.data[4];
45870728a38Smrg        wire.actionData[5] = interp->act.data[5];
45970728a38Smrg        wire.actionData[6] = interp->act.data[6];
46070728a38Smrg        tmp = fwrite(&wire, SIZEOF(xkmSymInterpretDesc), 1, file);
46170728a38Smrg        size += tmp * SIZEOF(xkmSymInterpretDesc);
4628c9fbc29Smrg    }
4638c9fbc29Smrg    if (info->group_compat) {
46470728a38Smrg        register unsigned bit;
46570728a38Smrg
46670728a38Smrg        xkmModsDesc modsWire;
46770728a38Smrg
46870728a38Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
46970728a38Smrg            if (info->group_compat & bit) {
47070728a38Smrg                modsWire.realMods = xkb->compat->groups[i].real_mods;
47170728a38Smrg                modsWire.virtualMods = xkb->compat->groups[i].vmods;
47270728a38Smrg                fwrite(&modsWire, SIZEOF(xkmModsDesc), 1, file);
47370728a38Smrg                size += SIZEOF(xkmModsDesc);
47470728a38Smrg            }
47570728a38Smrg        }
4768c9fbc29Smrg    }
4778c9fbc29Smrg    return size;
4788c9fbc29Smrg}
4798c9fbc29Smrg
4808c9fbc29Smrg/***====================================================================***/
4818c9fbc29Smrg
4828c9fbc29Smrgstatic unsigned
48370728a38SmrgSizeXKMSymbols(XkbFileInfo *result, XkmInfo *info,
48470728a38Smrg               xkmSectionInfo *toc, int *offset_inout)
4858c9fbc29Smrg{
48670728a38Smrg    Display *dpy;
48770728a38Smrg    XkbDescPtr xkb;
48870728a38Smrg    unsigned size;
48970728a38Smrg    register int i, nSyms;
49070728a38Smrg    char *name;
49170728a38Smrg
49270728a38Smrg    xkb = result->xkb;
49370728a38Smrg    if ((!xkb) || (!xkb->map) || ((!xkb->map->syms))) {
49470728a38Smrg        _XkbLibError(_XkbErrMissingSymbols, "SizeXKMSymbols", 0);
49570728a38Smrg        return 0;
4968c9fbc29Smrg    }
49770728a38Smrg    dpy = xkb->dpy;
49870728a38Smrg    if (xkb->names && (xkb->names->symbols != None))
49970728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->symbols);
50070728a38Smrg    else
50170728a38Smrg        name = NULL;
50270728a38Smrg    size = xkmSizeCountedString(name);
50370728a38Smrg    size += 4;                  /* min and max keycode, group names mask */
50470728a38Smrg    for (i = 0; i < XkbNumKbdGroups; i++) {
50570728a38Smrg        if (xkb->names->groups[i] != None)
50670728a38Smrg            size += xkmSizeCountedAtomString(dpy, xkb->names->groups[i]);
5078c9fbc29Smrg    }
50870728a38Smrg    info->total_vmodmaps = 0;
50970728a38Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
51070728a38Smrg        nSyms = XkbKeyNumSyms(xkb, i);
51170728a38Smrg        size += SIZEOF(xkmKeySymMapDesc) + (nSyms * 4);
51270728a38Smrg        if (xkb->server) {
51370728a38Smrg            if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) {
51470728a38Smrg                register int g;
51570728a38Smrg
51670728a38Smrg                for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
51770728a38Smrg                    if (xkb->server->explicit[i] & (1 << g)) {
51870728a38Smrg                        XkbKeyTypePtr type;
51970728a38Smrg                        char *name;
52070728a38Smrg
52170728a38Smrg                        type = XkbKeyKeyType(xkb, i, g);
52270728a38Smrg                        name = XkbAtomGetString(dpy, type->name);
52370728a38Smrg                        if (name != NULL)
52470728a38Smrg                            size += xkmSizeCountedString(name);
52570728a38Smrg                    }
52670728a38Smrg                }
52770728a38Smrg            }
52870728a38Smrg            if (XkbKeyHasActions(xkb, i))
52970728a38Smrg                size += nSyms * SIZEOF(xkmActionDesc);
53070728a38Smrg            if (xkb->server->behaviors[i].type != XkbKB_Default)
53170728a38Smrg                size += SIZEOF(xkmBehaviorDesc);
53270728a38Smrg            if (xkb->server->vmodmap && (xkb->server->vmodmap[i] != 0))
53370728a38Smrg                info->total_vmodmaps++;
53470728a38Smrg        }
5358c9fbc29Smrg    }
53670728a38Smrg    size += info->total_vmodmaps * SIZEOF(xkmVModMapDesc);
53770728a38Smrg    toc->type = XkmSymbolsIndex;
53870728a38Smrg    toc->format = MSBFirst;
53970728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
54070728a38Smrg    toc->offset = (*offset_inout);
54170728a38Smrg    (*offset_inout) += toc->size;
5428c9fbc29Smrg    return 1;
5438c9fbc29Smrg}
5448c9fbc29Smrg
5458c9fbc29Smrgstatic unsigned
54670728a38SmrgWriteXKMSymbols(FILE *file, XkbFileInfo *result, XkmInfo *info)
5478c9fbc29Smrg{
54870728a38Smrg    Display *dpy;
54970728a38Smrg    XkbDescPtr xkb;
55070728a38Smrg    register int i, n;
55170728a38Smrg    xkmKeySymMapDesc wireMap;
55270728a38Smrg    char *name;
55370728a38Smrg    unsigned tmp, size = 0;
55470728a38Smrg
55570728a38Smrg    xkb = result->xkb;
55670728a38Smrg    dpy = xkb->dpy;
55770728a38Smrg    if (xkb->names && (xkb->names->symbols != None))
55870728a38Smrg        name = XkbAtomGetString(dpy, xkb->names->symbols);
55970728a38Smrg    else
56070728a38Smrg        name = NULL;
56170728a38Smrg    size += xkmPutCountedString(file, name);
56270728a38Smrg    for (tmp = i = 0; i < XkbNumKbdGroups; i++) {
56370728a38Smrg        if (xkb->names->groups[i] != None)
56470728a38Smrg            tmp |= (1 << i);
5658c9fbc29Smrg    }
56670728a38Smrg    size += xkmPutCARD8(file, xkb->min_key_code);
56770728a38Smrg    size += xkmPutCARD8(file, xkb->max_key_code);
56870728a38Smrg    size += xkmPutCARD8(file, tmp);
56970728a38Smrg    size += xkmPutCARD8(file, info->total_vmodmaps);
57070728a38Smrg    for (i = 0, n = 1; i < XkbNumKbdGroups; i++, n <<= 1) {
57170728a38Smrg        if ((tmp & n) == 0)
57270728a38Smrg            continue;
57370728a38Smrg        size += xkmPutCountedAtomString(dpy, file, xkb->names->groups[i]);
5748c9fbc29Smrg    }
57570728a38Smrg    for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
57670728a38Smrg        char *typeName[XkbNumKbdGroups];
57770728a38Smrg
57870728a38Smrg        wireMap.width = XkbKeyGroupsWidth(xkb, i);
57970728a38Smrg        wireMap.num_groups = XkbKeyGroupInfo(xkb, i);
58070728a38Smrg        if (xkb->map && xkb->map->modmap)
58170728a38Smrg            wireMap.modifier_map = xkb->map->modmap[i];
58270728a38Smrg        else
58370728a38Smrg            wireMap.modifier_map = 0;
58470728a38Smrg        wireMap.flags = 0;
58570728a38Smrg        bzero((char *) typeName, XkbNumKbdGroups * sizeof(char *));
58670728a38Smrg        if (xkb->server) {
58770728a38Smrg            if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) {
58870728a38Smrg                register int g;
58970728a38Smrg
59070728a38Smrg                for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) {
59170728a38Smrg                    if (xkb->server->explicit[i] & (1 << g)) {
59270728a38Smrg                        XkbKeyTypePtr type;
59370728a38Smrg
59470728a38Smrg                        type = XkbKeyKeyType(xkb, i, g);
59570728a38Smrg                        typeName[g] = XkbAtomGetString(dpy, type->name);
59670728a38Smrg                        if (typeName[g] != NULL)
59770728a38Smrg                            wireMap.flags |= (1 << g);
59870728a38Smrg                    }
59970728a38Smrg                }
60070728a38Smrg            }
60170728a38Smrg            if (XkbKeyHasActions(xkb, i))
60270728a38Smrg                wireMap.flags |= XkmKeyHasActions;
60370728a38Smrg            if (xkb->server->behaviors[i].type != XkbKB_Default)
60470728a38Smrg                wireMap.flags |= XkmKeyHasBehavior;
60570728a38Smrg            if ((xkb->server->explicit[i] & XkbExplicitAutoRepeatMask) &&
60670728a38Smrg                (xkb->ctrls != NULL)) {
60770728a38Smrg                if (xkb->ctrls->per_key_repeat[(i / 8)] & (1 << (i % 8)))
60870728a38Smrg                    wireMap.flags |= XkmRepeatingKey;
60970728a38Smrg                else
61070728a38Smrg                    wireMap.flags |= XkmNonRepeatingKey;
61170728a38Smrg            }
61270728a38Smrg        }
61370728a38Smrg        tmp = fwrite(&wireMap, SIZEOF(xkmKeySymMapDesc), 1, file);
61470728a38Smrg        size += tmp * SIZEOF(xkmKeySymMapDesc);
61570728a38Smrg        if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) {
61670728a38Smrg            register int g;
61770728a38Smrg
61870728a38Smrg            for (g = 0; g < XkbNumKbdGroups; g++) {
61970728a38Smrg                if (typeName[g] != NULL)
62070728a38Smrg                    size += xkmPutCountedString(file, typeName[g]);
62170728a38Smrg            }
62270728a38Smrg        }
62370728a38Smrg        if (XkbNumGroups(wireMap.num_groups) > 0) {
62470728a38Smrg            KeySym *sym;
62570728a38Smrg
62670728a38Smrg            sym = XkbKeySymsPtr(xkb, i);
62770728a38Smrg            for (n = XkbKeyNumSyms(xkb, i); n > 0; n--, sym++) {
62870728a38Smrg                size += xkmPutCARD32(file, (CARD32) *sym);
62970728a38Smrg            }
63070728a38Smrg            if (wireMap.flags & XkmKeyHasActions) {
63170728a38Smrg                XkbAction *act;
63270728a38Smrg
63370728a38Smrg                act = XkbKeyActionsPtr(xkb, i);
63470728a38Smrg                for (n = XkbKeyNumActions(xkb, i); n > 0; n--, act++) {
63570728a38Smrg                    tmp = fwrite(act, SIZEOF(xkmActionDesc), 1, file);
63670728a38Smrg                    size += tmp * SIZEOF(xkmActionDesc);
63770728a38Smrg                }
63870728a38Smrg            }
63970728a38Smrg        }
64070728a38Smrg        if (wireMap.flags & XkmKeyHasBehavior) {
64170728a38Smrg            xkmBehaviorDesc b;
64270728a38Smrg
64370728a38Smrg            b.type = xkb->server->behaviors[i].type;
64470728a38Smrg            b.data = xkb->server->behaviors[i].data;
64570728a38Smrg            tmp = fwrite(&b, SIZEOF(xkmBehaviorDesc), 1, file);
64670728a38Smrg            size += tmp * SIZEOF(xkmBehaviorDesc);
64770728a38Smrg        }
6488c9fbc29Smrg    }
64970728a38Smrg    if (info->total_vmodmaps > 0) {
65070728a38Smrg        xkmVModMapDesc v;
65170728a38Smrg
65270728a38Smrg        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
65370728a38Smrg            if (xkb->server->vmodmap[i] != 0) {
65470728a38Smrg                v.key = i;
65570728a38Smrg                v.vmods = xkb->server->vmodmap[i];
65670728a38Smrg                tmp = fwrite(&v, SIZEOF(xkmVModMapDesc), 1, file);
65770728a38Smrg                size += tmp * SIZEOF(xkmVModMapDesc);
65870728a38Smrg            }
65970728a38Smrg        }
6608c9fbc29Smrg    }
6618c9fbc29Smrg    return size;
6628c9fbc29Smrg}
6638c9fbc29Smrg
6648c9fbc29Smrg/***====================================================================***/
6658c9fbc29Smrg
6668c9fbc29Smrgstatic unsigned
66770728a38SmrgSizeXKMIndicators(XkbFileInfo *result, XkmInfo *info,
66870728a38Smrg                  xkmSectionInfo *toc, int *offset_inout)
6698c9fbc29Smrg{
67070728a38Smrg    Display *dpy;
67170728a38Smrg    XkbDescPtr xkb;
67270728a38Smrg    unsigned size;
67370728a38Smrg    register unsigned i, nLEDs;
67470728a38Smrg
67570728a38Smrg    xkb = result->xkb;
67670728a38Smrg    if ((xkb == NULL) || (xkb->indicators == NULL)) {
6778c9fbc29Smrg/*	_XkbLibError(_XkbErrMissingIndicators,"SizeXKMIndicators",0);*/
67870728a38Smrg        return 0;
6798c9fbc29Smrg    }
68070728a38Smrg    dpy = xkb->dpy;
68170728a38Smrg    nLEDs = 0;
68270728a38Smrg    size = 8; /* number of indicator maps/physical indicators */
68370728a38Smrg    if (xkb->indicators != NULL) {
68470728a38Smrg        for (i = 0; i < XkbNumIndicators; i++) {
68570728a38Smrg            XkbIndicatorMapPtr map = &xkb->indicators->maps[i];
68670728a38Smrg
68770728a38Smrg            if ((map->flags != 0) || (map->which_groups != 0) ||
68870728a38Smrg                (map->groups != 0) || (map->which_mods != 0) ||
68970728a38Smrg                (map->mods.real_mods != 0) || (map->mods.vmods != 0) ||
69070728a38Smrg                (map->ctrls != 0) ||
69170728a38Smrg                (xkb->names && (xkb->names->indicators[i] != None))) {
69270728a38Smrg                char *name;
69370728a38Smrg
69470728a38Smrg                if (xkb->names && xkb->names->indicators[i] != None) {
69570728a38Smrg                    name = XkbAtomGetString(dpy, xkb->names->indicators[i]);
69670728a38Smrg                }
69770728a38Smrg                else
69870728a38Smrg                    name = NULL;
69970728a38Smrg                size += xkmSizeCountedString(name);
70070728a38Smrg                size += SIZEOF(xkmIndicatorMapDesc);
70170728a38Smrg                nLEDs++;
70270728a38Smrg            }
70370728a38Smrg        }
7048c9fbc29Smrg    }
70570728a38Smrg    info->num_leds = nLEDs;
70670728a38Smrg    toc->type = XkmIndicatorsIndex;
70770728a38Smrg    toc->format = MSBFirst;
70870728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
70970728a38Smrg    toc->offset = (*offset_inout);
71070728a38Smrg    (*offset_inout) += toc->size;
7118c9fbc29Smrg    return 1;
7128c9fbc29Smrg}
7138c9fbc29Smrg
7148c9fbc29Smrgstatic unsigned
71570728a38SmrgWriteXKMIndicators(FILE *file, XkbFileInfo *result, XkmInfo *info)
7168c9fbc29Smrg{
71770728a38Smrg    Display *dpy;
71870728a38Smrg    XkbDescPtr xkb;
71970728a38Smrg    register unsigned i;
72070728a38Smrg    xkmIndicatorMapDesc wire;
72170728a38Smrg    unsigned tmp, size = 0;
72270728a38Smrg
72370728a38Smrg    xkb = result->xkb;
72470728a38Smrg    dpy = xkb->dpy;
72570728a38Smrg    size += xkmPutCARD8(file, info->num_leds);
72670728a38Smrg    size += xkmPutPadding(file, 3);
72770728a38Smrg    size += xkmPutCARD32(file, xkb->indicators->phys_indicators);
72870728a38Smrg    if (xkb->indicators != NULL) {
72970728a38Smrg        for (i = 0; i < XkbNumIndicators; i++) {
73070728a38Smrg            XkbIndicatorMapPtr map = &xkb->indicators->maps[i];
73170728a38Smrg
73270728a38Smrg            if ((map->flags != 0) || (map->which_groups != 0) ||
73370728a38Smrg                (map->groups != 0) || (map->which_mods != 0) ||
73470728a38Smrg                (map->mods.real_mods != 0) || (map->mods.vmods != 0) ||
73570728a38Smrg                (map->ctrls != 0) || (xkb->names &&
73670728a38Smrg                                      (xkb->names->indicators[i] != None))) {
73770728a38Smrg                char *name;
73870728a38Smrg
73970728a38Smrg                if (xkb->names && xkb->names->indicators[i] != None) {
74070728a38Smrg                    name = XkbAtomGetString(dpy, xkb->names->indicators[i]);
74170728a38Smrg                }
74270728a38Smrg                else
74370728a38Smrg                    name = NULL;
74470728a38Smrg                size += xkmPutCountedString(file, name);
74570728a38Smrg                wire.indicator = i + 1;
74670728a38Smrg                wire.flags = map->flags;
74770728a38Smrg                wire.which_mods = map->which_mods;
74870728a38Smrg                wire.real_mods = map->mods.real_mods;
74970728a38Smrg                wire.vmods = map->mods.vmods;
75070728a38Smrg                wire.which_groups = map->which_groups;
75170728a38Smrg                wire.groups = map->groups;
75270728a38Smrg                wire.ctrls = map->ctrls;
75370728a38Smrg                tmp = fwrite(&wire, SIZEOF(xkmIndicatorMapDesc), 1, file);
75470728a38Smrg                size += tmp * SIZEOF(xkmIndicatorMapDesc);
75570728a38Smrg            }
75670728a38Smrg        }
7578c9fbc29Smrg    }
7588c9fbc29Smrg    return size;
7598c9fbc29Smrg}
7608c9fbc29Smrg
7618c9fbc29Smrg/***====================================================================***/
7628c9fbc29Smrg
7638c9fbc29Smrgstatic unsigned
76470728a38SmrgSizeXKMGeomDoodad(XkbFileInfo *result, XkbDoodadPtr doodad)
7658c9fbc29Smrg{
76670728a38Smrg    unsigned size;
7678c9fbc29Smrg
76870728a38Smrg    size = SIZEOF(xkmAnyDoodadDesc);
76970728a38Smrg    size += xkmSizeCountedAtomString(result->xkb->dpy, doodad->any.name);
77070728a38Smrg    if (doodad->any.type == XkbTextDoodad) {
77170728a38Smrg        size += xkmSizeCountedString(doodad->text.text);
77270728a38Smrg        size += xkmSizeCountedString(doodad->text.font);
7738c9fbc29Smrg    }
77470728a38Smrg    else if (doodad->any.type == XkbLogoDoodad) {
77570728a38Smrg        size += xkmSizeCountedString(doodad->logo.logo_name);
7768c9fbc29Smrg    }
7778c9fbc29Smrg    return size;
7788c9fbc29Smrg}
7798c9fbc29Smrg
7808c9fbc29Smrgstatic unsigned
78170728a38SmrgSizeXKMGeomSection(XkbFileInfo *result, XkbSectionPtr section)
7828c9fbc29Smrg{
78370728a38Smrg    register int i;
78470728a38Smrg    unsigned size;
7858c9fbc29Smrg
78670728a38Smrg    size = SIZEOF(xkmSectionDesc);
78770728a38Smrg    size += xkmSizeCountedAtomString(result->xkb->dpy, section->name);
7888c9fbc29Smrg    if (section->rows) {
78970728a38Smrg        XkbRowPtr row;
79070728a38Smrg
79170728a38Smrg        for (row = section->rows, i = 0; i < section->num_rows; i++, row++) {
79270728a38Smrg            size += SIZEOF(xkmRowDesc);
79370728a38Smrg            size += row->num_keys * SIZEOF(xkmKeyDesc);
79470728a38Smrg        }
7958c9fbc29Smrg    }
7968c9fbc29Smrg    if (section->doodads) {
79770728a38Smrg        XkbDoodadPtr doodad;
79870728a38Smrg
79970728a38Smrg        for (doodad = section->doodads, i = 0; i < section->num_doodads;
80070728a38Smrg             i++, doodad++) {
80170728a38Smrg            size += SizeXKMGeomDoodad(result, doodad);
80270728a38Smrg        }
8038c9fbc29Smrg    }
8048c9fbc29Smrg    if (section->overlays) {
80570728a38Smrg        XkbOverlayPtr ol;
80670728a38Smrg
80770728a38Smrg        for (ol = section->overlays, i = 0; i < section->num_overlays;
80870728a38Smrg             i++, ol++) {
80970728a38Smrg            register int r;
81070728a38Smrg            XkbOverlayRowPtr row;
81170728a38Smrg
81270728a38Smrg            size += xkmSizeCountedAtomString(result->xkb->dpy, ol->name);
81370728a38Smrg            size += SIZEOF(xkmOverlayDesc);
81470728a38Smrg            for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
81570728a38Smrg                size += SIZEOF(xkmOverlayRowDesc);
81670728a38Smrg                size += row->num_keys * SIZEOF(xkmOverlayKeyDesc);
81770728a38Smrg            }
81870728a38Smrg        }
8198c9fbc29Smrg    }
8208c9fbc29Smrg    return size;
8218c9fbc29Smrg}
8228c9fbc29Smrg
8238c9fbc29Smrgstatic unsigned
82470728a38SmrgSizeXKMGeometry(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout)
8258c9fbc29Smrg{
82670728a38Smrg    register int i;
82770728a38Smrg    Display *dpy;
82870728a38Smrg    XkbDescPtr xkb;
82970728a38Smrg    XkbGeometryPtr geom;
83070728a38Smrg    unsigned size;
83170728a38Smrg
83270728a38Smrg    xkb = result->xkb;
83370728a38Smrg    if ((!xkb) || (!xkb->geom))
83470728a38Smrg        return 0;
83570728a38Smrg    dpy = xkb->dpy;
83670728a38Smrg    geom = xkb->geom;
83770728a38Smrg    size = xkmSizeCountedAtomString(dpy, geom->name);
83870728a38Smrg    size += SIZEOF(xkmGeometryDesc);
83970728a38Smrg    size += xkmSizeCountedString(geom->label_font);
8408c9fbc29Smrg    if (geom->properties) {
84170728a38Smrg        XkbPropertyPtr prop;
84270728a38Smrg
84370728a38Smrg        for (i = 0, prop = geom->properties; i < geom->num_properties;
84470728a38Smrg             i++, prop++) {
84570728a38Smrg            size += xkmSizeCountedString(prop->name);
84670728a38Smrg            size += xkmSizeCountedString(prop->value);
84770728a38Smrg        }
8488c9fbc29Smrg    }
8498c9fbc29Smrg    if (geom->colors) {
85070728a38Smrg        XkbColorPtr color;
85170728a38Smrg
85270728a38Smrg        for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
85370728a38Smrg            size += xkmSizeCountedString(color->spec);
85470728a38Smrg        }
8558c9fbc29Smrg    }
8568c9fbc29Smrg    if (geom->shapes) {
85770728a38Smrg        XkbShapePtr shape;
85870728a38Smrg
85970728a38Smrg        for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
86070728a38Smrg            register int n;
86170728a38Smrg            register XkbOutlinePtr ol;
86270728a38Smrg
86370728a38Smrg            size += xkmSizeCountedAtomString(dpy, shape->name);
86470728a38Smrg            size += SIZEOF(xkmShapeDesc);
86570728a38Smrg            for (n = 0, ol = shape->outlines; n < shape->num_outlines;
86670728a38Smrg                 n++, ol++) {
86770728a38Smrg                size += SIZEOF(xkmOutlineDesc);
86870728a38Smrg                size += ol->num_points * SIZEOF(xkmPointDesc);
86970728a38Smrg            }
87070728a38Smrg        }
8718c9fbc29Smrg    }
8728c9fbc29Smrg    if (geom->sections) {
87370728a38Smrg        XkbSectionPtr section;
87470728a38Smrg
87570728a38Smrg        for (i = 0, section = geom->sections; i < geom->num_sections;
87670728a38Smrg             i++, section++) {
87770728a38Smrg            size += SizeXKMGeomSection(result, section);
87870728a38Smrg        }
8798c9fbc29Smrg    }
88070728a38Smrg    if (geom->doodads) {
88170728a38Smrg        XkbDoodadPtr doodad;
88270728a38Smrg
88370728a38Smrg        for (i = 0, doodad = geom->doodads; i < geom->num_doodads;
88470728a38Smrg             i++, doodad++) {
88570728a38Smrg            size += SizeXKMGeomDoodad(result, doodad);
88670728a38Smrg        }
8878c9fbc29Smrg    }
8888c9fbc29Smrg    if (geom->key_aliases) {
88970728a38Smrg        size += geom->num_key_aliases * (XkbKeyNameLength * 2);
8908c9fbc29Smrg    }
89170728a38Smrg    toc->type = XkmGeometryIndex;
89270728a38Smrg    toc->format = MSBFirst;
89370728a38Smrg    toc->size = size + SIZEOF(xkmSectionInfo);
89470728a38Smrg    toc->offset = (*offset_inout);
89570728a38Smrg    (*offset_inout) += toc->size;
8968c9fbc29Smrg    return 1;
8978c9fbc29Smrg}
8988c9fbc29Smrg
8998c9fbc29Smrgstatic unsigned
90070728a38SmrgWriteXKMGeomDoodad(FILE *file, XkbFileInfo *result, XkbDoodadPtr doodad)
9018c9fbc29Smrg{
90270728a38Smrg    Display *dpy;
90370728a38Smrg    XkbDescPtr xkb;
90470728a38Smrg    xkmDoodadDesc doodadWire;
90570728a38Smrg    unsigned tmp, size = 0;
90670728a38Smrg
90770728a38Smrg    xkb = result->xkb;
90870728a38Smrg    dpy = xkb->dpy;
90970728a38Smrg    bzero((char *) &doodadWire, sizeof(doodadWire));
91070728a38Smrg    doodadWire.any.type = doodad->any.type;
91170728a38Smrg    doodadWire.any.priority = doodad->any.priority;
91270728a38Smrg    doodadWire.any.top = doodad->any.top;
91370728a38Smrg    doodadWire.any.left = doodad->any.left;
9148c9fbc29Smrg    switch (doodad->any.type) {
91570728a38Smrg    case XkbOutlineDoodad:
91670728a38Smrg    case XkbSolidDoodad:
91770728a38Smrg        doodadWire.shape.angle = doodad->shape.angle;
91870728a38Smrg        doodadWire.shape.color_ndx = doodad->shape.color_ndx;
91970728a38Smrg        doodadWire.shape.shape_ndx = doodad->shape.shape_ndx;
92070728a38Smrg        break;
92170728a38Smrg    case XkbTextDoodad:
92270728a38Smrg        doodadWire.text.angle = doodad->text.angle;
92370728a38Smrg        doodadWire.text.width = doodad->text.width;
92470728a38Smrg        doodadWire.text.height = doodad->text.height;
92570728a38Smrg        doodadWire.text.color_ndx = doodad->text.color_ndx;
92670728a38Smrg        break;
92770728a38Smrg    case XkbIndicatorDoodad:
92870728a38Smrg        doodadWire.indicator.shape_ndx = doodad->indicator.shape_ndx;
92970728a38Smrg        doodadWire.indicator.on_color_ndx = doodad->indicator.on_color_ndx;
93070728a38Smrg        doodadWire.indicator.off_color_ndx = doodad->indicator.off_color_ndx;
93170728a38Smrg        break;
93270728a38Smrg    case XkbLogoDoodad:
93370728a38Smrg        doodadWire.logo.angle = doodad->logo.angle;
93470728a38Smrg        doodadWire.logo.color_ndx = doodad->logo.color_ndx;
93570728a38Smrg        doodadWire.logo.shape_ndx = doodad->logo.shape_ndx;
93670728a38Smrg        break;
93770728a38Smrg    default:
93870728a38Smrg        _XkbLibError(_XkbErrIllegalDoodad, "WriteXKMGeomDoodad",
93970728a38Smrg                     doodad->any.type);
94070728a38Smrg        return 0;
9418c9fbc29Smrg    }
94270728a38Smrg    size += xkmPutCountedAtomString(dpy, file, doodad->any.name);
94370728a38Smrg    tmp = fwrite(&doodadWire, SIZEOF(xkmDoodadDesc), 1, file);
94470728a38Smrg    size += tmp * SIZEOF(xkmDoodadDesc);
94570728a38Smrg    if (doodad->any.type == XkbTextDoodad) {
94670728a38Smrg        size += xkmPutCountedString(file, doodad->text.text);
94770728a38Smrg        size += xkmPutCountedString(file, doodad->text.font);
9488c9fbc29Smrg    }
94970728a38Smrg    else if (doodad->any.type == XkbLogoDoodad) {
95070728a38Smrg        size += xkmPutCountedString(file, doodad->logo.logo_name);
9518c9fbc29Smrg    }
9528c9fbc29Smrg    return size;
9538c9fbc29Smrg}
9548c9fbc29Smrg
9558c9fbc29Smrgstatic unsigned
95670728a38SmrgWriteXKMGeomOverlay(FILE *file, XkbFileInfo *result, XkbOverlayPtr ol)
9578c9fbc29Smrg{
95870728a38Smrg    register int r, k;
95970728a38Smrg    Display *dpy;
96070728a38Smrg    XkbDescPtr xkb;
96170728a38Smrg    XkbOverlayRowPtr row;
96270728a38Smrg    xkmOverlayDesc olWire;
96370728a38Smrg    xkmOverlayRowDesc rowWire;
96470728a38Smrg    xkmOverlayKeyDesc keyWire;
96570728a38Smrg    unsigned tmp, size = 0;
96670728a38Smrg
96770728a38Smrg    xkb = result->xkb;
96870728a38Smrg    dpy = xkb->dpy;
96970728a38Smrg    bzero((char *) &olWire, sizeof(olWire));
97070728a38Smrg    bzero((char *) &rowWire, sizeof(rowWire));
97170728a38Smrg    bzero((char *) &keyWire, sizeof(keyWire));
97270728a38Smrg    size += xkmPutCountedAtomString(dpy, file, ol->name);
97370728a38Smrg    olWire.num_rows = ol->num_rows;
97470728a38Smrg    tmp = fwrite(&olWire, SIZEOF(xkmOverlayDesc), 1, file);
97570728a38Smrg    size += tmp * SIZEOF(xkmOverlayDesc);
97670728a38Smrg    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
97770728a38Smrg        XkbOverlayKeyPtr key;
97870728a38Smrg
97970728a38Smrg        rowWire.row_under = row->row_under;
98070728a38Smrg        rowWire.num_keys = row->num_keys;
98170728a38Smrg        tmp = fwrite(&rowWire, SIZEOF(xkmOverlayRowDesc), 1, file);
98270728a38Smrg        size += tmp * SIZEOF(xkmOverlayRowDesc);
98370728a38Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
98470728a38Smrg            memcpy(keyWire.over, key->over.name, XkbKeyNameLength);
98570728a38Smrg            memcpy(keyWire.under, key->under.name, XkbKeyNameLength);
98670728a38Smrg            tmp = fwrite(&keyWire, SIZEOF(xkmOverlayKeyDesc), 1, file);
98770728a38Smrg            size += tmp * SIZEOF(xkmOverlayKeyDesc);
98870728a38Smrg        }
9898c9fbc29Smrg    }
9904cd6a3aeSmrg    return size;
9918c9fbc29Smrg}
9928c9fbc29Smrg
9938c9fbc29Smrgstatic unsigned
99470728a38SmrgWriteXKMGeomSection(FILE *file, XkbFileInfo *result, XkbSectionPtr section)
9958c9fbc29Smrg{
99670728a38Smrg    register int i;
99770728a38Smrg    Display *dpy;
99870728a38Smrg    XkbDescPtr xkb;
99970728a38Smrg    xkmSectionDesc sectionWire;
100070728a38Smrg    unsigned tmp, size = 0;
100170728a38Smrg
100270728a38Smrg    xkb = result->xkb;
100370728a38Smrg    dpy = xkb->dpy;
100470728a38Smrg    size += xkmPutCountedAtomString(dpy, file, section->name);
100570728a38Smrg    sectionWire.top = section->top;
100670728a38Smrg    sectionWire.left = section->left;
100770728a38Smrg    sectionWire.width = section->width;
100870728a38Smrg    sectionWire.height = section->height;
100970728a38Smrg    sectionWire.angle = section->angle;
101070728a38Smrg    sectionWire.priority = section->priority;
101170728a38Smrg    sectionWire.num_rows = section->num_rows;
101270728a38Smrg    sectionWire.num_doodads = section->num_doodads;
101370728a38Smrg    sectionWire.num_overlays = section->num_overlays;
101470728a38Smrg    tmp = fwrite(&sectionWire, SIZEOF(xkmSectionDesc), 1, file);
101570728a38Smrg    size += tmp * SIZEOF(xkmSectionDesc);
10168c9fbc29Smrg    if (section->rows) {
101770728a38Smrg        register unsigned k;
101870728a38Smrg        XkbRowPtr row;
101970728a38Smrg        xkmRowDesc rowWire;
102070728a38Smrg        XkbKeyPtr key;
102170728a38Smrg        xkmKeyDesc keyWire;
102270728a38Smrg
102370728a38Smrg        for (i = 0, row = section->rows; i < section->num_rows; i++, row++) {
102470728a38Smrg            rowWire.top = row->top;
102570728a38Smrg            rowWire.left = row->left;
102670728a38Smrg            rowWire.num_keys = row->num_keys;
102770728a38Smrg            rowWire.vertical = row->vertical;
102870728a38Smrg            tmp = fwrite(&rowWire, SIZEOF(xkmRowDesc), 1, file);
102970728a38Smrg            size += tmp * SIZEOF(xkmRowDesc);
103070728a38Smrg            for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
103170728a38Smrg                memcpy(keyWire.name, key->name.name, XkbKeyNameLength);
103270728a38Smrg                keyWire.gap = key->gap;
103370728a38Smrg                keyWire.shape_ndx = key->shape_ndx;
103470728a38Smrg                keyWire.color_ndx = key->color_ndx;
103570728a38Smrg                tmp = fwrite(&keyWire, SIZEOF(xkmKeyDesc), 1, file);
103670728a38Smrg                size += tmp * SIZEOF(xkmKeyDesc);
103770728a38Smrg            }
103870728a38Smrg        }
10398c9fbc29Smrg    }
10408c9fbc29Smrg    if (section->doodads) {
104170728a38Smrg        XkbDoodadPtr doodad;
104270728a38Smrg
104370728a38Smrg        for (i = 0, doodad = section->doodads; i < section->num_doodads;
104470728a38Smrg             i++, doodad++) {
104570728a38Smrg            size += WriteXKMGeomDoodad(file, result, doodad);
104670728a38Smrg        }
10478c9fbc29Smrg    }
10488c9fbc29Smrg    if (section->overlays) {
104970728a38Smrg        XkbOverlayPtr ol;
105070728a38Smrg
105170728a38Smrg        for (i = 0, ol = section->overlays; i < section->num_overlays;
105270728a38Smrg             i++, ol++) {
105370728a38Smrg            size += WriteXKMGeomOverlay(file, result, ol);
105470728a38Smrg        }
10558c9fbc29Smrg    }
10568c9fbc29Smrg    return size;
10578c9fbc29Smrg}
10588c9fbc29Smrg
10598c9fbc29Smrgstatic unsigned
106070728a38SmrgWriteXKMGeometry(FILE *file, XkbFileInfo *result)
10618c9fbc29Smrg{
106270728a38Smrg    register int i;
106370728a38Smrg    Display *dpy;
106470728a38Smrg    XkbDescPtr xkb;
106570728a38Smrg    XkbGeometryPtr geom;
106670728a38Smrg    xkmGeometryDesc wire;
106770728a38Smrg    unsigned tmp, size = 0;
106870728a38Smrg
106970728a38Smrg    xkb = result->xkb;
107070728a38Smrg    if ((!xkb) || (!xkb->geom))
107170728a38Smrg        return 0;
107270728a38Smrg    dpy = xkb->dpy;
107370728a38Smrg    geom = xkb->geom;
107470728a38Smrg    wire.width_mm = geom->width_mm;
107570728a38Smrg    wire.height_mm = geom->height_mm;
107670728a38Smrg    wire.base_color_ndx = XkbGeomColorIndex(geom, geom->base_color);
107770728a38Smrg    wire.label_color_ndx = XkbGeomColorIndex(geom, geom->label_color);
107870728a38Smrg    wire.num_properties = geom->num_properties;
107970728a38Smrg    wire.num_colors = geom->num_colors;
108070728a38Smrg    wire.num_shapes = geom->num_shapes;
108170728a38Smrg    wire.num_sections = geom->num_sections;
108270728a38Smrg    wire.num_doodads = geom->num_doodads;
108370728a38Smrg    wire.num_key_aliases = geom->num_key_aliases;
108470728a38Smrg    size += xkmPutCountedAtomString(dpy, file, geom->name);
108570728a38Smrg    tmp = fwrite(&wire, SIZEOF(xkmGeometryDesc), 1, file);
108670728a38Smrg    size += tmp * SIZEOF(xkmGeometryDesc);
108770728a38Smrg    size += xkmPutCountedString(file, geom->label_font);
10888c9fbc29Smrg    if (geom->properties) {
108970728a38Smrg        XkbPropertyPtr prop;
109070728a38Smrg
109170728a38Smrg        for (i = 0, prop = geom->properties; i < geom->num_properties;
109270728a38Smrg             i++, prop++) {
109370728a38Smrg            size += xkmPutCountedString(file, prop->name);
109470728a38Smrg            size += xkmPutCountedString(file, prop->value);
109570728a38Smrg        }
10968c9fbc29Smrg    }
10978c9fbc29Smrg    if (geom->colors) {
109870728a38Smrg        XkbColorPtr color;
109970728a38Smrg
110070728a38Smrg        for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
110170728a38Smrg            size += xkmPutCountedString(file, color->spec);
110270728a38Smrg        }
11038c9fbc29Smrg    }
11048c9fbc29Smrg    if (geom->shapes) {
110570728a38Smrg        XkbShapePtr shape;
110670728a38Smrg        xkmShapeDesc shapeWire;
110770728a38Smrg
110870728a38Smrg        for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
110970728a38Smrg            register int n;
111070728a38Smrg            XkbOutlinePtr ol;
111170728a38Smrg            xkmOutlineDesc olWire;
111270728a38Smrg
111370728a38Smrg            bzero((char *) &shapeWire, sizeof(xkmShapeDesc));
111470728a38Smrg            size += xkmPutCountedAtomString(dpy, file, shape->name);
111570728a38Smrg            shapeWire.num_outlines = shape->num_outlines;
111670728a38Smrg            if (shape->primary != NULL)
111770728a38Smrg                shapeWire.primary_ndx = XkbOutlineIndex(shape, shape->primary);
111870728a38Smrg            else
111970728a38Smrg                shapeWire.primary_ndx = XkbNoShape;
112070728a38Smrg            if (shape->approx != NULL)
112170728a38Smrg                shapeWire.approx_ndx = XkbOutlineIndex(shape, shape->approx);
112270728a38Smrg            else
112370728a38Smrg                shapeWire.approx_ndx = XkbNoShape;
112470728a38Smrg            tmp = fwrite(&shapeWire, SIZEOF(xkmShapeDesc), 1, file);
112570728a38Smrg            size += tmp * SIZEOF(xkmShapeDesc);
112670728a38Smrg            for (n = 0, ol = shape->outlines; n < shape->num_outlines;
112770728a38Smrg                 n++, ol++) {
112870728a38Smrg                register int p;
112970728a38Smrg                XkbPointPtr pt;
113070728a38Smrg                xkmPointDesc ptWire;
113170728a38Smrg
113270728a38Smrg                olWire.num_points = ol->num_points;
113370728a38Smrg                olWire.corner_radius = ol->corner_radius;
113470728a38Smrg                tmp = fwrite(&olWire, SIZEOF(xkmOutlineDesc), 1, file);
113570728a38Smrg                size += tmp * SIZEOF(xkmOutlineDesc);
113670728a38Smrg                for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
113770728a38Smrg                    ptWire.x = pt->x;
113870728a38Smrg                    ptWire.y = pt->y;
113970728a38Smrg                    tmp = fwrite(&ptWire, SIZEOF(xkmPointDesc), 1, file);
114070728a38Smrg                    size += tmp * SIZEOF(xkmPointDesc);
114170728a38Smrg                }
114270728a38Smrg            }
114370728a38Smrg        }
11448c9fbc29Smrg    }
11458c9fbc29Smrg    if (geom->sections) {
114670728a38Smrg        XkbSectionPtr section;
114770728a38Smrg
114870728a38Smrg        for (i = 0, section = geom->sections; i < geom->num_sections;
114970728a38Smrg             i++, section++) {
115070728a38Smrg            size += WriteXKMGeomSection(file, result, section);
115170728a38Smrg        }
11528c9fbc29Smrg    }
11538c9fbc29Smrg    if (geom->doodads) {
115470728a38Smrg        XkbDoodadPtr doodad;
115570728a38Smrg
115670728a38Smrg        for (i = 0, doodad = geom->doodads; i < geom->num_doodads;
115770728a38Smrg             i++, doodad++) {
115870728a38Smrg            size += WriteXKMGeomDoodad(file, result, doodad);
115970728a38Smrg        }
11608c9fbc29Smrg    }
11618c9fbc29Smrg    if (geom->key_aliases) {
116270728a38Smrg        tmp =
116370728a38Smrg            fwrite(geom->key_aliases, 2 * XkbKeyNameLength,
116470728a38Smrg                   geom->num_key_aliases, file);
116570728a38Smrg        size += tmp * (2 * XkbKeyNameLength);
11668c9fbc29Smrg    }
11678c9fbc29Smrg    return size;
11688c9fbc29Smrg}
11698c9fbc29Smrg
11708c9fbc29Smrg/***====================================================================***/
11718c9fbc29Smrg
11728c9fbc29Smrg/*ARGSUSED*/
11738c9fbc29Smrgstatic int
117470728a38SmrgGetXKMKeyNamesTOC(XkbFileInfo *result, XkmInfo *info,
117570728a38Smrg                  int max_toc, xkmSectionInfo *toc_rtrn)
11768c9fbc29Smrg{
117770728a38Smrg    int num_toc;
117870728a38Smrg    int total_size;
117970728a38Smrg
118070728a38Smrg    total_size = num_toc = 0;
118170728a38Smrg    if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size))
118270728a38Smrg        num_toc++;
118370728a38Smrg    if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size))
118470728a38Smrg        num_toc++;
11858c9fbc29Smrg    return num_toc;
11868c9fbc29Smrg}
11878c9fbc29Smrg
11888c9fbc29Smrg/*ARGSUSED*/
11898c9fbc29Smrgstatic int
119070728a38SmrgGetXKMTypesTOC(XkbFileInfo *result, XkmInfo *info,
119170728a38Smrg               int max_toc, xkmSectionInfo *toc_rtrn)
11928c9fbc29Smrg{
119370728a38Smrg    int num_toc;
119470728a38Smrg    int total_size;
119570728a38Smrg
119670728a38Smrg    total_size = num_toc = 0;
119770728a38Smrg    if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size))
119870728a38Smrg        num_toc++;
119970728a38Smrg    if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size))
120070728a38Smrg        num_toc++;
12018c9fbc29Smrg    return num_toc;
12028c9fbc29Smrg}
12038c9fbc29Smrg
12048c9fbc29Smrg/*ARGSUSED*/
12058c9fbc29Smrgstatic int
120670728a38SmrgGetXKMCompatMapTOC(XkbFileInfo *result, XkmInfo *info,
120770728a38Smrg                   int max_toc, xkmSectionInfo *toc_rtrn)
12088c9fbc29Smrg{
120970728a38Smrg    int num_toc;
121070728a38Smrg    int total_size;
121170728a38Smrg
121270728a38Smrg    total_size = num_toc = 0;
121370728a38Smrg    if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size))
121470728a38Smrg        num_toc++;
121570728a38Smrg    if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size))
121670728a38Smrg        num_toc++;
121770728a38Smrg    if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size))
121870728a38Smrg        num_toc++;
12198c9fbc29Smrg    return num_toc;
12208c9fbc29Smrg}
12218c9fbc29Smrg
12228c9fbc29Smrg/*ARGSUSED*/
12238c9fbc29Smrgstatic int
122470728a38SmrgGetXKMSemanticsTOC(XkbFileInfo *result, XkmInfo *info,
122570728a38Smrg                   int max_toc, xkmSectionInfo *toc_rtrn)
12268c9fbc29Smrg{
122770728a38Smrg    int num_toc;
122870728a38Smrg    int total_size;
122970728a38Smrg
123070728a38Smrg    total_size = num_toc = 0;
123170728a38Smrg    if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size))
123270728a38Smrg        num_toc++;
123370728a38Smrg    if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size))
123470728a38Smrg        num_toc++;
123570728a38Smrg    if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size))
123670728a38Smrg        num_toc++;
123770728a38Smrg    if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size))
123870728a38Smrg        num_toc++;
12398c9fbc29Smrg    return num_toc;
12408c9fbc29Smrg}
12418c9fbc29Smrg
12428c9fbc29Smrg/*ARGSUSED*/
12438c9fbc29Smrgstatic int
124470728a38SmrgGetXKMLayoutTOC(XkbFileInfo *result, XkmInfo *info,
124570728a38Smrg                int max_toc, xkmSectionInfo *toc_rtrn)
12468c9fbc29Smrg{
124770728a38Smrg    int num_toc;
124870728a38Smrg    int total_size;
124970728a38Smrg
125070728a38Smrg    total_size = num_toc = 0;
125170728a38Smrg    if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size))
125270728a38Smrg        num_toc++;
125370728a38Smrg    if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size))
125470728a38Smrg        num_toc++;
125570728a38Smrg    if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size))
125670728a38Smrg        num_toc++;
125770728a38Smrg    if (SizeXKMSymbols(result, info, &toc_rtrn[num_toc], &total_size))
125870728a38Smrg        num_toc++;
125970728a38Smrg    if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size))
126070728a38Smrg        num_toc++;
126170728a38Smrg    if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size))
126270728a38Smrg        num_toc++;
12638c9fbc29Smrg    return num_toc;
12648c9fbc29Smrg}
12658c9fbc29Smrg
12668c9fbc29Smrg/*ARGSUSED*/
12678c9fbc29Smrgstatic int
126870728a38SmrgGetXKMKeymapTOC(XkbFileInfo *result, XkmInfo *info,
126970728a38Smrg                int max_toc, xkmSectionInfo *toc_rtrn)
12708c9fbc29Smrg{
127170728a38Smrg    int num_toc;
127270728a38Smrg    int total_size;
127370728a38Smrg
127470728a38Smrg    total_size = num_toc = 0;
127570728a38Smrg    if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size))
127670728a38Smrg        num_toc++;
127770728a38Smrg    if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size))
127870728a38Smrg        num_toc++;
127970728a38Smrg    if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size))
128070728a38Smrg        num_toc++;
128170728a38Smrg    if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size))
128270728a38Smrg        num_toc++;
128370728a38Smrg    if (SizeXKMSymbols(result, info, &toc_rtrn[num_toc], &total_size))
128470728a38Smrg        num_toc++;
128570728a38Smrg    if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size))
128670728a38Smrg        num_toc++;
128770728a38Smrg    if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size))
128870728a38Smrg        num_toc++;
12898c9fbc29Smrg    return num_toc;
12908c9fbc29Smrg}
12918c9fbc29Smrg
12928c9fbc29Smrg/*ARGSUSED*/
12938c9fbc29Smrgstatic int
129470728a38SmrgGetXKMGeometryTOC(XkbFileInfo *result, XkmInfo *info,
129570728a38Smrg                  int max_toc, xkmSectionInfo *toc_rtrn)
12968c9fbc29Smrg{
129770728a38Smrg    int num_toc;
129870728a38Smrg    int total_size;
12998c9fbc29Smrg
130070728a38Smrg    total_size = num_toc = 0;
130170728a38Smrg    if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size))
130270728a38Smrg        num_toc++;
13038c9fbc29Smrg    return num_toc;
13048c9fbc29Smrg}
13058c9fbc29Smrg
13068c9fbc29Smrgstatic Bool
130770728a38SmrgWriteXKMFile(FILE *file, XkbFileInfo *result,
130870728a38Smrg             int num_toc, xkmSectionInfo *toc, XkmInfo *info)
13098c9fbc29Smrg{
131070728a38Smrg    register int i;
131170728a38Smrg    unsigned tmp, size, total = 0;
131270728a38Smrg
131370728a38Smrg    for (i = 0; i < num_toc; i++) {
131470728a38Smrg        tmp = fwrite(&toc[i], SIZEOF(xkmSectionInfo), 1, file);
131570728a38Smrg        total += tmp * SIZEOF(xkmSectionInfo);
131670728a38Smrg        switch (toc[i].type) {
131770728a38Smrg        case XkmTypesIndex:
131870728a38Smrg            size = WriteXKMKeyTypes(file, result);
131970728a38Smrg            break;
132070728a38Smrg        case XkmCompatMapIndex:
132170728a38Smrg            size = WriteXKMCompatMap(file, result, info);
132270728a38Smrg            break;
132370728a38Smrg        case XkmSymbolsIndex:
132470728a38Smrg            size = WriteXKMSymbols(file, result, info);
132570728a38Smrg            break;
132670728a38Smrg        case XkmIndicatorsIndex:
132770728a38Smrg            size = WriteXKMIndicators(file, result, info);
132870728a38Smrg            break;
132970728a38Smrg        case XkmKeyNamesIndex:
133070728a38Smrg            size = WriteXKMKeycodes(file, result);
133170728a38Smrg            break;
133270728a38Smrg        case XkmGeometryIndex:
133370728a38Smrg            size = WriteXKMGeometry(file, result);
133470728a38Smrg            break;
133570728a38Smrg        case XkmVirtualModsIndex:
133670728a38Smrg            size = WriteXKMVirtualMods(file, result, info);
133770728a38Smrg            break;
133870728a38Smrg        default:
133970728a38Smrg            _XkbLibError(_XkbErrIllegalTOCType, "WriteXKMFile", toc[i].type);
134070728a38Smrg            return False;
134170728a38Smrg        }
134270728a38Smrg        size += SIZEOF(xkmSectionInfo);
134370728a38Smrg        if (size != toc[i].size) {
134470728a38Smrg            _XkbLibError(_XkbErrBadLength,
134570728a38Smrg                         XkbConfigText(toc[i].type, XkbMessage),
134670728a38Smrg                         size - toc[i].size);
134770728a38Smrg            return False;
134870728a38Smrg        }
13498c9fbc29Smrg    }
13508c9fbc29Smrg    return True;
13518c9fbc29Smrg}
13528c9fbc29Smrg
13538c9fbc29Smrg
13548c9fbc29Smrg#define	MAX_TOC	16
13558c9fbc29Smrg
13568c9fbc29SmrgBool
135770728a38SmrgXkbWriteXKMFile(FILE *out, XkbFileInfo *result)
13588c9fbc29Smrg{
135970728a38Smrg    Bool ok;
136070728a38Smrg    XkbDescPtr xkb;
136170728a38Smrg    XkmInfo info;
136270728a38Smrg    int size_toc, i;
136370728a38Smrg    unsigned hdr, present;
136470728a38Smrg    xkmFileInfo fileInfo;
136570728a38Smrg    xkmSectionInfo toc[MAX_TOC];
136670728a38Smrg
136770728a38Smrg    int (*getTOC) (XkbFileInfo *        /* result */ ,
136870728a38Smrg                   XkmInfo *            /* info */ ,
136970728a38Smrg                   int                  /* max_to */ ,
137070728a38Smrg                   xkmSectionInfo *     /* toc_rtrn */
137170728a38Smrg        );
13728c9fbc29Smrg
13738c9fbc29Smrg    switch (result->type) {
137470728a38Smrg    case XkmKeyNamesIndex:
137570728a38Smrg        getTOC = GetXKMKeyNamesTOC;
137670728a38Smrg        break;
137770728a38Smrg    case XkmTypesIndex:
137870728a38Smrg        getTOC = GetXKMTypesTOC;
137970728a38Smrg        break;
138070728a38Smrg    case XkmCompatMapIndex:
138170728a38Smrg        getTOC = GetXKMCompatMapTOC;
138270728a38Smrg        break;
138370728a38Smrg    case XkmSemanticsFile:
138470728a38Smrg        getTOC = GetXKMSemanticsTOC;
138570728a38Smrg        break;
138670728a38Smrg    case XkmLayoutFile:
138770728a38Smrg        getTOC = GetXKMLayoutTOC;
138870728a38Smrg        break;
138970728a38Smrg    case XkmKeymapFile:
139070728a38Smrg        getTOC = GetXKMKeymapTOC;
139170728a38Smrg        break;
139270728a38Smrg    case XkmGeometryFile:
139370728a38Smrg    case XkmGeometryIndex:
139470728a38Smrg        getTOC = GetXKMGeometryTOC;
139570728a38Smrg        break;
139670728a38Smrg    default:
139770728a38Smrg        _XkbLibError(_XkbErrIllegalContents,
139870728a38Smrg                     XkbConfigText(result->type, XkbMessage), 0);
139970728a38Smrg        return False;
14008c9fbc29Smrg    }
140170728a38Smrg    xkb = result->xkb;
14028c9fbc29Smrg
140370728a38Smrg    bzero((char *) &info, sizeof(XkmInfo));
140470728a38Smrg    size_toc = (*getTOC) (result, &info, MAX_TOC, toc);
140570728a38Smrg    if (size_toc < 1) {
140670728a38Smrg        _XkbLibError(_XkbErrEmptyFile, "XkbWriteXKMFile", 0);
140770728a38Smrg        return False;
14088c9fbc29Smrg    }
140970728a38Smrg    if (out == NULL) {
141070728a38Smrg        _XkbLibError(_XkbErrFileCannotOpen, "XkbWriteXKMFile", 0);
141170728a38Smrg        return False;
14128c9fbc29Smrg    }
141370728a38Smrg    for (i = present = 0; i < size_toc; i++) {
141470728a38Smrg        toc[i].offset += 4 + SIZEOF(xkmFileInfo);
141570728a38Smrg        toc[i].offset += (size_toc * SIZEOF(xkmSectionInfo));
141670728a38Smrg        if (toc[i].type <= XkmLastIndex) {
141770728a38Smrg            present |= (1 << toc[i].type);
141870728a38Smrg        }
14198c9fbc29Smrg#ifdef DEBUG
142070728a38Smrg        else {
142170728a38Smrg            fprintf(stderr, "Illegal section type %d\n", toc[i].type);
142270728a38Smrg            fprintf(stderr, "Ignored\n");
142370728a38Smrg        }
14248c9fbc29Smrg#endif
14258c9fbc29Smrg    }
142670728a38Smrg    hdr = (('x' << 24) | ('k' << 16) | ('m' << 8) | XkmFileVersion);
142770728a38Smrg    xkmPutCARD32(out, (unsigned long) hdr);
142870728a38Smrg    fileInfo.type = result->type;
142970728a38Smrg    fileInfo.min_kc = xkb->min_key_code;
143070728a38Smrg    fileInfo.max_kc = xkb->max_key_code;
143170728a38Smrg    fileInfo.num_toc = size_toc;
143270728a38Smrg    fileInfo.present = present;
143370728a38Smrg    fileInfo.pad = 0;
143470728a38Smrg    fwrite(&fileInfo, SIZEOF(xkmFileInfo), 1, out);
143570728a38Smrg    fwrite(toc, SIZEOF(xkmSectionInfo), size_toc, out);
143670728a38Smrg    ok = WriteXKMFile(out, result, size_toc, toc, &info);
14378c9fbc29Smrg    return ok;
14388c9fbc29Smrg}
1439