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