xkmout.c revision 8c9fbc29
18c9fbc29Smrg/* $Xorg: xkmout.c,v 1.3 2000/08/17 19:46:44 cpqbld Exp $ */
28c9fbc29Smrg/************************************************************
38c9fbc29Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
48c9fbc29Smrg
58c9fbc29Smrg Permission to use, copy, modify, and distribute this
68c9fbc29Smrg software and its documentation for any purpose and without
78c9fbc29Smrg fee is hereby granted, provided that the above copyright
88c9fbc29Smrg notice appear in all copies and that both that copyright
98c9fbc29Smrg notice and this permission notice appear in supporting
108c9fbc29Smrg documentation, and that the name of Silicon Graphics not be
118c9fbc29Smrg used in advertising or publicity pertaining to distribution
128c9fbc29Smrg of the software without specific prior written permission.
138c9fbc29Smrg Silicon Graphics makes no representation about the suitability
148c9fbc29Smrg of this software for any purpose. It is provided "as is"
158c9fbc29Smrg without any express or implied warranty.
168c9fbc29Smrg
178c9fbc29Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
188c9fbc29Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
198c9fbc29Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
208c9fbc29Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
218c9fbc29Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
228c9fbc29Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
238c9fbc29Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
248c9fbc29Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
258c9fbc29Smrg
268c9fbc29Smrg ********************************************************/
278c9fbc29Smrg/* $XFree86: xc/lib/xkbfile/xkmout.c,v 1.5 2001/07/25 15:04:58 dawes Exp $ */
288c9fbc29Smrg
298c9fbc29Smrg#ifdef HAVE_CONFIG_H
308c9fbc29Smrg#include <config.h>
318c9fbc29Smrg#endif
328c9fbc29Smrg#include <stdio.h>
338c9fbc29Smrg#include <ctype.h>
348c9fbc29Smrg#include <stdlib.h>
358c9fbc29Smrg#include <X11/Xfuncs.h>
368c9fbc29Smrg#include <X11/Xlib.h>
378c9fbc29Smrg#include <X11/XKBlib.h>
388c9fbc29Smrg#include <X11/extensions/XKBgeom.h>
398c9fbc29Smrg
408c9fbc29Smrg#include "XKMformat.h"
418c9fbc29Smrg#include "XKBfileInt.h"
428c9fbc29Smrg
438c9fbc29Smrgtypedef struct _XkmInfo {
448c9fbc29Smrg     unsigned short	bound_vmods;
458c9fbc29Smrg     unsigned short	named_vmods;
468c9fbc29Smrg     unsigned char	num_bound;
478c9fbc29Smrg     unsigned char	group_compat;
488c9fbc29Smrg     unsigned short	num_group_compat;
498c9fbc29Smrg     unsigned short	num_leds;
508c9fbc29Smrg     int		total_vmodmaps;
518c9fbc29Smrg} XkmInfo;
528c9fbc29Smrg
538c9fbc29Smrg/***====================================================================***/
548c9fbc29Smrg
558c9fbc29Smrg#define	xkmPutCARD8(f,v)	(putc(v,f),1)
568c9fbc29Smrg
578c9fbc29Smrgstatic int
588c9fbc29SmrgxkmPutCARD16(FILE *file,unsigned val)
598c9fbc29Smrg{
608c9fbc29SmrgCARD16	tmp= val;
618c9fbc29Smrg
628c9fbc29Smrg    fwrite(&tmp,2,1,file);
638c9fbc29Smrg    return 2;
648c9fbc29Smrg}
658c9fbc29Smrg
668c9fbc29Smrgstatic int
678c9fbc29SmrgxkmPutCARD32(FILE *file,unsigned long val)
688c9fbc29Smrg{
698c9fbc29SmrgCARD32 tmp= val;
708c9fbc29Smrg
718c9fbc29Smrg    fwrite(&tmp,4,1,file);
728c9fbc29Smrg    return 4;
738c9fbc29Smrg}
748c9fbc29Smrg
758c9fbc29Smrgstatic int
768c9fbc29SmrgxkmPutPadding(FILE *file,unsigned pad)
778c9fbc29Smrg{
788c9fbc29Smrgint	i;
798c9fbc29Smrg    for (i=0;i<pad;i++) {
808c9fbc29Smrg	putc('\0',file);
818c9fbc29Smrg    }
828c9fbc29Smrg    return pad;
838c9fbc29Smrg}
848c9fbc29Smrg
858c9fbc29Smrgstatic int
868c9fbc29SmrgxkmPutCountedBytes(FILE *file,char *ptr,unsigned count)
878c9fbc29Smrg{
888c9fbc29Smrgregister int nOut;
898c9fbc29Smrgregister unsigned pad;
908c9fbc29Smrg
918c9fbc29Smrg    if (count==0)
928c9fbc29Smrg	return xkmPutCARD32(file,(unsigned long)0);
938c9fbc29Smrg
948c9fbc29Smrg    xkmPutCARD16(file,count);
958c9fbc29Smrg    nOut= fwrite(ptr,1,count,file);
968c9fbc29Smrg    if (nOut<0)
978c9fbc29Smrg	return 2;
988c9fbc29Smrg    nOut= count+2;
998c9fbc29Smrg    pad= XkbPaddedSize(nOut)-nOut;
1008c9fbc29Smrg    if (pad)
1018c9fbc29Smrg	xkmPutPadding(file,pad);
1028c9fbc29Smrg    return nOut+pad;
1038c9fbc29Smrg}
1048c9fbc29Smrg
1058c9fbc29Smrgstatic unsigned
1068c9fbc29SmrgxkmSizeCountedString(char *str)
1078c9fbc29Smrg{
1088c9fbc29Smrg    if (str==NULL)
1098c9fbc29Smrg	return 4;
1108c9fbc29Smrg    return XkbPaddedSize(strlen(str)+2);
1118c9fbc29Smrg}
1128c9fbc29Smrg
1138c9fbc29Smrgstatic int
1148c9fbc29SmrgxkmPutCountedString(FILE *file,char *str)
1158c9fbc29Smrg{
1168c9fbc29Smrg    if (str==NULL)
1178c9fbc29Smrg	 return xkmPutCARD32(file,(unsigned long)0);
1188c9fbc29Smrg    return xkmPutCountedBytes(file,str,strlen(str));
1198c9fbc29Smrg}
1208c9fbc29Smrg
1218c9fbc29Smrg#define	xkmSizeCountedAtomString(d,a)	\
1228c9fbc29Smrg	xkmSizeCountedString(XkbAtomGetString((d),(a)))
1238c9fbc29Smrg
1248c9fbc29Smrg#define	xkmPutCountedAtomString(d,f,a)	\
1258c9fbc29Smrg	xkmPutCountedString((f),XkbAtomGetString((d),(a)))
1268c9fbc29Smrg
1278c9fbc29Smrg/***====================================================================***/
1288c9fbc29Smrg
1298c9fbc29Smrgstatic unsigned
1308c9fbc29SmrgSizeXKMVirtualMods(	XkbFileInfo *		result,
1318c9fbc29Smrg			XkmInfo *		info,
1328c9fbc29Smrg			xkmSectionInfo *	toc,
1338c9fbc29Smrg			int *			offset_inout)
1348c9fbc29Smrg{
1358c9fbc29SmrgDisplay *	dpy;
1368c9fbc29SmrgXkbDescPtr	xkb;
1378c9fbc29Smrgunsigned	nBound,bound;
1388c9fbc29Smrgunsigned	nNamed,named,szNames;
1398c9fbc29Smrgregister unsigned	i,bit;
1408c9fbc29Smrg
1418c9fbc29Smrg    xkb= result->xkb;
1428c9fbc29Smrg    dpy= xkb->dpy;
1438c9fbc29Smrg    if ((!xkb)||(!xkb->names)||(!xkb->server)) {
1448c9fbc29Smrg	_XkbLibError(_XkbErrMissingVMods,"SizeXKMVirtualMods",0);
1458c9fbc29Smrg	return 0;
1468c9fbc29Smrg    }
1478c9fbc29Smrg    bound=named=0;
1488c9fbc29Smrg    for (i=nBound=nNamed=szNames=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1498c9fbc29Smrg	if (xkb->server->vmods[i]!=XkbNoModifierMask) {
1508c9fbc29Smrg	    bound|= bit;
1518c9fbc29Smrg	    nBound++;
1528c9fbc29Smrg	}
1538c9fbc29Smrg	if (xkb->names->vmods[i]!=None) {
1548c9fbc29Smrg	    named|= bit;
1558c9fbc29Smrg	    szNames+= xkmSizeCountedAtomString(dpy,xkb->names->vmods[i]);
1568c9fbc29Smrg	    nNamed++;
1578c9fbc29Smrg	}
1588c9fbc29Smrg    }
1598c9fbc29Smrg    info->num_bound= nBound;
1608c9fbc29Smrg    info->bound_vmods= bound;
1618c9fbc29Smrg    info->named_vmods= named;
1628c9fbc29Smrg    if ((nBound==0)&&(nNamed==0))
1638c9fbc29Smrg	return 0;
1648c9fbc29Smrg    toc->type= 		XkmVirtualModsIndex;
1658c9fbc29Smrg    toc->format= 	MSBFirst;
1668c9fbc29Smrg    toc->size= 		4+XkbPaddedSize(nBound)+szNames+SIZEOF(xkmSectionInfo);
1678c9fbc29Smrg    toc->offset= 	*offset_inout;
1688c9fbc29Smrg    (*offset_inout)+= 	toc->size;
1698c9fbc29Smrg    return 1;
1708c9fbc29Smrg}
1718c9fbc29Smrg
1728c9fbc29Smrgstatic unsigned
1738c9fbc29SmrgWriteXKMVirtualMods(FILE *file,XkbFileInfo *result,XkmInfo *info)
1748c9fbc29Smrg{
1758c9fbc29Smrgregister unsigned int i,bit;
1768c9fbc29SmrgXkbDescPtr	xkb;
1778c9fbc29SmrgDisplay *	dpy;
1788c9fbc29Smrgunsigned	size= 0;
1798c9fbc29Smrg
1808c9fbc29Smrg    xkb= result->xkb;
1818c9fbc29Smrg    dpy= xkb->dpy;
1828c9fbc29Smrg    size+= xkmPutCARD16(file,info->bound_vmods);
1838c9fbc29Smrg    size+= xkmPutCARD16(file,info->named_vmods);
1848c9fbc29Smrg    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1858c9fbc29Smrg	if (info->bound_vmods&bit)
1868c9fbc29Smrg	    size+= xkmPutCARD8(file,xkb->server->vmods[i]);
1878c9fbc29Smrg    }
1888c9fbc29Smrg    if ((i= XkbPaddedSize(info->num_bound)-info->num_bound)>0)
1898c9fbc29Smrg	size+= xkmPutPadding(file,i);
1908c9fbc29Smrg    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1918c9fbc29Smrg	if (info->named_vmods&bit) {
1928c9fbc29Smrg	    register char *name;
1938c9fbc29Smrg	    name= XkbAtomGetString(dpy,xkb->names->vmods[i]);
1948c9fbc29Smrg	    size+= xkmPutCountedString(file,name);
1958c9fbc29Smrg	}
1968c9fbc29Smrg    }
1978c9fbc29Smrg    return size;
1988c9fbc29Smrg}
1998c9fbc29Smrg
2008c9fbc29Smrg/***====================================================================***/
2018c9fbc29Smrg
2028c9fbc29Smrgstatic unsigned
2038c9fbc29SmrgSizeXKMKeycodes(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
2048c9fbc29Smrg{
2058c9fbc29SmrgXkbDescPtr	xkb;
2068c9fbc29SmrgAtom		kcName;
2078c9fbc29Smrgint		size=0;
2088c9fbc29SmrgDisplay *	dpy;
2098c9fbc29Smrg
2108c9fbc29Smrg    xkb= result->xkb;
2118c9fbc29Smrg    dpy= xkb->dpy;
2128c9fbc29Smrg    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
2138c9fbc29Smrg	_XkbLibError(_XkbErrMissingNames,"SizeXKMKeycodes",0);
2148c9fbc29Smrg	return 0;
2158c9fbc29Smrg    }
2168c9fbc29Smrg    kcName= xkb->names->keycodes;
2178c9fbc29Smrg    size+= 4;	/* min and max keycode */
2188c9fbc29Smrg    size+= xkmSizeCountedAtomString(dpy,kcName);
2198c9fbc29Smrg    size+= XkbNumKeys(xkb)*sizeof(XkbKeyNameRec);
2208c9fbc29Smrg    if (xkb->names->num_key_aliases>0) {
2218c9fbc29Smrg	if (xkb->names->key_aliases!=NULL)
2228c9fbc29Smrg	     size+= xkb->names->num_key_aliases*sizeof(XkbKeyAliasRec);
2238c9fbc29Smrg	else xkb->names->num_key_aliases= 0;
2248c9fbc29Smrg    }
2258c9fbc29Smrg    toc->type= 		XkmKeyNamesIndex;
2268c9fbc29Smrg    toc->format= 	MSBFirst;
2278c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
2288c9fbc29Smrg    toc->offset= 	(*offset_inout);
2298c9fbc29Smrg    (*offset_inout)+= 	toc->size;
2308c9fbc29Smrg    return 1;
2318c9fbc29Smrg}
2328c9fbc29Smrg
2338c9fbc29Smrgstatic unsigned
2348c9fbc29SmrgWriteXKMKeycodes(FILE *file,XkbFileInfo *result)
2358c9fbc29Smrg{
2368c9fbc29SmrgXkbDescPtr	xkb;
2378c9fbc29SmrgAtom	 	kcName;
2388c9fbc29Smrgchar 		*start;
2398c9fbc29SmrgDisplay *	dpy;
2408c9fbc29Smrgunsigned	tmp,size= 0;
2418c9fbc29Smrg
2428c9fbc29Smrg    xkb= result->xkb;
2438c9fbc29Smrg    dpy= xkb->dpy;
2448c9fbc29Smrg    kcName= xkb->names->keycodes;
2458c9fbc29Smrg    start= xkb->names->keys[xkb->min_key_code].name;
2468c9fbc29Smrg
2478c9fbc29Smrg    size+= xkmPutCountedString(file,XkbAtomGetString(dpy,kcName));
2488c9fbc29Smrg    size+= xkmPutCARD8(file,xkb->min_key_code);
2498c9fbc29Smrg    size+= xkmPutCARD8(file,xkb->max_key_code);
2508c9fbc29Smrg    size+= xkmPutCARD8(file,xkb->names->num_key_aliases);
2518c9fbc29Smrg    size+= xkmPutPadding(file,1);
2528c9fbc29Smrg    tmp= fwrite(start,sizeof(XkbKeyNameRec),XkbNumKeys(xkb),file);
2538c9fbc29Smrg    size+= tmp*sizeof(XkbKeyNameRec);
2548c9fbc29Smrg    if (xkb->names->num_key_aliases>0) {
2558c9fbc29Smrg	tmp= fwrite((char *)xkb->names->key_aliases,
2568c9fbc29Smrg			sizeof(XkbKeyAliasRec),xkb->names->num_key_aliases,
2578c9fbc29Smrg			file);
2588c9fbc29Smrg	size+= tmp*sizeof(XkbKeyAliasRec);
2598c9fbc29Smrg    }
2608c9fbc29Smrg    return size;
2618c9fbc29Smrg}
2628c9fbc29Smrg
2638c9fbc29Smrg/***====================================================================***/
2648c9fbc29Smrg
2658c9fbc29Smrgstatic unsigned
2668c9fbc29SmrgSizeXKMKeyTypes(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
2678c9fbc29Smrg{
2688c9fbc29Smrgregister unsigned	i,n,size;
2698c9fbc29SmrgXkbKeyTypePtr		type;
2708c9fbc29SmrgXkbDescPtr		xkb;
2718c9fbc29SmrgDisplay *		dpy;
2728c9fbc29Smrgchar *			name;
2738c9fbc29Smrg
2748c9fbc29Smrg    xkb= result->xkb;
2758c9fbc29Smrg    dpy= xkb->dpy;
2768c9fbc29Smrg    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
2778c9fbc29Smrg	_XkbLibError(_XkbErrMissingTypes,"SizeXKBKeyTypes",0);
2788c9fbc29Smrg	return 0;
2798c9fbc29Smrg    }
2808c9fbc29Smrg    if (xkb->map->num_types<XkbNumRequiredTypes) {
2818c9fbc29Smrg	_XkbLibError(_XkbErrMissingReqTypes,"SizeXKBKeyTypes",0);
2828c9fbc29Smrg	return 0;
2838c9fbc29Smrg    }
2848c9fbc29Smrg    if (xkb->names)	name= XkbAtomGetString(dpy,xkb->names->types);
2858c9fbc29Smrg    else		name= NULL;
2868c9fbc29Smrg    size= xkmSizeCountedString(name);
2878c9fbc29Smrg    size+= 4;	/* room for # of key types + padding */
2888c9fbc29Smrg    for (i=0,type=xkb->map->types;i<xkb->map->num_types;i++,type++) {
2898c9fbc29Smrg	size+= SIZEOF(xkmKeyTypeDesc);
2908c9fbc29Smrg	size+= SIZEOF(xkmKTMapEntryDesc)*type->map_count;
2918c9fbc29Smrg	size+= xkmSizeCountedAtomString(dpy,type->name);
2928c9fbc29Smrg	if (type->preserve)
2938c9fbc29Smrg	    size+= SIZEOF(xkmModsDesc)*type->map_count;
2948c9fbc29Smrg	if (type->level_names) {
2958c9fbc29Smrg	    Atom *names;
2968c9fbc29Smrg	    names= type->level_names;
2978c9fbc29Smrg	    for (n=0;n<(unsigned)type->num_levels;n++) {
2988c9fbc29Smrg		size+= xkmSizeCountedAtomString(dpy,names[n]);
2998c9fbc29Smrg	    }
3008c9fbc29Smrg	}
3018c9fbc29Smrg    }
3028c9fbc29Smrg    toc->type= 		XkmTypesIndex;
3038c9fbc29Smrg    toc->format= 	MSBFirst;
3048c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
3058c9fbc29Smrg    toc->offset= 	(*offset_inout);
3068c9fbc29Smrg    (*offset_inout)+= 	toc->size;
3078c9fbc29Smrg    return 1;
3088c9fbc29Smrg}
3098c9fbc29Smrg
3108c9fbc29Smrgstatic unsigned
3118c9fbc29SmrgWriteXKMKeyTypes(FILE *file,XkbFileInfo *result)
3128c9fbc29Smrg{
3138c9fbc29Smrgregister unsigned	i,n;
3148c9fbc29SmrgXkbDescPtr		xkb;
3158c9fbc29SmrgXkbKeyTypePtr		type;
3168c9fbc29SmrgxkmKeyTypeDesc		wire;
3178c9fbc29SmrgXkbKTMapEntryPtr	entry;
3188c9fbc29SmrgxkmKTMapEntryDesc	wire_entry;
3198c9fbc29SmrgAtom *			names;
3208c9fbc29SmrgDisplay *		dpy;
3218c9fbc29Smrgunsigned		tmp,size= 0;
3228c9fbc29Smrgchar *			name;
3238c9fbc29Smrg
3248c9fbc29Smrg    xkb= result->xkb;
3258c9fbc29Smrg    dpy= xkb->dpy;
3268c9fbc29Smrg    if (xkb->names)	name= XkbAtomGetString(dpy,xkb->names->types);
3278c9fbc29Smrg    else		name= NULL;
3288c9fbc29Smrg    size+= xkmPutCountedString(file,name);
3298c9fbc29Smrg    size+= xkmPutCARD16(file,xkb->map->num_types);
3308c9fbc29Smrg    size+= xkmPutPadding(file,2);
3318c9fbc29Smrg    type= xkb->map->types;
3328c9fbc29Smrg    for (i=0;i<xkb->map->num_types;i++,type++) {
3338c9fbc29Smrg	wire.realMods= type->mods.real_mods;
3348c9fbc29Smrg	wire.virtualMods= type->mods.vmods;
3358c9fbc29Smrg	wire.numLevels= type->num_levels;
3368c9fbc29Smrg	wire.nMapEntries= type->map_count;
3378c9fbc29Smrg	wire.preserve= (type->preserve!=NULL);
3388c9fbc29Smrg	if (type->level_names!=NULL)
3398c9fbc29Smrg	     wire.nLevelNames= type->num_levels;
3408c9fbc29Smrg	else wire.nLevelNames= 0;
3418c9fbc29Smrg	tmp= fwrite(&wire,SIZEOF(xkmKeyTypeDesc),1,file);
3428c9fbc29Smrg	size+= tmp*SIZEOF(xkmKeyTypeDesc);
3438c9fbc29Smrg	for (n=0,entry= type->map;n<type->map_count;n++,entry++) {
3448c9fbc29Smrg	    wire_entry.level= entry->level;
3458c9fbc29Smrg	    wire_entry.realMods= entry->mods.real_mods;
3468c9fbc29Smrg	    wire_entry.virtualMods= entry->mods.vmods;
3478c9fbc29Smrg	    tmp= fwrite(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file);
3488c9fbc29Smrg	    size+= tmp*SIZEOF(xkmKTMapEntryDesc);
3498c9fbc29Smrg	}
3508c9fbc29Smrg	size+= xkmPutCountedString(file,XkbAtomGetString(dpy,type->name));
3518c9fbc29Smrg	if (type->preserve) {
3528c9fbc29Smrg	    xkmModsDesc	p_entry;
3538c9fbc29Smrg	    XkbModsPtr	pre;
3548c9fbc29Smrg	    for (n=0,pre=type->preserve;n<type->map_count;n++,pre++) {
3558c9fbc29Smrg		p_entry.realMods= pre->real_mods;
3568c9fbc29Smrg		p_entry.virtualMods= pre->vmods;
3578c9fbc29Smrg		tmp= fwrite(&p_entry,SIZEOF(xkmModsDesc),1,file);
3588c9fbc29Smrg		size+= tmp*SIZEOF(xkmModsDesc);
3598c9fbc29Smrg	    }
3608c9fbc29Smrg	}
3618c9fbc29Smrg	if (type->level_names!=NULL) {
3628c9fbc29Smrg	    names= type->level_names;
3638c9fbc29Smrg	    for (n=0;n<wire.nLevelNames;n++) {
3648c9fbc29Smrg		size+= xkmPutCountedString(file,XkbAtomGetString(dpy,names[n]));
3658c9fbc29Smrg	    }
3668c9fbc29Smrg	}
3678c9fbc29Smrg    }
3688c9fbc29Smrg    return size;
3698c9fbc29Smrg}
3708c9fbc29Smrg
3718c9fbc29Smrg/***====================================================================***/
3728c9fbc29Smrg
3738c9fbc29Smrgstatic unsigned
3748c9fbc29SmrgSizeXKMCompatMap(	XkbFileInfo *		result,
3758c9fbc29Smrg			XkmInfo *		info,
3768c9fbc29Smrg			xkmSectionInfo *	toc,
3778c9fbc29Smrg			int *			offset_inout)
3788c9fbc29Smrg{
3798c9fbc29SmrgXkbDescPtr	xkb;
3808c9fbc29Smrgchar *		name;
3818c9fbc29Smrgint		size;
3828c9fbc29Smrgregister int	i;
3838c9fbc29Smrgunsigned 	groups,nGroups;
3848c9fbc29SmrgDisplay *	dpy;
3858c9fbc29Smrg
3868c9fbc29Smrg    xkb= result->xkb;
3878c9fbc29Smrg    dpy= xkb->dpy;
3888c9fbc29Smrg    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
3898c9fbc29Smrg	_XkbLibError(_XkbErrMissingCompatMap,"SizeXKMCompatMap",0);
3908c9fbc29Smrg	return 0;
3918c9fbc29Smrg    }
3928c9fbc29Smrg    if (xkb->names)	name= XkbAtomGetString(dpy,xkb->names->compat);
3938c9fbc29Smrg    else		name= NULL;
3948c9fbc29Smrg
3958c9fbc29Smrg    for (i=groups=nGroups=0;i<XkbNumKbdGroups;i++) {
3968c9fbc29Smrg	if ((xkb->compat->groups[i].real_mods!=0)||
3978c9fbc29Smrg			(xkb->compat->groups[i].vmods!=0)) {
3988c9fbc29Smrg	    groups|= (1<<i);
3998c9fbc29Smrg	    nGroups++;
4008c9fbc29Smrg	}
4018c9fbc29Smrg    }
4028c9fbc29Smrg    info->group_compat= groups;
4038c9fbc29Smrg    info->num_group_compat= nGroups;
4048c9fbc29Smrg    size= 4; /* room for num_si and group_compat mask */
4058c9fbc29Smrg    size+= xkmSizeCountedString(name);
4068c9fbc29Smrg    size+= (SIZEOF(xkmSymInterpretDesc)*xkb->compat->num_si);
4078c9fbc29Smrg    size+= (SIZEOF(xkmModsDesc)*nGroups);
4088c9fbc29Smrg    toc->type= 		XkmCompatMapIndex;
4098c9fbc29Smrg    toc->format= 	MSBFirst;
4108c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
4118c9fbc29Smrg    toc->offset= 	(*offset_inout);
4128c9fbc29Smrg    (*offset_inout)+= 	toc->size;
4138c9fbc29Smrg    return 1;
4148c9fbc29Smrg}
4158c9fbc29Smrg
4168c9fbc29Smrgstatic unsigned
4178c9fbc29SmrgWriteXKMCompatMap(FILE *file,XkbFileInfo *result,XkmInfo *info)
4188c9fbc29Smrg{
4198c9fbc29Smrgregister unsigned	i;
4208c9fbc29Smrgchar *			name;
4218c9fbc29SmrgXkbDescPtr		xkb;
4228c9fbc29SmrgXkbSymInterpretPtr	interp;
4238c9fbc29SmrgxkmSymInterpretDesc	wire;
4248c9fbc29SmrgDisplay *		dpy;
4258c9fbc29Smrgunsigned		tmp,size=0;
4268c9fbc29Smrg
4278c9fbc29Smrg    xkb= result->xkb;
4288c9fbc29Smrg    dpy= xkb->dpy;
4298c9fbc29Smrg    if (xkb->names)	name= XkbAtomGetString(dpy,xkb->names->compat);
4308c9fbc29Smrg    else		name= NULL;
4318c9fbc29Smrg    size+= xkmPutCountedString(file,name);
4328c9fbc29Smrg    size+= xkmPutCARD16(file,xkb->compat->num_si);
4338c9fbc29Smrg    size+= xkmPutCARD8(file,info->group_compat);
4348c9fbc29Smrg    size+= xkmPutPadding(file,1);
4358c9fbc29Smrg    interp= xkb->compat->sym_interpret;
4368c9fbc29Smrg    for (i=0;i<xkb->compat->num_si;i++,interp++) {
4378c9fbc29Smrg	wire.sym= interp->sym;
4388c9fbc29Smrg	wire.mods= interp->mods;
4398c9fbc29Smrg	wire.match= interp->match;
4408c9fbc29Smrg	wire.virtualMod= interp->virtual_mod;
4418c9fbc29Smrg	wire.flags= interp->flags;
4428c9fbc29Smrg	wire.actionType= interp->act.type;
4438c9fbc29Smrg	wire.actionData[0]= interp->act.data[0];
4448c9fbc29Smrg	wire.actionData[1]= interp->act.data[1];
4458c9fbc29Smrg	wire.actionData[2]= interp->act.data[2];
4468c9fbc29Smrg	wire.actionData[3]= interp->act.data[3];
4478c9fbc29Smrg	wire.actionData[4]= interp->act.data[4];
4488c9fbc29Smrg	wire.actionData[5]= interp->act.data[5];
4498c9fbc29Smrg	wire.actionData[6]= interp->act.data[6];
4508c9fbc29Smrg	tmp= fwrite(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
4518c9fbc29Smrg	size+= tmp*SIZEOF(xkmSymInterpretDesc);
4528c9fbc29Smrg    }
4538c9fbc29Smrg    if (info->group_compat) {
4548c9fbc29Smrg	register unsigned 	bit;
4558c9fbc29Smrg	xkmModsDesc 		modsWire;
4568c9fbc29Smrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
4578c9fbc29Smrg	    if (info->group_compat&bit) {
4588c9fbc29Smrg		modsWire.realMods= xkb->compat->groups[i].real_mods;
4598c9fbc29Smrg		modsWire.virtualMods= xkb->compat->groups[i].vmods;
4608c9fbc29Smrg		fwrite(&modsWire,SIZEOF(xkmModsDesc),1,file);
4618c9fbc29Smrg		size+= SIZEOF(xkmModsDesc);
4628c9fbc29Smrg	    }
4638c9fbc29Smrg	}
4648c9fbc29Smrg    }
4658c9fbc29Smrg    return size;
4668c9fbc29Smrg}
4678c9fbc29Smrg
4688c9fbc29Smrg/***====================================================================***/
4698c9fbc29Smrg
4708c9fbc29Smrgstatic unsigned
4718c9fbc29SmrgSizeXKMSymbols(	XkbFileInfo *		result,
4728c9fbc29Smrg		XkmInfo *		info,
4738c9fbc29Smrg		xkmSectionInfo *	toc,
4748c9fbc29Smrg		int *			offset_inout)
4758c9fbc29Smrg{
4768c9fbc29SmrgDisplay *	dpy;
4778c9fbc29SmrgXkbDescPtr	xkb;
4788c9fbc29Smrgunsigned 	size;
4798c9fbc29Smrgregister int	i,nSyms;
4808c9fbc29Smrgchar *		name;
4818c9fbc29Smrg
4828c9fbc29Smrg    xkb= result->xkb;
4838c9fbc29Smrg    dpy= xkb->dpy;
4848c9fbc29Smrg    if ((!xkb)||(!xkb->map)||((!xkb->map->syms))) {
4858c9fbc29Smrg	_XkbLibError(_XkbErrMissingSymbols,"SizeXKMSymbols",0);
4868c9fbc29Smrg	return 0;
4878c9fbc29Smrg    }
4888c9fbc29Smrg    if (xkb->names && (xkb->names->symbols!=None))
4898c9fbc29Smrg	 name= XkbAtomGetString(dpy,xkb->names->symbols);
4908c9fbc29Smrg    else name= NULL;
4918c9fbc29Smrg    size= xkmSizeCountedString(name);
4928c9fbc29Smrg    size+= 4;	/* min and max keycode, group names mask */
4938c9fbc29Smrg    for (i=0;i<XkbNumKbdGroups;i++) {
4948c9fbc29Smrg	if (xkb->names->groups[i]!=None)
4958c9fbc29Smrg	    size+= xkmSizeCountedAtomString(dpy,xkb->names->groups[i]);
4968c9fbc29Smrg    }
4978c9fbc29Smrg    info->total_vmodmaps= 0;
4988c9fbc29Smrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
4998c9fbc29Smrg	nSyms= XkbKeyNumSyms(xkb,i);
5008c9fbc29Smrg	size+= SIZEOF(xkmKeySymMapDesc)+(nSyms*4);
5018c9fbc29Smrg	if (xkb->server) {
5028c9fbc29Smrg	    if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
5038c9fbc29Smrg		register int g;
5048c9fbc29Smrg		for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
5058c9fbc29Smrg		    if (xkb->server->explicit[i]&(1<<g)) {
5068c9fbc29Smrg			XkbKeyTypePtr	type;
5078c9fbc29Smrg			char *		name;
5088c9fbc29Smrg			type= XkbKeyKeyType(xkb,i,g);
5098c9fbc29Smrg			name= XkbAtomGetString(dpy,type->name);
5108c9fbc29Smrg			if (name!=NULL)
5118c9fbc29Smrg			    size+= xkmSizeCountedString(name);
5128c9fbc29Smrg		    }
5138c9fbc29Smrg		}
5148c9fbc29Smrg	    }
5158c9fbc29Smrg	    if (XkbKeyHasActions(xkb,i))
5168c9fbc29Smrg		size+= nSyms*SIZEOF(xkmActionDesc);
5178c9fbc29Smrg	    if (xkb->server->behaviors[i].type!=XkbKB_Default)
5188c9fbc29Smrg		size+= SIZEOF(xkmBehaviorDesc);
5198c9fbc29Smrg	    if (xkb->server->vmodmap && (xkb->server->vmodmap[i]!=0))
5208c9fbc29Smrg		info->total_vmodmaps++;
5218c9fbc29Smrg	}
5228c9fbc29Smrg    }
5238c9fbc29Smrg    size+= info->total_vmodmaps*SIZEOF(xkmVModMapDesc);
5248c9fbc29Smrg    toc->type= 		XkmSymbolsIndex;
5258c9fbc29Smrg    toc->format= 	MSBFirst;
5268c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
5278c9fbc29Smrg    toc->offset= 	(*offset_inout);
5288c9fbc29Smrg    (*offset_inout)+= 	toc->size;
5298c9fbc29Smrg    return 1;
5308c9fbc29Smrg}
5318c9fbc29Smrg
5328c9fbc29Smrgstatic unsigned
5338c9fbc29SmrgWriteXKMSymbols(FILE *file,XkbFileInfo *result,XkmInfo *info)
5348c9fbc29Smrg{
5358c9fbc29SmrgDisplay *		dpy;
5368c9fbc29SmrgXkbDescPtr		xkb;
5378c9fbc29Smrgregister int		i,n;
5388c9fbc29SmrgxkmKeySymMapDesc 	wireMap;
5398c9fbc29Smrgchar *			name;
5408c9fbc29Smrgunsigned		tmp,size= 0;
5418c9fbc29Smrg
5428c9fbc29Smrg    xkb= result->xkb;
5438c9fbc29Smrg    dpy= xkb->dpy;
5448c9fbc29Smrg    if (xkb->names && (xkb->names->symbols!=None))
5458c9fbc29Smrg	 name= XkbAtomGetString(dpy,xkb->names->symbols);
5468c9fbc29Smrg    else name= NULL;
5478c9fbc29Smrg    size+= xkmPutCountedString(file,name);
5488c9fbc29Smrg    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
5498c9fbc29Smrg	if (xkb->names->groups[i]!=None)
5508c9fbc29Smrg	    tmp|= (1<<i);
5518c9fbc29Smrg    }
5528c9fbc29Smrg    size+= xkmPutCARD8(file,xkb->min_key_code);
5538c9fbc29Smrg    size+= xkmPutCARD8(file,xkb->max_key_code);
5548c9fbc29Smrg    size+= xkmPutCARD8(file,tmp);
5558c9fbc29Smrg    size+= xkmPutCARD8(file,info->total_vmodmaps);
5568c9fbc29Smrg    for (i=0,n=1;i<XkbNumKbdGroups;i++,n<<=1) {
5578c9fbc29Smrg	if ((tmp&n)==0)
5588c9fbc29Smrg	    continue;
5598c9fbc29Smrg	size+= xkmPutCountedAtomString(dpy,file,xkb->names->groups[i]);
5608c9fbc29Smrg    }
5618c9fbc29Smrg    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++)  {
5628c9fbc29Smrg	char *typeName[XkbNumKbdGroups];
5638c9fbc29Smrg	wireMap.width= XkbKeyGroupsWidth(xkb,i);
5648c9fbc29Smrg	wireMap.num_groups= XkbKeyGroupInfo(xkb,i);
5658c9fbc29Smrg	if (xkb->map && xkb->map->modmap)
5668c9fbc29Smrg	     wireMap.modifier_map= xkb->map->modmap[i];
5678c9fbc29Smrg	else wireMap.modifier_map= 0;
5688c9fbc29Smrg	wireMap.flags= 0;
5698c9fbc29Smrg	bzero((char *)typeName,XkbNumKbdGroups*sizeof(char *));
5708c9fbc29Smrg	if (xkb->server) {
5718c9fbc29Smrg	    if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
5728c9fbc29Smrg		register int g;
5738c9fbc29Smrg		for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
5748c9fbc29Smrg		    if (xkb->server->explicit[i]&(1<<g)) {
5758c9fbc29Smrg			XkbKeyTypePtr	type;
5768c9fbc29Smrg			type= XkbKeyKeyType(xkb,i,g);
5778c9fbc29Smrg			typeName[g]= XkbAtomGetString(dpy,type->name);
5788c9fbc29Smrg			if (typeName[g]!=NULL)
5798c9fbc29Smrg			    wireMap.flags|= (1<<g);
5808c9fbc29Smrg		    }
5818c9fbc29Smrg		}
5828c9fbc29Smrg	    }
5838c9fbc29Smrg	    if (XkbKeyHasActions(xkb,i))
5848c9fbc29Smrg		wireMap.flags|= XkmKeyHasActions;
5858c9fbc29Smrg	    if (xkb->server->behaviors[i].type!=XkbKB_Default)
5868c9fbc29Smrg		wireMap.flags|= XkmKeyHasBehavior;
5878c9fbc29Smrg	    if ((xkb->server->explicit[i]&XkbExplicitAutoRepeatMask)&&
5888c9fbc29Smrg		(xkb->ctrls!=NULL)) {
5898c9fbc29Smrg		if (xkb->ctrls->per_key_repeat[(i/8)]&(1<<(i%8)))
5908c9fbc29Smrg		     wireMap.flags|= XkmRepeatingKey;
5918c9fbc29Smrg		else wireMap.flags|= XkmNonRepeatingKey;
5928c9fbc29Smrg	    }
5938c9fbc29Smrg	}
5948c9fbc29Smrg	tmp= fwrite(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file);
5958c9fbc29Smrg	size+= tmp*SIZEOF(xkmKeySymMapDesc);
5968c9fbc29Smrg	if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
5978c9fbc29Smrg	    register int g;
5988c9fbc29Smrg	    for (g=0;g<XkbNumKbdGroups;g++) {
5998c9fbc29Smrg		if (typeName[g]!=NULL)
6008c9fbc29Smrg		    size+= xkmPutCountedString(file,typeName[g]);
6018c9fbc29Smrg	    }
6028c9fbc29Smrg	}
6038c9fbc29Smrg	if (XkbNumGroups(wireMap.num_groups)>0) {
6048c9fbc29Smrg	    KeySym	*sym;
6058c9fbc29Smrg	    sym= XkbKeySymsPtr(xkb,i);
6068c9fbc29Smrg	    for (n=XkbKeyNumSyms(xkb,i);n>0;n--,sym++) {
6078c9fbc29Smrg		size+= xkmPutCARD32(file,(CARD32)*sym);
6088c9fbc29Smrg	    }
6098c9fbc29Smrg	    if (wireMap.flags&XkmKeyHasActions) {
6108c9fbc29Smrg		XkbAction *	act;
6118c9fbc29Smrg		act= XkbKeyActionsPtr(xkb,i);
6128c9fbc29Smrg		for (n=XkbKeyNumActions(xkb,i);n>0;n--,act++) {
6138c9fbc29Smrg		    tmp= fwrite(act,SIZEOF(xkmActionDesc),1,file);
6148c9fbc29Smrg		    size+= tmp*SIZEOF(xkmActionDesc);
6158c9fbc29Smrg		}
6168c9fbc29Smrg	    }
6178c9fbc29Smrg	}
6188c9fbc29Smrg	if (wireMap.flags&XkmKeyHasBehavior) {
6198c9fbc29Smrg	    xkmBehaviorDesc	b;
6208c9fbc29Smrg	    b.type= xkb->server->behaviors[i].type;
6218c9fbc29Smrg	    b.data= xkb->server->behaviors[i].data;
6228c9fbc29Smrg	    tmp= fwrite(&b,SIZEOF(xkmBehaviorDesc),1,file);
6238c9fbc29Smrg	    size+= tmp*SIZEOF(xkmBehaviorDesc);
6248c9fbc29Smrg	}
6258c9fbc29Smrg    }
6268c9fbc29Smrg    if (info->total_vmodmaps>0) {
6278c9fbc29Smrg	xkmVModMapDesc	v;
6288c9fbc29Smrg	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
6298c9fbc29Smrg	    if (xkb->server->vmodmap[i]!=0) {
6308c9fbc29Smrg		v.key= i;
6318c9fbc29Smrg		v.vmods= xkb->server->vmodmap[i];
6328c9fbc29Smrg		tmp= fwrite(&v,SIZEOF(xkmVModMapDesc),1,file);
6338c9fbc29Smrg		size+= tmp*SIZEOF(xkmVModMapDesc);
6348c9fbc29Smrg	    }
6358c9fbc29Smrg	}
6368c9fbc29Smrg    }
6378c9fbc29Smrg    return size;
6388c9fbc29Smrg}
6398c9fbc29Smrg
6408c9fbc29Smrg/***====================================================================***/
6418c9fbc29Smrg
6428c9fbc29Smrgstatic unsigned
6438c9fbc29SmrgSizeXKMIndicators(XkbFileInfo *result,XkmInfo *info,xkmSectionInfo *toc,
6448c9fbc29Smrg							int *offset_inout)
6458c9fbc29Smrg{
6468c9fbc29SmrgDisplay *		dpy;
6478c9fbc29SmrgXkbDescPtr		xkb;
6488c9fbc29Smrgunsigned 		size;
6498c9fbc29Smrgregister unsigned	i,nLEDs;
6508c9fbc29Smrg
6518c9fbc29Smrg    xkb= result->xkb;
6528c9fbc29Smrg    dpy= xkb->dpy;
6538c9fbc29Smrg    if ((xkb==NULL)||(xkb->indicators==NULL)) {
6548c9fbc29Smrg/*	_XkbLibError(_XkbErrMissingIndicators,"SizeXKMIndicators",0);*/
6558c9fbc29Smrg	return 0;
6568c9fbc29Smrg    }
6578c9fbc29Smrg    nLEDs=0;
6588c9fbc29Smrg    size= 8;	/* number of indicator maps/physical indicators */
6598c9fbc29Smrg    if (xkb->indicators!=NULL) {
6608c9fbc29Smrg	for (i=0;i<XkbNumIndicators;i++) {
6618c9fbc29Smrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
6628c9fbc29Smrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
6638c9fbc29Smrg		(map->which_mods!=0)||
6648c9fbc29Smrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
6658c9fbc29Smrg		(map->ctrls!=0) ||
6668c9fbc29Smrg		(xkb->names && (xkb->names->indicators[i]!=None))) {
6678c9fbc29Smrg		char *name;
6688c9fbc29Smrg		if (xkb->names && xkb->names->indicators[i]!=None) {
6698c9fbc29Smrg		     name= XkbAtomGetString(dpy,xkb->names->indicators[i]);
6708c9fbc29Smrg		}
6718c9fbc29Smrg		else name= NULL;
6728c9fbc29Smrg		size+= xkmSizeCountedString(name);
6738c9fbc29Smrg		size+= SIZEOF(xkmIndicatorMapDesc);
6748c9fbc29Smrg		nLEDs++;
6758c9fbc29Smrg	    }
6768c9fbc29Smrg	}
6778c9fbc29Smrg    }
6788c9fbc29Smrg    info->num_leds= nLEDs;
6798c9fbc29Smrg    toc->type= 		XkmIndicatorsIndex;
6808c9fbc29Smrg    toc->format= 	MSBFirst;
6818c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
6828c9fbc29Smrg    toc->offset= 	(*offset_inout);
6838c9fbc29Smrg    (*offset_inout)+= 	toc->size;
6848c9fbc29Smrg    return 1;
6858c9fbc29Smrg}
6868c9fbc29Smrg
6878c9fbc29Smrgstatic unsigned
6888c9fbc29SmrgWriteXKMIndicators(FILE *file,XkbFileInfo *result,XkmInfo *info)
6898c9fbc29Smrg{
6908c9fbc29SmrgDisplay *		dpy;
6918c9fbc29SmrgXkbDescPtr		xkb;
6928c9fbc29Smrgregister unsigned	i;
6938c9fbc29SmrgxkmIndicatorMapDesc	wire;
6948c9fbc29Smrgunsigned		tmp,size= 0;
6958c9fbc29Smrg
6968c9fbc29Smrg    xkb= result->xkb;
6978c9fbc29Smrg    dpy= xkb->dpy;
6988c9fbc29Smrg    size+= xkmPutCARD8(file,info->num_leds);
6998c9fbc29Smrg    size+= xkmPutPadding(file,3);
7008c9fbc29Smrg    size+= xkmPutCARD32(file,xkb->indicators->phys_indicators);
7018c9fbc29Smrg    if (xkb->indicators!=NULL) {
7028c9fbc29Smrg	for (i=0;i<XkbNumIndicators;i++) {
7038c9fbc29Smrg	    XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
7048c9fbc29Smrg	    if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
7058c9fbc29Smrg		(map->which_mods!=0)||
7068c9fbc29Smrg		(map->mods.real_mods!=0)||(map->mods.vmods!=0)||
7078c9fbc29Smrg		(map->ctrls!=0) ||
7088c9fbc29Smrg		(xkb->names && (xkb->names->indicators[i]!=None))) {
7098c9fbc29Smrg		char *name;
7108c9fbc29Smrg		if (xkb->names && xkb->names->indicators[i]!=None) {
7118c9fbc29Smrg		     name= XkbAtomGetString(dpy,xkb->names->indicators[i]);
7128c9fbc29Smrg		}
7138c9fbc29Smrg		else name= NULL;
7148c9fbc29Smrg		size+= xkmPutCountedString(file,name);
7158c9fbc29Smrg		wire.indicator= i+1;
7168c9fbc29Smrg		wire.flags= map->flags;
7178c9fbc29Smrg		wire.which_mods= map->which_mods;
7188c9fbc29Smrg		wire.real_mods= map->mods.real_mods;
7198c9fbc29Smrg		wire.vmods= map->mods.vmods;
7208c9fbc29Smrg		wire.which_groups= map->which_groups;
7218c9fbc29Smrg		wire.groups= map->groups;
7228c9fbc29Smrg		wire.ctrls= map->ctrls;
7238c9fbc29Smrg		tmp= fwrite(&wire,SIZEOF(xkmIndicatorMapDesc),1,file);
7248c9fbc29Smrg		size+= tmp*SIZEOF(xkmIndicatorMapDesc);
7258c9fbc29Smrg	    }
7268c9fbc29Smrg	}
7278c9fbc29Smrg    }
7288c9fbc29Smrg    return size;
7298c9fbc29Smrg}
7308c9fbc29Smrg
7318c9fbc29Smrg/***====================================================================***/
7328c9fbc29Smrg
7338c9fbc29Smrgstatic unsigned
7348c9fbc29SmrgSizeXKMGeomDoodad(XkbFileInfo *result,XkbDoodadPtr doodad)
7358c9fbc29Smrg{
7368c9fbc29Smrgunsigned	size;
7378c9fbc29Smrg
7388c9fbc29Smrg    size= SIZEOF(xkmAnyDoodadDesc);
7398c9fbc29Smrg    size+= xkmSizeCountedAtomString(result->xkb->dpy,doodad->any.name);
7408c9fbc29Smrg    if (doodad->any.type==XkbTextDoodad) {
7418c9fbc29Smrg	size+= xkmSizeCountedString(doodad->text.text);
7428c9fbc29Smrg	size+= xkmSizeCountedString(doodad->text.font);
7438c9fbc29Smrg    }
7448c9fbc29Smrg    else if (doodad->any.type==XkbLogoDoodad) {
7458c9fbc29Smrg	size+= xkmSizeCountedString(doodad->logo.logo_name);
7468c9fbc29Smrg    }
7478c9fbc29Smrg    return size;
7488c9fbc29Smrg}
7498c9fbc29Smrg
7508c9fbc29Smrgstatic unsigned
7518c9fbc29SmrgSizeXKMGeomSection(XkbFileInfo *result,XkbSectionPtr section)
7528c9fbc29Smrg{
7538c9fbc29Smrgregister int i;
7548c9fbc29Smrgunsigned size;
7558c9fbc29Smrg
7568c9fbc29Smrg    size= SIZEOF(xkmSectionDesc);
7578c9fbc29Smrg    size+= xkmSizeCountedAtomString(result->xkb->dpy,section->name);
7588c9fbc29Smrg    if (section->rows) {
7598c9fbc29Smrg	XkbRowPtr	row;
7608c9fbc29Smrg	for (row=section->rows,i=0;i<section->num_rows;i++,row++) {
7618c9fbc29Smrg	    size+= SIZEOF(xkmRowDesc);
7628c9fbc29Smrg	    size+= row->num_keys*SIZEOF(xkmKeyDesc);
7638c9fbc29Smrg	}
7648c9fbc29Smrg    }
7658c9fbc29Smrg    if (section->doodads) {
7668c9fbc29Smrg	XkbDoodadPtr	doodad;
7678c9fbc29Smrg	for (doodad=section->doodads,i=0;i<section->num_doodads;i++,doodad++) {
7688c9fbc29Smrg	    size+= SizeXKMGeomDoodad(result,doodad);
7698c9fbc29Smrg	}
7708c9fbc29Smrg    }
7718c9fbc29Smrg    if (section->overlays) {
7728c9fbc29Smrg	XkbOverlayPtr	ol;
7738c9fbc29Smrg	for (ol=section->overlays,i=0;i<section->num_overlays;i++,ol++) {
7748c9fbc29Smrg	    register int r;
7758c9fbc29Smrg	    XkbOverlayRowPtr	row;
7768c9fbc29Smrg	    size+= xkmSizeCountedAtomString(result->xkb->dpy,ol->name);
7778c9fbc29Smrg	    size+= SIZEOF(xkmOverlayDesc);
7788c9fbc29Smrg	    for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
7798c9fbc29Smrg		size+= SIZEOF(xkmOverlayRowDesc);
7808c9fbc29Smrg		size+= row->num_keys*SIZEOF(xkmOverlayKeyDesc);
7818c9fbc29Smrg	    }
7828c9fbc29Smrg	}
7838c9fbc29Smrg    }
7848c9fbc29Smrg    return size;
7858c9fbc29Smrg}
7868c9fbc29Smrg
7878c9fbc29Smrgstatic unsigned
7888c9fbc29SmrgSizeXKMGeometry(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
7898c9fbc29Smrg{
7908c9fbc29Smrgregister int	i;
7918c9fbc29SmrgDisplay *	dpy;
7928c9fbc29SmrgXkbDescPtr	xkb;
7938c9fbc29SmrgXkbGeometryPtr	geom;
7948c9fbc29Smrgunsigned	size;
7958c9fbc29Smrg
7968c9fbc29Smrg    xkb= result->xkb;
7978c9fbc29Smrg    dpy= xkb->dpy;
7988c9fbc29Smrg    if ((!xkb)||(!xkb->geom))
7998c9fbc29Smrg	return 0;
8008c9fbc29Smrg    geom= xkb->geom;
8018c9fbc29Smrg    size= xkmSizeCountedAtomString(dpy,geom->name);
8028c9fbc29Smrg    size+= SIZEOF(xkmGeometryDesc);
8038c9fbc29Smrg    size+= xkmSizeCountedString(geom->label_font);
8048c9fbc29Smrg    if (geom->properties) {
8058c9fbc29Smrg	XkbPropertyPtr	prop;
8068c9fbc29Smrg	for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
8078c9fbc29Smrg	    size+= xkmSizeCountedString(prop->name);
8088c9fbc29Smrg	    size+= xkmSizeCountedString(prop->value);
8098c9fbc29Smrg	}
8108c9fbc29Smrg    }
8118c9fbc29Smrg    if (geom->colors) {
8128c9fbc29Smrg	XkbColorPtr	color;
8138c9fbc29Smrg	for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
8148c9fbc29Smrg	    size+= xkmSizeCountedString(color->spec);
8158c9fbc29Smrg	}
8168c9fbc29Smrg    }
8178c9fbc29Smrg    if (geom->shapes) {
8188c9fbc29Smrg	XkbShapePtr	shape;
8198c9fbc29Smrg	for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
8208c9fbc29Smrg	    register int n;
8218c9fbc29Smrg	    register XkbOutlinePtr	ol;
8228c9fbc29Smrg	    size+= xkmSizeCountedAtomString(dpy,shape->name);
8238c9fbc29Smrg	    size+= SIZEOF(xkmShapeDesc);
8248c9fbc29Smrg	    for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
8258c9fbc29Smrg		size+= SIZEOF(xkmOutlineDesc);
8268c9fbc29Smrg		size+= ol->num_points*SIZEOF(xkmPointDesc);
8278c9fbc29Smrg	    }
8288c9fbc29Smrg	}
8298c9fbc29Smrg    }
8308c9fbc29Smrg    if (geom->sections) {
8318c9fbc29Smrg	XkbSectionPtr	section;
8328c9fbc29Smrg	for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
8338c9fbc29Smrg	    size+= SizeXKMGeomSection(result,section);
8348c9fbc29Smrg	}
8358c9fbc29Smrg    }
8368c9fbc29Smrg    if  (geom->doodads) {
8378c9fbc29Smrg	XkbDoodadPtr	doodad;
8388c9fbc29Smrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
8398c9fbc29Smrg	    size+= SizeXKMGeomDoodad(result,doodad);
8408c9fbc29Smrg	}
8418c9fbc29Smrg    }
8428c9fbc29Smrg    if (geom->key_aliases) {
8438c9fbc29Smrg	size+= geom->num_key_aliases*(XkbKeyNameLength*2);
8448c9fbc29Smrg    }
8458c9fbc29Smrg    toc->type= 		XkmGeometryIndex;
8468c9fbc29Smrg    toc->format= 	MSBFirst;
8478c9fbc29Smrg    toc->size= 		size+SIZEOF(xkmSectionInfo);
8488c9fbc29Smrg    toc->offset= 	(*offset_inout);
8498c9fbc29Smrg    (*offset_inout)+= 	toc->size;
8508c9fbc29Smrg    return 1;
8518c9fbc29Smrg}
8528c9fbc29Smrg
8538c9fbc29Smrgstatic unsigned
8548c9fbc29SmrgWriteXKMGeomDoodad(FILE *file,XkbFileInfo *result,XkbDoodadPtr doodad)
8558c9fbc29Smrg{
8568c9fbc29SmrgDisplay *	dpy;
8578c9fbc29SmrgXkbDescPtr	xkb;
8588c9fbc29SmrgxkmDoodadDesc	doodadWire;
8598c9fbc29Smrgunsigned	tmp,size= 0;
8608c9fbc29Smrg
8618c9fbc29Smrg    xkb= result->xkb;
8628c9fbc29Smrg    dpy= xkb->dpy;
8638c9fbc29Smrg    bzero((char *)&doodadWire,sizeof(doodadWire));
8648c9fbc29Smrg    doodadWire.any.type= doodad->any.type;
8658c9fbc29Smrg    doodadWire.any.priority= doodad->any.priority;
8668c9fbc29Smrg    doodadWire.any.top= doodad->any.top;
8678c9fbc29Smrg    doodadWire.any.left= doodad->any.left;
8688c9fbc29Smrg    switch (doodad->any.type) {
8698c9fbc29Smrg	case XkbOutlineDoodad:
8708c9fbc29Smrg	case XkbSolidDoodad:
8718c9fbc29Smrg	    doodadWire.shape.angle= doodad->shape.angle;
8728c9fbc29Smrg	    doodadWire.shape.color_ndx= doodad->shape.color_ndx;
8738c9fbc29Smrg	    doodadWire.shape.shape_ndx= doodad->shape.shape_ndx;
8748c9fbc29Smrg	    break;
8758c9fbc29Smrg	case XkbTextDoodad:
8768c9fbc29Smrg	    doodadWire.text.angle= doodad->text.angle;
8778c9fbc29Smrg	    doodadWire.text.width= doodad->text.width;
8788c9fbc29Smrg	    doodadWire.text.height= doodad->text.height;
8798c9fbc29Smrg	    doodadWire.text.color_ndx= doodad->text.color_ndx;
8808c9fbc29Smrg	    break;
8818c9fbc29Smrg	case XkbIndicatorDoodad:
8828c9fbc29Smrg	    doodadWire.indicator.shape_ndx= doodad->indicator.shape_ndx;
8838c9fbc29Smrg	    doodadWire.indicator.on_color_ndx= doodad->indicator.on_color_ndx;
8848c9fbc29Smrg	    doodadWire.indicator.off_color_ndx= doodad->indicator.off_color_ndx;
8858c9fbc29Smrg	    break;
8868c9fbc29Smrg	case XkbLogoDoodad:
8878c9fbc29Smrg	    doodadWire.logo.angle= doodad->logo.angle;
8888c9fbc29Smrg	    doodadWire.logo.color_ndx= doodad->logo.color_ndx;
8898c9fbc29Smrg	    doodadWire.logo.shape_ndx= doodad->logo.shape_ndx;
8908c9fbc29Smrg	    break;
8918c9fbc29Smrg	default:
8928c9fbc29Smrg	    _XkbLibError(_XkbErrIllegalDoodad,"WriteXKMGeomDoodad",
8938c9fbc29Smrg	    						doodad->any.type);
8948c9fbc29Smrg	    return 0;
8958c9fbc29Smrg    }
8968c9fbc29Smrg    size+= xkmPutCountedAtomString(dpy,file,doodad->any.name);
8978c9fbc29Smrg    tmp= fwrite(&doodadWire,SIZEOF(xkmDoodadDesc),1,file);
8988c9fbc29Smrg    size+= tmp*SIZEOF(xkmDoodadDesc);
8998c9fbc29Smrg    if (doodad->any.type==XkbTextDoodad) {
9008c9fbc29Smrg	size+= xkmPutCountedString(file,doodad->text.text);
9018c9fbc29Smrg	size+= xkmPutCountedString(file,doodad->text.font);
9028c9fbc29Smrg    }
9038c9fbc29Smrg    else if (doodad->any.type==XkbLogoDoodad) {
9048c9fbc29Smrg	size+= xkmPutCountedString(file,doodad->logo.logo_name);
9058c9fbc29Smrg    }
9068c9fbc29Smrg    return size;
9078c9fbc29Smrg}
9088c9fbc29Smrg
9098c9fbc29Smrgstatic unsigned
9108c9fbc29SmrgWriteXKMGeomOverlay(FILE *file,XkbFileInfo *result,XkbOverlayPtr ol)
9118c9fbc29Smrg{
9128c9fbc29Smrgregister int		r,k;
9138c9fbc29SmrgDisplay *		dpy;
9148c9fbc29SmrgXkbDescPtr		xkb;
9158c9fbc29SmrgXkbOverlayRowPtr	row;
9168c9fbc29SmrgxkmOverlayDesc		olWire;
9178c9fbc29SmrgxkmOverlayRowDesc	rowWire;
9188c9fbc29SmrgxkmOverlayKeyDesc	keyWire;
9198c9fbc29Smrgunsigned		tmp,size= 0;
9208c9fbc29Smrg
9218c9fbc29Smrg    xkb= result->xkb;
9228c9fbc29Smrg    dpy= xkb->dpy;
9238c9fbc29Smrg    bzero((char *)&olWire,sizeof(olWire));
9248c9fbc29Smrg    bzero((char *)&rowWire,sizeof(rowWire));
9258c9fbc29Smrg    bzero((char *)&keyWire,sizeof(keyWire));
9268c9fbc29Smrg    size+= xkmPutCountedAtomString(dpy,file,ol->name);
9278c9fbc29Smrg    olWire.num_rows= ol->num_rows;
9288c9fbc29Smrg    tmp= fwrite(&olWire,SIZEOF(xkmOverlayDesc),1,file);
9298c9fbc29Smrg    size+= tmp*SIZEOF(xkmOverlayDesc);
9308c9fbc29Smrg    for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
9318c9fbc29Smrg	XkbOverlayKeyPtr	key;
9328c9fbc29Smrg	rowWire.row_under= row->row_under;
9338c9fbc29Smrg	rowWire.num_keys= row->num_keys;
9348c9fbc29Smrg	tmp= fwrite(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file);
9358c9fbc29Smrg	size+= tmp*SIZEOF(xkmOverlayRowDesc);
9368c9fbc29Smrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
9378c9fbc29Smrg	    memcpy(keyWire.over,key->over.name,XkbKeyNameLength);
9388c9fbc29Smrg	    memcpy(keyWire.under,key->under.name,XkbKeyNameLength);
9398c9fbc29Smrg	    tmp= fwrite(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file);
9408c9fbc29Smrg	    size+= tmp*SIZEOF(xkmOverlayKeyDesc);
9418c9fbc29Smrg	}
9428c9fbc29Smrg    }
9438c9fbc29Smrg    return size;
9448c9fbc29Smrg}
9458c9fbc29Smrg
9468c9fbc29Smrgstatic unsigned
9478c9fbc29SmrgWriteXKMGeomSection(FILE *file,XkbFileInfo *result,XkbSectionPtr section)
9488c9fbc29Smrg{
9498c9fbc29Smrgregister int	i;
9508c9fbc29SmrgDisplay *	dpy;
9518c9fbc29SmrgXkbDescPtr	xkb;
9528c9fbc29SmrgxkmSectionDesc	sectionWire;
9538c9fbc29Smrgunsigned	tmp,size= 0;
9548c9fbc29Smrg
9558c9fbc29Smrg    xkb= result->xkb;
9568c9fbc29Smrg    dpy= xkb->dpy;
9578c9fbc29Smrg    size+= xkmPutCountedAtomString(dpy,file,section->name);
9588c9fbc29Smrg    sectionWire.top= section->top;
9598c9fbc29Smrg    sectionWire.left= section->left;
9608c9fbc29Smrg    sectionWire.width= section->width;
9618c9fbc29Smrg    sectionWire.height= section->height;
9628c9fbc29Smrg    sectionWire.angle= section->angle;
9638c9fbc29Smrg    sectionWire.priority= section->priority;
9648c9fbc29Smrg    sectionWire.num_rows= section->num_rows;
9658c9fbc29Smrg    sectionWire.num_doodads= section->num_doodads;
9668c9fbc29Smrg    sectionWire.num_overlays= section->num_overlays;
9678c9fbc29Smrg    tmp= fwrite(&sectionWire,SIZEOF(xkmSectionDesc),1,file);
9688c9fbc29Smrg    size+= tmp*SIZEOF(xkmSectionDesc);
9698c9fbc29Smrg    if (section->rows) {
9708c9fbc29Smrg	register unsigned k;
9718c9fbc29Smrg	XkbRowPtr	row;
9728c9fbc29Smrg	xkmRowDesc	rowWire;
9738c9fbc29Smrg	XkbKeyPtr	key;
9748c9fbc29Smrg	xkmKeyDesc	keyWire;
9758c9fbc29Smrg	for (i=0,row=section->rows;i<section->num_rows;i++,row++) {
9768c9fbc29Smrg	    rowWire.top= row->top;
9778c9fbc29Smrg	    rowWire.left= row->left;
9788c9fbc29Smrg	    rowWire.num_keys= row->num_keys;
9798c9fbc29Smrg	    rowWire.vertical= row->vertical;
9808c9fbc29Smrg	    tmp= fwrite(&rowWire,SIZEOF(xkmRowDesc),1,file);
9818c9fbc29Smrg	    size+= tmp*SIZEOF(xkmRowDesc);
9828c9fbc29Smrg	    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
9838c9fbc29Smrg		memcpy(keyWire.name,key->name.name,XkbKeyNameLength);
9848c9fbc29Smrg		keyWire.gap= key->gap;
9858c9fbc29Smrg		keyWire.shape_ndx= key->shape_ndx;
9868c9fbc29Smrg		keyWire.color_ndx= key->color_ndx;
9878c9fbc29Smrg		tmp= fwrite(&keyWire,SIZEOF(xkmKeyDesc),1,file);
9888c9fbc29Smrg		size+= tmp*SIZEOF(xkmKeyDesc);
9898c9fbc29Smrg	    }
9908c9fbc29Smrg	}
9918c9fbc29Smrg    }
9928c9fbc29Smrg    if (section->doodads) {
9938c9fbc29Smrg	XkbDoodadPtr	doodad;
9948c9fbc29Smrg	for (i=0,doodad=section->doodads;i<section->num_doodads;i++,doodad++) {
9958c9fbc29Smrg	    size+= WriteXKMGeomDoodad(file,result,doodad);
9968c9fbc29Smrg	}
9978c9fbc29Smrg    }
9988c9fbc29Smrg    if (section->overlays) {
9998c9fbc29Smrg	XkbOverlayPtr	ol;
10008c9fbc29Smrg	for (i=0,ol=section->overlays;i<section->num_overlays;i++,ol++) {
10018c9fbc29Smrg	    size+= WriteXKMGeomOverlay(file,result,ol);
10028c9fbc29Smrg	}
10038c9fbc29Smrg    }
10048c9fbc29Smrg    return size;
10058c9fbc29Smrg}
10068c9fbc29Smrg
10078c9fbc29Smrgstatic unsigned
10088c9fbc29SmrgWriteXKMGeometry(FILE *file,XkbFileInfo *result)
10098c9fbc29Smrg{
10108c9fbc29Smrgregister int	i;
10118c9fbc29SmrgDisplay *	dpy;
10128c9fbc29SmrgXkbDescPtr	xkb;
10138c9fbc29SmrgXkbGeometryPtr	geom;
10148c9fbc29SmrgxkmGeometryDesc	wire;
10158c9fbc29Smrgunsigned	tmp,size= 0;
10168c9fbc29Smrg
10178c9fbc29Smrg    xkb= result->xkb;
10188c9fbc29Smrg    dpy= xkb->dpy;
10198c9fbc29Smrg    if ((!xkb)||(!xkb->geom))
10208c9fbc29Smrg	return 0;
10218c9fbc29Smrg    geom= xkb->geom;
10228c9fbc29Smrg    wire.width_mm= geom->width_mm;
10238c9fbc29Smrg    wire.height_mm= geom->height_mm;
10248c9fbc29Smrg    wire.base_color_ndx= XkbGeomColorIndex(geom,geom->base_color);
10258c9fbc29Smrg    wire.label_color_ndx= XkbGeomColorIndex(geom,geom->label_color);
10268c9fbc29Smrg    wire.num_properties= geom->num_properties;
10278c9fbc29Smrg    wire.num_colors= geom->num_colors;
10288c9fbc29Smrg    wire.num_shapes= geom->num_shapes;
10298c9fbc29Smrg    wire.num_sections= geom->num_sections;
10308c9fbc29Smrg    wire.num_doodads= geom->num_doodads;
10318c9fbc29Smrg    wire.num_key_aliases= geom->num_key_aliases;
10328c9fbc29Smrg    size+= xkmPutCountedAtomString(dpy,file,geom->name);
10338c9fbc29Smrg    tmp= fwrite(&wire,SIZEOF(xkmGeometryDesc),1,file);
10348c9fbc29Smrg    size+= tmp*SIZEOF(xkmGeometryDesc);
10358c9fbc29Smrg    size+= xkmPutCountedString(file,geom->label_font);
10368c9fbc29Smrg    if (geom->properties) {
10378c9fbc29Smrg	XkbPropertyPtr	prop;
10388c9fbc29Smrg	for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
10398c9fbc29Smrg	    size+= xkmPutCountedString(file,prop->name);
10408c9fbc29Smrg	    size+= xkmPutCountedString(file,prop->value);
10418c9fbc29Smrg	}
10428c9fbc29Smrg    }
10438c9fbc29Smrg    if (geom->colors) {
10448c9fbc29Smrg	XkbColorPtr	color;
10458c9fbc29Smrg	for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
10468c9fbc29Smrg	    size+= xkmPutCountedString(file,color->spec);
10478c9fbc29Smrg	}
10488c9fbc29Smrg    }
10498c9fbc29Smrg    if (geom->shapes) {
10508c9fbc29Smrg	XkbShapePtr	shape;
10518c9fbc29Smrg	xkmShapeDesc	shapeWire;
10528c9fbc29Smrg
10538c9fbc29Smrg	for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
10548c9fbc29Smrg	    register int 	n;
10558c9fbc29Smrg	    XkbOutlinePtr	ol;
10568c9fbc29Smrg	    xkmOutlineDesc	olWire;
10578c9fbc29Smrg	    bzero((char *)&shapeWire,sizeof(xkmShapeDesc));
10588c9fbc29Smrg	    size+= xkmPutCountedAtomString(dpy,file,shape->name);
10598c9fbc29Smrg	    shapeWire.num_outlines= shape->num_outlines;
10608c9fbc29Smrg	    if (shape->primary!=NULL)
10618c9fbc29Smrg		 shapeWire.primary_ndx= XkbOutlineIndex(shape,shape->primary);
10628c9fbc29Smrg	    else shapeWire.primary_ndx= XkbNoShape;
10638c9fbc29Smrg	    if (shape->approx!=NULL)
10648c9fbc29Smrg		 shapeWire.approx_ndx= XkbOutlineIndex(shape,shape->approx);
10658c9fbc29Smrg	    else shapeWire.approx_ndx= XkbNoShape;
10668c9fbc29Smrg	    tmp= fwrite(&shapeWire,SIZEOF(xkmShapeDesc),1,file);
10678c9fbc29Smrg	    size+= tmp*SIZEOF(xkmShapeDesc);
10688c9fbc29Smrg	    for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
10698c9fbc29Smrg		register int	p;
10708c9fbc29Smrg		XkbPointPtr	pt;
10718c9fbc29Smrg		xkmPointDesc	ptWire;
10728c9fbc29Smrg		olWire.num_points= ol->num_points;
10738c9fbc29Smrg		olWire.corner_radius= ol->corner_radius;
10748c9fbc29Smrg		tmp= fwrite(&olWire,SIZEOF(xkmOutlineDesc),1,file);
10758c9fbc29Smrg		size+= tmp*SIZEOF(xkmOutlineDesc);
10768c9fbc29Smrg		for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
10778c9fbc29Smrg		    ptWire.x= pt->x;
10788c9fbc29Smrg		    ptWire.y= pt->y;
10798c9fbc29Smrg		    tmp= fwrite(&ptWire,SIZEOF(xkmPointDesc),1,file);
10808c9fbc29Smrg		    size+= tmp*SIZEOF(xkmPointDesc);
10818c9fbc29Smrg		}
10828c9fbc29Smrg	    }
10838c9fbc29Smrg	}
10848c9fbc29Smrg    }
10858c9fbc29Smrg    if (geom->sections) {
10868c9fbc29Smrg	XkbSectionPtr	section;
10878c9fbc29Smrg	for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
10888c9fbc29Smrg	    size+= WriteXKMGeomSection(file,result,section);
10898c9fbc29Smrg	}
10908c9fbc29Smrg    }
10918c9fbc29Smrg    if (geom->doodads) {
10928c9fbc29Smrg	XkbDoodadPtr	doodad;
10938c9fbc29Smrg	for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
10948c9fbc29Smrg	    size+= WriteXKMGeomDoodad(file,result,doodad);
10958c9fbc29Smrg	}
10968c9fbc29Smrg    }
10978c9fbc29Smrg    if (geom->key_aliases) {
10988c9fbc29Smrg	tmp= fwrite(geom->key_aliases,2*XkbKeyNameLength,geom->num_key_aliases,
10998c9fbc29Smrg									file);
11008c9fbc29Smrg	size+= tmp*(2*XkbKeyNameLength);
11018c9fbc29Smrg    }
11028c9fbc29Smrg    return size;
11038c9fbc29Smrg}
11048c9fbc29Smrg
11058c9fbc29Smrg/***====================================================================***/
11068c9fbc29Smrg
11078c9fbc29Smrg/*ARGSUSED*/
11088c9fbc29Smrgstatic int
11098c9fbc29SmrgGetXKMKeyNamesTOC(	XkbFileInfo *	result,
11108c9fbc29Smrg			XkmInfo *	info,
11118c9fbc29Smrg			int		max_toc,
11128c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
11138c9fbc29Smrg{
11148c9fbc29Smrgint	num_toc;
11158c9fbc29Smrgint	total_size;
11168c9fbc29Smrg
11178c9fbc29Smrg    total_size= num_toc=0;
11188c9fbc29Smrg    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
11198c9fbc29Smrg	num_toc++;
11208c9fbc29Smrg    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
11218c9fbc29Smrg	num_toc++;
11228c9fbc29Smrg    return num_toc;
11238c9fbc29Smrg}
11248c9fbc29Smrg
11258c9fbc29Smrg/*ARGSUSED*/
11268c9fbc29Smrgstatic int
11278c9fbc29SmrgGetXKMTypesTOC(	XkbFileInfo *	result,
11288c9fbc29Smrg		XkmInfo *	info,
11298c9fbc29Smrg		int		max_toc,
11308c9fbc29Smrg		xkmSectionInfo *toc_rtrn)
11318c9fbc29Smrg{
11328c9fbc29Smrgint	num_toc;
11338c9fbc29Smrgint	total_size;
11348c9fbc29Smrg
11358c9fbc29Smrg    total_size= num_toc=0;
11368c9fbc29Smrg    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
11378c9fbc29Smrg	num_toc++;
11388c9fbc29Smrg    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
11398c9fbc29Smrg	num_toc++;
11408c9fbc29Smrg    return num_toc;
11418c9fbc29Smrg}
11428c9fbc29Smrg
11438c9fbc29Smrg/*ARGSUSED*/
11448c9fbc29Smrgstatic int
11458c9fbc29SmrgGetXKMCompatMapTOC(	XkbFileInfo *	result,
11468c9fbc29Smrg			XkmInfo *	info,
11478c9fbc29Smrg			int		max_toc,
11488c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
11498c9fbc29Smrg{
11508c9fbc29Smrgint	num_toc;
11518c9fbc29Smrgint	total_size;
11528c9fbc29Smrg
11538c9fbc29Smrg    total_size= num_toc=0;
11548c9fbc29Smrg    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
11558c9fbc29Smrg	num_toc++;
11568c9fbc29Smrg    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
11578c9fbc29Smrg	num_toc++;
11588c9fbc29Smrg    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
11598c9fbc29Smrg	num_toc++;
11608c9fbc29Smrg    return num_toc;
11618c9fbc29Smrg}
11628c9fbc29Smrg
11638c9fbc29Smrg/*ARGSUSED*/
11648c9fbc29Smrgstatic int
11658c9fbc29SmrgGetXKMSemanticsTOC(	XkbFileInfo *	result,
11668c9fbc29Smrg			XkmInfo *	info,
11678c9fbc29Smrg			int		max_toc,
11688c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
11698c9fbc29Smrg{
11708c9fbc29Smrgint	num_toc;
11718c9fbc29Smrgint	total_size;
11728c9fbc29Smrg
11738c9fbc29Smrg    total_size= num_toc=0;
11748c9fbc29Smrg    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
11758c9fbc29Smrg	num_toc++;
11768c9fbc29Smrg    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
11778c9fbc29Smrg	num_toc++;
11788c9fbc29Smrg    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
11798c9fbc29Smrg	num_toc++;
11808c9fbc29Smrg    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
11818c9fbc29Smrg	num_toc++;
11828c9fbc29Smrg    return num_toc;
11838c9fbc29Smrg}
11848c9fbc29Smrg
11858c9fbc29Smrg/*ARGSUSED*/
11868c9fbc29Smrgstatic int
11878c9fbc29SmrgGetXKMLayoutTOC(	XkbFileInfo *	result,
11888c9fbc29Smrg			XkmInfo *	info,
11898c9fbc29Smrg			int		max_toc,
11908c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
11918c9fbc29Smrg{
11928c9fbc29Smrgint	num_toc;
11938c9fbc29Smrgint	total_size;
11948c9fbc29Smrg
11958c9fbc29Smrg    total_size= num_toc=0;
11968c9fbc29Smrg    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
11978c9fbc29Smrg	num_toc++;
11988c9fbc29Smrg    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
11998c9fbc29Smrg	num_toc++;
12008c9fbc29Smrg    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
12018c9fbc29Smrg	num_toc++;
12028c9fbc29Smrg    if (SizeXKMSymbols(result,info,&toc_rtrn[num_toc],&total_size))
12038c9fbc29Smrg	num_toc++;
12048c9fbc29Smrg    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
12058c9fbc29Smrg	num_toc++;
12068c9fbc29Smrg    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
12078c9fbc29Smrg	num_toc++;
12088c9fbc29Smrg    return num_toc;
12098c9fbc29Smrg}
12108c9fbc29Smrg
12118c9fbc29Smrg/*ARGSUSED*/
12128c9fbc29Smrgstatic int
12138c9fbc29SmrgGetXKMKeymapTOC(	XkbFileInfo *	result,
12148c9fbc29Smrg			XkmInfo *	info,
12158c9fbc29Smrg			int		max_toc,
12168c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
12178c9fbc29Smrg{
12188c9fbc29Smrgint	num_toc;
12198c9fbc29Smrgint	total_size;
12208c9fbc29Smrg
12218c9fbc29Smrg    total_size= num_toc=0;
12228c9fbc29Smrg    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
12238c9fbc29Smrg	num_toc++;
12248c9fbc29Smrg    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
12258c9fbc29Smrg	num_toc++;
12268c9fbc29Smrg    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
12278c9fbc29Smrg	num_toc++;
12288c9fbc29Smrg    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
12298c9fbc29Smrg	num_toc++;
12308c9fbc29Smrg    if (SizeXKMSymbols(result,info,&toc_rtrn[num_toc],&total_size))
12318c9fbc29Smrg	num_toc++;
12328c9fbc29Smrg    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
12338c9fbc29Smrg	num_toc++;
12348c9fbc29Smrg    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
12358c9fbc29Smrg	num_toc++;
12368c9fbc29Smrg    return num_toc;
12378c9fbc29Smrg}
12388c9fbc29Smrg
12398c9fbc29Smrg/*ARGSUSED*/
12408c9fbc29Smrgstatic int
12418c9fbc29SmrgGetXKMGeometryTOC(	XkbFileInfo *	result,
12428c9fbc29Smrg			XkmInfo *	info,
12438c9fbc29Smrg			int		max_toc,
12448c9fbc29Smrg			xkmSectionInfo *toc_rtrn)
12458c9fbc29Smrg{
12468c9fbc29Smrgint	num_toc;
12478c9fbc29Smrgint	total_size;
12488c9fbc29Smrg
12498c9fbc29Smrg    total_size= num_toc=0;
12508c9fbc29Smrg    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
12518c9fbc29Smrg	num_toc++;
12528c9fbc29Smrg    return num_toc;
12538c9fbc29Smrg}
12548c9fbc29Smrg
12558c9fbc29Smrgstatic Bool
12568c9fbc29SmrgWriteXKMFile(	FILE *		file,
12578c9fbc29Smrg		XkbFileInfo *	result,
12588c9fbc29Smrg		int		num_toc,
12598c9fbc29Smrg		xkmSectionInfo *toc,
12608c9fbc29Smrg		XkmInfo *	info)
12618c9fbc29Smrg{
12628c9fbc29Smrgregister int 	i;
12638c9fbc29Smrgunsigned	tmp,size,total= 0;
12648c9fbc29Smrg
12658c9fbc29Smrg    for (i=0;i<num_toc;i++) {
12668c9fbc29Smrg	tmp= fwrite(&toc[i],SIZEOF(xkmSectionInfo),1,file);
12678c9fbc29Smrg	total+= tmp*SIZEOF(xkmSectionInfo);
12688c9fbc29Smrg	switch (toc[i].type) {
12698c9fbc29Smrg	    case XkmTypesIndex:
12708c9fbc29Smrg		size= WriteXKMKeyTypes(file,result);
12718c9fbc29Smrg		break;
12728c9fbc29Smrg	    case XkmCompatMapIndex:
12738c9fbc29Smrg		size= WriteXKMCompatMap(file,result,info);
12748c9fbc29Smrg		break;
12758c9fbc29Smrg	    case XkmSymbolsIndex:
12768c9fbc29Smrg		size= WriteXKMSymbols(file,result,info);
12778c9fbc29Smrg		break;
12788c9fbc29Smrg	    case XkmIndicatorsIndex:
12798c9fbc29Smrg		size= WriteXKMIndicators(file,result,info);
12808c9fbc29Smrg		break;
12818c9fbc29Smrg	    case XkmKeyNamesIndex:
12828c9fbc29Smrg		size= WriteXKMKeycodes(file,result);
12838c9fbc29Smrg		break;
12848c9fbc29Smrg	    case XkmGeometryIndex:
12858c9fbc29Smrg		size= WriteXKMGeometry(file,result);
12868c9fbc29Smrg		break;
12878c9fbc29Smrg	    case XkmVirtualModsIndex:
12888c9fbc29Smrg		size= WriteXKMVirtualMods(file,result,info);
12898c9fbc29Smrg		break;
12908c9fbc29Smrg	    default:
12918c9fbc29Smrg		_XkbLibError(_XkbErrIllegalTOCType,"WriteXKMFile",toc[i].type);
12928c9fbc29Smrg		return False;
12938c9fbc29Smrg	}
12948c9fbc29Smrg	size+= SIZEOF(xkmSectionInfo);
12958c9fbc29Smrg	if (size!=toc[i].size) {
12968c9fbc29Smrg	    _XkbLibError(_XkbErrBadLength,XkbConfigText(toc[i].type,XkbMessage),
12978c9fbc29Smrg	    						size-toc[i].size);
12988c9fbc29Smrg	    return False;
12998c9fbc29Smrg	}
13008c9fbc29Smrg    }
13018c9fbc29Smrg    return True;
13028c9fbc29Smrg}
13038c9fbc29Smrg
13048c9fbc29Smrg
13058c9fbc29Smrg#define	MAX_TOC	16
13068c9fbc29Smrg
13078c9fbc29SmrgBool
13088c9fbc29SmrgXkbWriteXKMFile(FILE *out,XkbFileInfo *result)
13098c9fbc29Smrg{
13108c9fbc29SmrgBool	 		ok;
13118c9fbc29SmrgXkbDescPtr		xkb;
13128c9fbc29SmrgXkmInfo			info;
13138c9fbc29Smrgint			size_toc,i;
13148c9fbc29Smrgunsigned		hdr,present;
13158c9fbc29SmrgxkmFileInfo		fileInfo;
13168c9fbc29SmrgxkmSectionInfo		toc[MAX_TOC];
13178c9fbc29Smrgint			(*getTOC)(
13188c9fbc29Smrg	XkbFileInfo *	/* result */,
13198c9fbc29Smrg	XkmInfo *	/* info */,
13208c9fbc29Smrg	int		/* max_to */,
13218c9fbc29Smrg	xkmSectionInfo */* toc_rtrn */
13228c9fbc29Smrg);
13238c9fbc29Smrg
13248c9fbc29Smrg    switch (result->type) {
13258c9fbc29Smrg	case XkmKeyNamesIndex:
13268c9fbc29Smrg	    getTOC= GetXKMKeyNamesTOC;
13278c9fbc29Smrg	    break;
13288c9fbc29Smrg	case XkmTypesIndex:
13298c9fbc29Smrg	    getTOC= GetXKMTypesTOC;
13308c9fbc29Smrg	    break;
13318c9fbc29Smrg	case XkmCompatMapIndex:
13328c9fbc29Smrg	    getTOC= GetXKMCompatMapTOC;
13338c9fbc29Smrg	    break;
13348c9fbc29Smrg	case XkmSemanticsFile:
13358c9fbc29Smrg	    getTOC= GetXKMSemanticsTOC;
13368c9fbc29Smrg	    break;
13378c9fbc29Smrg	case XkmLayoutFile:
13388c9fbc29Smrg	    getTOC= GetXKMLayoutTOC;
13398c9fbc29Smrg	    break;
13408c9fbc29Smrg	case XkmKeymapFile:
13418c9fbc29Smrg	    getTOC= GetXKMKeymapTOC;
13428c9fbc29Smrg	    break;
13438c9fbc29Smrg	case XkmGeometryFile:
13448c9fbc29Smrg	case XkmGeometryIndex:
13458c9fbc29Smrg	    getTOC= GetXKMGeometryTOC;
13468c9fbc29Smrg	    break;
13478c9fbc29Smrg	default:
13488c9fbc29Smrg	    _XkbLibError(_XkbErrIllegalContents,
13498c9fbc29Smrg	    			XkbConfigText(result->type,XkbMessage),0);
13508c9fbc29Smrg	    return False;
13518c9fbc29Smrg    }
13528c9fbc29Smrg    xkb= result->xkb;
13538c9fbc29Smrg
13548c9fbc29Smrg    bzero((char *)&info,sizeof(XkmInfo));
13558c9fbc29Smrg    size_toc= (*getTOC)(result,&info,MAX_TOC,toc);
13568c9fbc29Smrg    if (size_toc<1) {
13578c9fbc29Smrg	_XkbLibError(_XkbErrEmptyFile,"XkbWriteXKMFile",0);
13588c9fbc29Smrg	return False;
13598c9fbc29Smrg    }
13608c9fbc29Smrg    if (out==NULL) {
13618c9fbc29Smrg	_XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXKMFile",0);
13628c9fbc29Smrg	return False;
13638c9fbc29Smrg    }
13648c9fbc29Smrg    for (i=present=0;i<size_toc;i++) {
13658c9fbc29Smrg	toc[i].offset+= 4+SIZEOF(xkmFileInfo);
13668c9fbc29Smrg	toc[i].offset+= (size_toc*SIZEOF(xkmSectionInfo));
13678c9fbc29Smrg	if (toc[i].type<=XkmLastIndex) {
13688c9fbc29Smrg	    present|= (1<<toc[i].type);
13698c9fbc29Smrg	}
13708c9fbc29Smrg#ifdef DEBUG
13718c9fbc29Smrg	else {
13728c9fbc29Smrg	    fprintf(stderr,"Illegal section type %d\n",toc[i].type);
13738c9fbc29Smrg	    fprintf(stderr,"Ignored\n");
13748c9fbc29Smrg	}
13758c9fbc29Smrg#endif
13768c9fbc29Smrg    }
13778c9fbc29Smrg    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
13788c9fbc29Smrg    xkmPutCARD32(out,(unsigned long)hdr);
13798c9fbc29Smrg    fileInfo.type= result->type;
13808c9fbc29Smrg    fileInfo.min_kc= xkb->min_key_code;
13818c9fbc29Smrg    fileInfo.max_kc= xkb->max_key_code;
13828c9fbc29Smrg    fileInfo.num_toc= size_toc;
13838c9fbc29Smrg    fileInfo.present= present;
13848c9fbc29Smrg    fileInfo.pad= 0;
13858c9fbc29Smrg    fwrite(&fileInfo,SIZEOF(xkmFileInfo),1,out);
13868c9fbc29Smrg    fwrite(toc,SIZEOF(xkmSectionInfo),size_toc,out);
13878c9fbc29Smrg    ok= WriteXKMFile(out,result,size_toc,toc,&info);
13888c9fbc29Smrg    return ok;
13898c9fbc29Smrg}
1390