1706f2543Smrg/************************************************************
2706f2543Smrg Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3706f2543Smrg
4706f2543Smrg Permission to use, copy, modify, and distribute this
5706f2543Smrg software and its documentation for any purpose and without
6706f2543Smrg fee is hereby granted, provided that the above copyright
7706f2543Smrg notice appear in all copies and that both that copyright
8706f2543Smrg notice and this permission notice appear in supporting
9706f2543Smrg documentation, and that the name of Silicon Graphics not be
10706f2543Smrg used in advertising or publicity pertaining to distribution
11706f2543Smrg of the software without specific prior written permission.
12706f2543Smrg Silicon Graphics makes no representation about the suitability
13706f2543Smrg of this software for any purpose. It is provided "as is"
14706f2543Smrg without any express or implied warranty.
15706f2543Smrg
16706f2543Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17706f2543Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18706f2543Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19706f2543Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20706f2543Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22706f2543Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23706f2543Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg
25706f2543Smrg ********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <stdio.h>
32706f2543Smrg
33706f2543Smrg#include <X11/Xos.h>
34706f2543Smrg#include <X11/Xfuncs.h>
35706f2543Smrg
36706f2543Smrg#include <X11/X.h>
37706f2543Smrg#include <X11/Xproto.h>
38706f2543Smrg#include <X11/keysym.h>
39706f2543Smrg#include <X11/extensions/XKMformat.h>
40706f2543Smrg#include "misc.h"
41706f2543Smrg#include "inputstr.h"
42706f2543Smrg#include "xkbstr.h"
43706f2543Smrg#include "xkbsrv.h"
44706f2543Smrg#include "xkbgeom.h"
45706f2543Smrg
46706f2543SmrgAtom
47706f2543SmrgXkbInternAtom(char *str,Bool only_if_exists)
48706f2543Smrg{
49706f2543Smrg    if (str==NULL)
50706f2543Smrg	return None;
51706f2543Smrg    return MakeAtom(str,strlen(str),!only_if_exists);
52706f2543Smrg}
53706f2543Smrg
54706f2543Smrgchar *
55706f2543Smrg_XkbDupString(const char *str)
56706f2543Smrg{
57706f2543Smrgchar *new;
58706f2543Smrg
59706f2543Smrg   if (str==NULL)
60706f2543Smrg	return NULL;
61706f2543Smrg   new= calloc(strlen(str)+1,sizeof(char));
62706f2543Smrg   if (new)
63706f2543Smrg	strcpy(new,str);
64706f2543Smrg   return new;
65706f2543Smrg}
66706f2543Smrg
67706f2543Smrg/***====================================================================***/
68706f2543Smrg
69706f2543Smrgstatic void *
70706f2543SmrgXkmInsureSize(void *oldPtr,int oldCount,int *newCountRtrn,int elemSize)
71706f2543Smrg{
72706f2543Smrgint	newCount= *newCountRtrn;
73706f2543Smrg
74706f2543Smrg    if (oldPtr==NULL) {
75706f2543Smrg	if (newCount==0)
76706f2543Smrg	    return NULL;
77706f2543Smrg	oldPtr= calloc(newCount,elemSize);
78706f2543Smrg    }
79706f2543Smrg    else if (oldCount<newCount) {
80706f2543Smrg	oldPtr= realloc(oldPtr,newCount*elemSize);
81706f2543Smrg	if (oldPtr!=NULL) {
82706f2543Smrg	    char *tmp= (char *)oldPtr;
83706f2543Smrg	    memset(&tmp[oldCount*elemSize], 0, (newCount-oldCount)*elemSize);
84706f2543Smrg	}
85706f2543Smrg    }
86706f2543Smrg    else if (newCount<oldCount) {
87706f2543Smrg	*newCountRtrn= oldCount;
88706f2543Smrg    }
89706f2543Smrg    return oldPtr;
90706f2543Smrg}
91706f2543Smrg
92706f2543Smrg#define	XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t))))
93706f2543Smrg
94706f2543Smrgstatic CARD8
95706f2543SmrgXkmGetCARD8(FILE *file,int *pNRead)
96706f2543Smrg{
97706f2543Smrgint	tmp;
98706f2543Smrg    tmp= getc(file);
99706f2543Smrg    if (pNRead&&(tmp!=EOF))
100706f2543Smrg	(*pNRead)+= 1;
101706f2543Smrg    return tmp;
102706f2543Smrg}
103706f2543Smrg
104706f2543Smrgstatic CARD16
105706f2543SmrgXkmGetCARD16(FILE *file,int *pNRead)
106706f2543Smrg{
107706f2543SmrgCARD16		val;
108706f2543Smrg
109706f2543Smrg    if ((fread(&val,2,1,file)==1)&&(pNRead))
110706f2543Smrg	(*pNRead)+= 2;
111706f2543Smrg    return val;
112706f2543Smrg}
113706f2543Smrg
114706f2543Smrgstatic CARD32
115706f2543SmrgXkmGetCARD32(FILE *file,int *pNRead)
116706f2543Smrg{
117706f2543SmrgCARD32	val;
118706f2543Smrg
119706f2543Smrg    if ((fread(&val,4,1,file)==1)&&(pNRead))
120706f2543Smrg	(*pNRead)+= 4;
121706f2543Smrg    return val;
122706f2543Smrg}
123706f2543Smrg
124706f2543Smrgstatic int
125706f2543SmrgXkmSkipPadding(FILE *file,unsigned pad)
126706f2543Smrg{
127706f2543Smrgregister int	i,nRead=0;
128706f2543Smrg
129706f2543Smrg    for (i=0;i<pad;i++) {
130706f2543Smrg	if (getc(file)!=EOF)
131706f2543Smrg	    nRead++;
132706f2543Smrg    }
133706f2543Smrg    return nRead;
134706f2543Smrg}
135706f2543Smrg
136706f2543Smrgstatic int
137706f2543SmrgXkmGetCountedString(FILE *file,char *str,int max_len)
138706f2543Smrg{
139706f2543Smrgint	count,nRead=0;
140706f2543Smrg
141706f2543Smrg    count= XkmGetCARD16(file,&nRead);
142706f2543Smrg    if (count>0) {
143706f2543Smrg	int tmp;
144706f2543Smrg	if (count>max_len) {
145706f2543Smrg	    tmp= fread(str,1,max_len,file);
146706f2543Smrg	    while (tmp<count) {
147706f2543Smrg		if ((getc(file))!=EOF)
148706f2543Smrg		     tmp++;
149706f2543Smrg		else break;
150706f2543Smrg	    }
151706f2543Smrg	}
152706f2543Smrg	else {
153706f2543Smrg	    tmp= fread(str,1,count,file);
154706f2543Smrg	}
155706f2543Smrg	nRead+= tmp;
156706f2543Smrg    }
157706f2543Smrg    if (count>=max_len)	str[max_len-1]= '\0';
158706f2543Smrg    else		str[count]= '\0';
159706f2543Smrg    count= XkbPaddedSize(nRead)-nRead;
160706f2543Smrg    if (count>0)
161706f2543Smrg	nRead+= XkmSkipPadding(file,count);
162706f2543Smrg    return nRead;
163706f2543Smrg}
164706f2543Smrg
165706f2543Smrg/***====================================================================***/
166706f2543Smrg
167706f2543Smrgstatic int
168706f2543SmrgReadXkmVirtualMods(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
169706f2543Smrg{
170706f2543Smrgregister unsigned int i,bit;
171706f2543Smrgunsigned int	bound,named,tmp;
172706f2543Smrgint		nRead=0;
173706f2543Smrg
174706f2543Smrg    if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) {
175706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
176706f2543Smrg	return -1;
177706f2543Smrg    }
178706f2543Smrg    bound= XkmGetCARD16(file,&nRead);
179706f2543Smrg    named= XkmGetCARD16(file,&nRead);
180706f2543Smrg    for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
181706f2543Smrg	if (bound&bit) {
182706f2543Smrg	    xkb->server->vmods[i]= XkmGetCARD8(file,&nRead);
183706f2543Smrg	    if (changes)
184706f2543Smrg		changes->map.vmods|= bit;
185706f2543Smrg	    tmp++;
186706f2543Smrg	}
187706f2543Smrg    }
188706f2543Smrg    if ((i= XkbPaddedSize(tmp)-tmp)>0)
189706f2543Smrg	nRead+= XkmSkipPadding(file,i);
190706f2543Smrg    if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) {
191706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
192706f2543Smrg	return -1;
193706f2543Smrg    }
194706f2543Smrg    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
195706f2543Smrg	char name[100];
196706f2543Smrg	if (named&bit) {
197706f2543Smrg	    if (nRead+=XkmGetCountedString(file,name,100)) {
198706f2543Smrg		xkb->names->vmods[i]= XkbInternAtom(name,FALSE);
199706f2543Smrg		if (changes)
200706f2543Smrg		    changes->names.changed_vmods|= bit;
201706f2543Smrg	    }
202706f2543Smrg	}
203706f2543Smrg    }
204706f2543Smrg    return nRead;
205706f2543Smrg}
206706f2543Smrg
207706f2543Smrg/***====================================================================***/
208706f2543Smrg
209706f2543Smrgstatic int
210706f2543SmrgReadXkmKeycodes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
211706f2543Smrg{
212706f2543Smrgregister int	i;
213706f2543Smrgunsigned	minKC,maxKC,nAl;
214706f2543Smrgint		nRead=0;
215706f2543Smrgchar 		name[100];
216706f2543SmrgXkbKeyNamePtr	pN;
217706f2543Smrg
218706f2543Smrg    name[0]= '\0';
219706f2543Smrg    nRead+= XkmGetCountedString(file,name,100);
220706f2543Smrg    minKC= XkmGetCARD8(file,&nRead);
221706f2543Smrg    maxKC= XkmGetCARD8(file,&nRead);
222706f2543Smrg    if (xkb->min_key_code==0) {
223706f2543Smrg	xkb->min_key_code= minKC;
224706f2543Smrg	xkb->max_key_code= maxKC;
225706f2543Smrg    }
226706f2543Smrg    else {
227706f2543Smrg	if (minKC<xkb->min_key_code)
228706f2543Smrg	    xkb->min_key_code= minKC;
229706f2543Smrg	if (maxKC>xkb->max_key_code) {
230706f2543Smrg	    _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC);
231706f2543Smrg	    return -1;
232706f2543Smrg	}
233706f2543Smrg    }
234706f2543Smrg    nAl= XkmGetCARD8(file,&nRead);
235706f2543Smrg    nRead+= XkmSkipPadding(file,1);
236706f2543Smrg
237706f2543Smrg#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask)
238706f2543Smrg    if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) {
239706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
240706f2543Smrg	return -1;
241706f2543Smrg    }
242706f2543Smrg    if (name[0]!='\0') {
243706f2543Smrg	xkb->names->keycodes= XkbInternAtom(name,FALSE);
244706f2543Smrg    }
245706f2543Smrg
246706f2543Smrg    for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) {
247706f2543Smrg	if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) {
248706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
249706f2543Smrg	    return -1;
250706f2543Smrg	}
251706f2543Smrg	nRead+= XkbKeyNameLength;
252706f2543Smrg    }
253706f2543Smrg    if (nAl>0) {
254706f2543Smrg	XkbKeyAliasPtr	pAl;
255706f2543Smrg	for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) {
256706f2543Smrg	    int tmp;
257706f2543Smrg	    tmp= fread(pAl,1,2*XkbKeyNameLength,file);
258706f2543Smrg	    if (tmp!=2*XkbKeyNameLength) {
259706f2543Smrg		_XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
260706f2543Smrg		return -1;
261706f2543Smrg	    }
262706f2543Smrg	    nRead+= 2*XkbKeyNameLength;
263706f2543Smrg	}
264706f2543Smrg	if (changes)
265706f2543Smrg	    changes->names.changed|= XkbKeyAliasesMask;
266706f2543Smrg    }
267706f2543Smrg    if (changes)
268706f2543Smrg	changes->names.changed|= XkbKeyNamesMask;
269706f2543Smrg    return nRead;
270706f2543Smrg}
271706f2543Smrg
272706f2543Smrg/***====================================================================***/
273706f2543Smrg
274706f2543Smrgstatic int
275706f2543SmrgReadXkmKeyTypes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
276706f2543Smrg{
277706f2543Smrgregister unsigned	i,n;
278706f2543Smrgunsigned		num_types;
279706f2543Smrgint			nRead=0;
280706f2543Smrgint			tmp;
281706f2543SmrgXkbKeyTypePtr		type;
282706f2543SmrgxkmKeyTypeDesc		wire;
283706f2543SmrgXkbKTMapEntryPtr	entry;
284706f2543SmrgxkmKTMapEntryDesc	wire_entry;
285706f2543Smrgchar 			buf[100];
286706f2543Smrg
287706f2543Smrg    if ((tmp= XkmGetCountedString(file,buf,100))<1) {
288706f2543Smrg	_XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
289706f2543Smrg	return -1;
290706f2543Smrg    }
291706f2543Smrg    nRead+= tmp;
292706f2543Smrg    if (buf[0]!='\0') {
293706f2543Smrg	if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) {
294706f2543Smrg	    _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
295706f2543Smrg	    return -1;
296706f2543Smrg        }
297706f2543Smrg	xkb->names->types= XkbInternAtom(buf,FALSE);
298706f2543Smrg    }
299706f2543Smrg    num_types= XkmGetCARD16(file,&nRead);
300706f2543Smrg    nRead+= XkmSkipPadding(file,2);
301706f2543Smrg    if (num_types<1)
302706f2543Smrg	return nRead;
303706f2543Smrg    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) {
304706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
305706f2543Smrg	return nRead;
306706f2543Smrg    }
307706f2543Smrg    xkb->map->num_types= num_types;
308706f2543Smrg    if (num_types<XkbNumRequiredTypes) {
309706f2543Smrg	_XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0);
310706f2543Smrg	return -1;
311706f2543Smrg    }
312706f2543Smrg    type= xkb->map->types;
313706f2543Smrg    for (i=0;i<num_types;i++,type++) {
314706f2543Smrg	if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) {
315706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
316706f2543Smrg	    return -1;
317706f2543Smrg	}
318706f2543Smrg	nRead+= SIZEOF(xkmKeyTypeDesc);
319706f2543Smrg	if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))||
320706f2543Smrg	    (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)||
321706f2543Smrg	     ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) {
322706f2543Smrg	    _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i);
323706f2543Smrg	    return -1;
324706f2543Smrg	}
325706f2543Smrg	tmp= wire.nMapEntries;
326706f2543Smrg	XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec);
327706f2543Smrg	if ((wire.nMapEntries>0)&&(type->map==NULL)) {
328706f2543Smrg	    _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries);
329706f2543Smrg	    return -1;
330706f2543Smrg	}
331706f2543Smrg	for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) {
332706f2543Smrg	    if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) {
333706f2543Smrg		_XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
334706f2543Smrg		return -1;
335706f2543Smrg	    }
336706f2543Smrg	    nRead+= SIZEOF(xkmKTMapEntryDesc);
337706f2543Smrg	    entry->active= (wire_entry.virtualMods==0);
338706f2543Smrg	    entry->level= wire_entry.level;
339706f2543Smrg	    entry->mods.mask= wire_entry.realMods;
340706f2543Smrg	    entry->mods.real_mods= wire_entry.realMods;
341706f2543Smrg	    entry->mods.vmods= wire_entry.virtualMods;
342706f2543Smrg	}
343706f2543Smrg	nRead+= XkmGetCountedString(file,buf,100);
344706f2543Smrg	if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))||
345706f2543Smrg	    ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))||
346706f2543Smrg	    ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))||
347706f2543Smrg	    ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) {
348706f2543Smrg	   _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0);
349706f2543Smrg	   return -1;
350706f2543Smrg	}
351706f2543Smrg	if (buf[0]!='\0') {
352706f2543Smrg	     type->name= XkbInternAtom(buf,FALSE);
353706f2543Smrg	}
354706f2543Smrg	else type->name= None;
355706f2543Smrg
356706f2543Smrg	if (wire.preserve) {
357706f2543Smrg	    xkmModsDesc	p_entry;
358706f2543Smrg	    XkbModsPtr	pre;
359706f2543Smrg	    XkmInsureTypedSize(type->preserve,type->map_count,&tmp,
360706f2543Smrg						XkbModsRec);
361706f2543Smrg	    if (type->preserve==NULL) {
362706f2543Smrg		_XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
363706f2543Smrg		return -1;
364706f2543Smrg	    }
365706f2543Smrg	    for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) {
366706f2543Smrg		if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) {
367706f2543Smrg		    _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
368706f2543Smrg		    return -1;
369706f2543Smrg		}
370706f2543Smrg		nRead+= SIZEOF(xkmModsDesc);
371706f2543Smrg		pre->mask= p_entry.realMods;
372706f2543Smrg		pre->real_mods= p_entry.realMods;
373706f2543Smrg		pre->vmods= p_entry.virtualMods;
374706f2543Smrg	    }
375706f2543Smrg	}
376706f2543Smrg	if (wire.nLevelNames>0) {
377706f2543Smrg	    int width= wire.numLevels;
378706f2543Smrg	    if (wire.nLevelNames>(unsigned)width) {
379706f2543Smrg		_XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
380706f2543Smrg		return -1;
381706f2543Smrg	    }
382706f2543Smrg	    XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom);
383706f2543Smrg	    if (type->level_names!=NULL) {
384706f2543Smrg		for (n=0;n<wire.nLevelNames;n++) {
385706f2543Smrg		    if ((tmp=XkmGetCountedString(file,buf,100))<1)
386706f2543Smrg			return -1;
387706f2543Smrg		    nRead+= tmp;
388706f2543Smrg		    if (strlen(buf)==0)
389706f2543Smrg			 type->level_names[n]= None;
390706f2543Smrg		    else type->level_names[n]= XkbInternAtom(buf,0);
391706f2543Smrg		}
392706f2543Smrg	    }
393706f2543Smrg	}
394706f2543Smrg	type->mods.mask= wire.realMods;
395706f2543Smrg	type->mods.real_mods= wire.realMods;
396706f2543Smrg	type->mods.vmods= wire.virtualMods;
397706f2543Smrg	type->num_levels= wire.numLevels;
398706f2543Smrg	type->map_count= wire.nMapEntries;
399706f2543Smrg    }
400706f2543Smrg    if (changes) {
401706f2543Smrg	changes->map.changed|= XkbKeyTypesMask;
402706f2543Smrg	changes->map.first_type= 0;
403706f2543Smrg	changes->map.num_types= xkb->map->num_types;
404706f2543Smrg    }
405706f2543Smrg    return nRead;
406706f2543Smrg}
407706f2543Smrg
408706f2543Smrg/***====================================================================***/
409706f2543Smrg
410706f2543Smrgstatic int
411706f2543SmrgReadXkmCompatMap(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
412706f2543Smrg{
413706f2543Smrgregister int		i;
414706f2543Smrgunsigned		num_si,groups;
415706f2543Smrgchar 			name[100];
416706f2543SmrgXkbSymInterpretPtr	interp;
417706f2543SmrgxkmSymInterpretDesc	wire;
418706f2543Smrgunsigned		tmp;
419706f2543Smrgint			nRead=0;
420706f2543SmrgXkbCompatMapPtr		compat;
421706f2543SmrgXkbAction               *act;
422706f2543Smrg
423706f2543Smrg    if ((tmp= XkmGetCountedString(file,name,100))<1) {
424706f2543Smrg	_XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0);
425706f2543Smrg	return -1;
426706f2543Smrg    }
427706f2543Smrg    nRead+= tmp;
428706f2543Smrg    if (name[0]!='\0') {
429706f2543Smrg	if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) {
430706f2543Smrg	    _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0);
431706f2543Smrg	    return -1;
432706f2543Smrg	}
433706f2543Smrg	xkb->names->compat= XkbInternAtom(name,FALSE);
434706f2543Smrg    }
435706f2543Smrg    num_si= XkmGetCARD16(file,&nRead);
436706f2543Smrg    groups= XkmGetCARD8(file,&nRead);
437706f2543Smrg    nRead+= XkmSkipPadding(file,1);
438706f2543Smrg    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success)
439706f2543Smrg	return -1;
440706f2543Smrg    compat= xkb->compat;
441706f2543Smrg    compat->num_si= num_si;
442706f2543Smrg    interp= compat->sym_interpret;
443706f2543Smrg    for (i=0;i<num_si;i++,interp++) {
444706f2543Smrg	tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
445706f2543Smrg	nRead+= tmp*SIZEOF(xkmSymInterpretDesc);
446706f2543Smrg	interp->sym= wire.sym;
447706f2543Smrg	interp->mods= wire.mods;
448706f2543Smrg	interp->match= wire.match;
449706f2543Smrg	interp->virtual_mod= wire.virtualMod;
450706f2543Smrg	interp->flags= wire.flags;
451706f2543Smrg	interp->act.type= wire.actionType;
452706f2543Smrg        act = (XkbAction *) &interp->act;
453706f2543Smrg
454706f2543Smrg        switch (interp->act.type) {
455706f2543Smrg        case XkbSA_SetMods:
456706f2543Smrg        case XkbSA_LatchMods:
457706f2543Smrg        case XkbSA_LockMods:
458706f2543Smrg            act->mods.flags = wire.actionData[0];
459706f2543Smrg            act->mods.mask = wire.actionData[1];
460706f2543Smrg            act->mods.real_mods = wire.actionData[2];
461706f2543Smrg            act->mods.vmods1 = wire.actionData[3];
462706f2543Smrg            act->mods.vmods2 = wire.actionData[4];
463706f2543Smrg            break;
464706f2543Smrg        case XkbSA_SetGroup:
465706f2543Smrg        case XkbSA_LatchGroup:
466706f2543Smrg        case XkbSA_LockGroup:
467706f2543Smrg            act->group.flags = wire.actionData[0];
468706f2543Smrg            act->group.group_XXX = wire.actionData[1];
469706f2543Smrg            break;
470706f2543Smrg        case XkbSA_MovePtr:
471706f2543Smrg            act->ptr.flags = wire.actionData[0];
472706f2543Smrg            act->ptr.high_XXX = wire.actionData[1];
473706f2543Smrg            act->ptr.low_XXX = wire.actionData[2];
474706f2543Smrg            act->ptr.high_YYY = wire.actionData[3];
475706f2543Smrg            act->ptr.low_YYY = wire.actionData[4];
476706f2543Smrg            break;
477706f2543Smrg        case XkbSA_PtrBtn:
478706f2543Smrg        case XkbSA_LockPtrBtn:
479706f2543Smrg            act->btn.flags = wire.actionData[0];
480706f2543Smrg            act->btn.count = wire.actionData[1];
481706f2543Smrg            act->btn.button = wire.actionData[2];
482706f2543Smrg            break;
483706f2543Smrg        case XkbSA_DeviceBtn:
484706f2543Smrg        case XkbSA_LockDeviceBtn:
485706f2543Smrg            act->devbtn.flags = wire.actionData[0];
486706f2543Smrg            act->devbtn.count = wire.actionData[1];
487706f2543Smrg            act->devbtn.button = wire.actionData[2];
488706f2543Smrg            act->devbtn.device = wire.actionData[3];
489706f2543Smrg            break;
490706f2543Smrg        case XkbSA_SetPtrDflt:
491706f2543Smrg            act->dflt.flags = wire.actionData[0];
492706f2543Smrg            act->dflt.affect = wire.actionData[1];
493706f2543Smrg            act->dflt.valueXXX = wire.actionData[2];
494706f2543Smrg            break;
495706f2543Smrg        case XkbSA_ISOLock:
496706f2543Smrg            act->iso.flags = wire.actionData[0];
497706f2543Smrg            act->iso.mask = wire.actionData[1];
498706f2543Smrg            act->iso.real_mods = wire.actionData[2];
499706f2543Smrg            act->iso.group_XXX = wire.actionData[3];
500706f2543Smrg            act->iso.affect = wire.actionData[4];
501706f2543Smrg            act->iso.vmods1 = wire.actionData[5];
502706f2543Smrg            act->iso.vmods2 = wire.actionData[6];
503706f2543Smrg            break;
504706f2543Smrg        case XkbSA_SwitchScreen:
505706f2543Smrg            act->screen.flags = wire.actionData[0];
506706f2543Smrg            act->screen.screenXXX = wire.actionData[1];
507706f2543Smrg            break;
508706f2543Smrg        case XkbSA_SetControls:
509706f2543Smrg        case XkbSA_LockControls:
510706f2543Smrg            act->ctrls.flags = wire.actionData[0];
511706f2543Smrg            act->ctrls.ctrls3 = wire.actionData[1];
512706f2543Smrg            act->ctrls.ctrls2 = wire.actionData[2];
513706f2543Smrg            act->ctrls.ctrls1 = wire.actionData[3];
514706f2543Smrg            act->ctrls.ctrls0 = wire.actionData[4];
515706f2543Smrg            break;
516706f2543Smrg        case XkbSA_RedirectKey:
517706f2543Smrg            act->redirect.new_key = wire.actionData[0];
518706f2543Smrg            act->redirect.mods_mask = wire.actionData[1];
519706f2543Smrg            act->redirect.mods = wire.actionData[2];
520706f2543Smrg            act->redirect.vmods_mask0 = wire.actionData[3];
521706f2543Smrg            act->redirect.vmods_mask1 = wire.actionData[4];
522706f2543Smrg            act->redirect.vmods0 = wire.actionData[4];
523706f2543Smrg            act->redirect.vmods1 = wire.actionData[5];
524706f2543Smrg            break;
525706f2543Smrg        case XkbSA_DeviceValuator:
526706f2543Smrg            act->devval.device = wire.actionData[0];
527706f2543Smrg            act->devval.v1_what = wire.actionData[1];
528706f2543Smrg            act->devval.v1_ndx = wire.actionData[2];
529706f2543Smrg            act->devval.v1_value = wire.actionData[3];
530706f2543Smrg            act->devval.v2_what = wire.actionData[4];
531706f2543Smrg            act->devval.v2_ndx = wire.actionData[5];
532706f2543Smrg            act->devval.v2_what = wire.actionData[6];
533706f2543Smrg            break;
534706f2543Smrg
535706f2543Smrg        case XkbSA_XFree86Private:
536706f2543Smrg            /* copy the kind of action */
537706f2543Smrg            memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize);
538706f2543Smrg            break ;
539706f2543Smrg
540706f2543Smrg        case XkbSA_Terminate:
541706f2543Smrg            /* no args, kinda (note: untrue for xfree86). */
542706f2543Smrg            break;
543706f2543Smrg        case XkbSA_ActionMessage:
544706f2543Smrg            /* unsupported. */
545706f2543Smrg            break;
546706f2543Smrg        }
547706f2543Smrg    }
548706f2543Smrg    if ((num_si>0)&&(changes)) {
549706f2543Smrg	changes->compat.first_si= 0;
550706f2543Smrg	changes->compat.num_si= num_si;
551706f2543Smrg    }
552706f2543Smrg    if (groups) {
553706f2543Smrg	register unsigned bit;
554706f2543Smrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
555706f2543Smrg	    xkmModsDesc	md;
556706f2543Smrg	    if (groups&bit) {
557706f2543Smrg		tmp= fread(&md,SIZEOF(xkmModsDesc),1,file);
558706f2543Smrg		nRead+= tmp*SIZEOF(xkmModsDesc);
559706f2543Smrg		xkb->compat->groups[i].real_mods= md.realMods;
560706f2543Smrg		xkb->compat->groups[i].vmods= md.virtualMods;
561706f2543Smrg		if (md.virtualMods != 0) {
562706f2543Smrg		    unsigned mask;
563706f2543Smrg		    if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask))
564706f2543Smrg			xkb->compat->groups[i].mask= md.realMods|mask;
565706f2543Smrg		}
566706f2543Smrg		else xkb->compat->groups[i].mask= md.realMods;
567706f2543Smrg	    }
568706f2543Smrg	}
569706f2543Smrg	if (changes)
570706f2543Smrg	    changes->compat.changed_groups|= groups;
571706f2543Smrg    }
572706f2543Smrg    return nRead;
573706f2543Smrg}
574706f2543Smrg
575706f2543Smrgstatic int
576706f2543SmrgReadXkmIndicators(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
577706f2543Smrg{
578706f2543Smrgregister unsigned	nLEDs;
579706f2543SmrgxkmIndicatorMapDesc	wire;
580706f2543Smrgchar			buf[100];
581706f2543Smrgunsigned		tmp;
582706f2543Smrgint			nRead=0;
583706f2543Smrg
584706f2543Smrg    if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) {
585706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"indicator rec",0);
586706f2543Smrg	return -1;
587706f2543Smrg    }
588706f2543Smrg    if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
589706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"indicator names",0);
590706f2543Smrg	return -1;
591706f2543Smrg    }
592706f2543Smrg    nLEDs= XkmGetCARD8(file,&nRead);
593706f2543Smrg    nRead+= XkmSkipPadding(file,3);
594706f2543Smrg    xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead);
595706f2543Smrg    while (nLEDs-->0) {
596706f2543Smrg	Atom 			name;
597706f2543Smrg	XkbIndicatorMapPtr	map;
598706f2543Smrg
599706f2543Smrg	if ((tmp=XkmGetCountedString(file,buf,100))<1) {
600706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
601706f2543Smrg	    return -1;
602706f2543Smrg	}
603706f2543Smrg	nRead+= tmp;
604706f2543Smrg	if (buf[0]!='\0')
605706f2543Smrg	     name= XkbInternAtom(buf,FALSE);
606706f2543Smrg	else name= None;
607706f2543Smrg	if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) {
608706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
609706f2543Smrg	    return -1;
610706f2543Smrg	}
611706f2543Smrg	nRead+= tmp*SIZEOF(xkmIndicatorMapDesc);
612706f2543Smrg	if (xkb->names) {
613706f2543Smrg	    xkb->names->indicators[wire.indicator-1]= name;
614706f2543Smrg	    if (changes)
615706f2543Smrg		changes->names.changed_indicators|= (1<<(wire.indicator-1));
616706f2543Smrg	}
617706f2543Smrg	map= &xkb->indicators->maps[wire.indicator-1];
618706f2543Smrg	map->flags= wire.flags;
619706f2543Smrg	map->which_groups= wire.which_groups;
620706f2543Smrg	map->groups= wire.groups;
621706f2543Smrg	map->which_mods= wire.which_mods;
622706f2543Smrg	map->mods.mask= wire.real_mods;
623706f2543Smrg	map->mods.real_mods= wire.real_mods;
624706f2543Smrg	map->mods.vmods= wire.vmods;
625706f2543Smrg	map->ctrls= wire.ctrls;
626706f2543Smrg    }
627706f2543Smrg    return nRead;
628706f2543Smrg}
629706f2543Smrg
630706f2543Smrgstatic XkbKeyTypePtr
631706f2543SmrgFindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms)
632706f2543Smrg{
633706f2543Smrg    if ((!xkb)||(!xkb->map))
634706f2543Smrg	return NULL;
635706f2543Smrg    if (name!=None) {
636706f2543Smrg	register unsigned i;
637706f2543Smrg	for (i=0;i<xkb->map->num_types;i++) {
638706f2543Smrg	    if (xkb->map->types[i].name==name) {
639706f2543Smrg		if (xkb->map->types[i].num_levels!=width)
640706f2543Smrg		    DebugF("Group width mismatch between key and type\n");
641706f2543Smrg		return &xkb->map->types[i];
642706f2543Smrg	    }
643706f2543Smrg	}
644706f2543Smrg    }
645706f2543Smrg    if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol)))
646706f2543Smrg	return &xkb->map->types[XkbOneLevelIndex];
647706f2543Smrg    if (syms!=NULL) {
648706f2543Smrg	if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1]))
649706f2543Smrg	    return &xkb->map->types[XkbAlphabeticIndex];
650706f2543Smrg	else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1]))
651706f2543Smrg	    return &xkb->map->types[XkbKeypadIndex];
652706f2543Smrg    }
653706f2543Smrg    return &xkb->map->types[XkbTwoLevelIndex];
654706f2543Smrg}
655706f2543Smrg
656706f2543Smrgstatic int
657706f2543SmrgReadXkmSymbols(FILE *file,XkbDescPtr xkb)
658706f2543Smrg{
659706f2543Smrgregister int		i,g,s,totalVModMaps;
660706f2543SmrgxkmKeySymMapDesc 	wireMap;
661706f2543Smrgchar 			buf[100];
662706f2543Smrgunsigned		minKC,maxKC,groupNames,tmp;
663706f2543Smrgint			nRead=0;
664706f2543Smrg
665706f2543Smrg    if ((tmp=XkmGetCountedString(file,buf,100))<1)
666706f2543Smrg	return -1;
667706f2543Smrg    nRead+= tmp;
668706f2543Smrg    minKC= XkmGetCARD8(file,&nRead);
669706f2543Smrg    maxKC= XkmGetCARD8(file,&nRead);
670706f2543Smrg    groupNames= XkmGetCARD8(file,&nRead);
671706f2543Smrg    totalVModMaps= XkmGetCARD8(file,&nRead);
672706f2543Smrg    if (XkbAllocNames(xkb,
673706f2543Smrg	      XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask,
674706f2543Smrg	      0,0)!=Success) {
675706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"physical names",0);
676706f2543Smrg	return -1;
677706f2543Smrg    }
678706f2543Smrg    if ((buf[0]!='\0')&&(xkb->names)) {
679706f2543Smrg	Atom name;
680706f2543Smrg	name= XkbInternAtom(buf,0);
681706f2543Smrg	xkb->names->symbols= name;
682706f2543Smrg	xkb->names->phys_symbols= name;
683706f2543Smrg    }
684706f2543Smrg    for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) {
685706f2543Smrg	if (groupNames&g) {
686706f2543Smrg	    if ((tmp=XkmGetCountedString(file,buf,100))<1)
687706f2543Smrg		return -1;
688706f2543Smrg	    nRead+= tmp;
689706f2543Smrg
690706f2543Smrg	    if (!xkb->names)
691706f2543Smrg		    continue;
692706f2543Smrg
693706f2543Smrg	    if (buf[0]!='\0') {
694706f2543Smrg		Atom name;
695706f2543Smrg		name= XkbInternAtom(buf,0);
696706f2543Smrg		xkb->names->groups[i]= name;
697706f2543Smrg	    }
698706f2543Smrg	    else xkb->names->groups[i]= None;
699706f2543Smrg	}
700706f2543Smrg    }
701706f2543Smrg    if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) {
702706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"server map",0);
703706f2543Smrg	return -1;
704706f2543Smrg    }
705706f2543Smrg    if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) {
706706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"client map",0);
707706f2543Smrg	return -1;
708706f2543Smrg    }
709706f2543Smrg    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) {
710706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"controls",0);
711706f2543Smrg	return -1;
712706f2543Smrg    }
713706f2543Smrg    if ((xkb->map==NULL)||(xkb->server==NULL))
714706f2543Smrg	return -1;
715706f2543Smrg    if (xkb->min_key_code<8)	xkb->min_key_code= minKC;
716706f2543Smrg    if (xkb->max_key_code<8)	xkb->max_key_code= maxKC;
717706f2543Smrg    if ((minKC>=8)&&(minKC<xkb->min_key_code))
718706f2543Smrg	xkb->min_key_code= minKC;
719706f2543Smrg    if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) {
720706f2543Smrg	_XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC);
721706f2543Smrg	return -1;
722706f2543Smrg    }
723706f2543Smrg    for (i=minKC;i<=(int)maxKC;i++)  {
724706f2543Smrg	Atom 		typeName[XkbNumKbdGroups];
725706f2543Smrg	XkbKeyTypePtr	type[XkbNumKbdGroups];
726706f2543Smrg	if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) {
727706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0);
728706f2543Smrg	    return -1;
729706f2543Smrg	}
730706f2543Smrg	nRead+= tmp*SIZEOF(xkmKeySymMapDesc);
731706f2543Smrg	memset((char *)typeName, 0, XkbNumKbdGroups*sizeof(Atom));
732706f2543Smrg	memset((char *)type, 0, XkbNumKbdGroups*sizeof(XkbKeyTypePtr));
733706f2543Smrg	if (wireMap.flags&XkmKeyHasTypes) {
734706f2543Smrg	    register int g;
735706f2543Smrg	    for (g=0;g<XkbNumKbdGroups;g++) {
736706f2543Smrg		if ((wireMap.flags&(1<<g))&&
737706f2543Smrg			((tmp=XkmGetCountedString(file,buf,100))>0)) {
738706f2543Smrg		    typeName[g]= XkbInternAtom(buf,1);
739706f2543Smrg		    nRead+= tmp;
740706f2543Smrg		}
741706f2543Smrg		type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL);
742706f2543Smrg		if (type[g]==NULL) {
743706f2543Smrg		    _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0);
744706f2543Smrg		    return -1;
745706f2543Smrg		}
746706f2543Smrg		if (typeName[g]==type[g]->name)
747706f2543Smrg		    xkb->server->explicit[i]|= (1<<g);
748706f2543Smrg	    }
749706f2543Smrg	}
750706f2543Smrg	if (wireMap.flags&XkmRepeatingKey) {
751706f2543Smrg	    xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8));
752706f2543Smrg	    xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
753706f2543Smrg	}
754706f2543Smrg	else if (wireMap.flags&XkmNonRepeatingKey) {
755706f2543Smrg	    xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8));
756706f2543Smrg	    xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
757706f2543Smrg	}
758706f2543Smrg	xkb->map->modmap[i]= wireMap.modifier_map;
759706f2543Smrg	if (XkbNumGroups(wireMap.num_groups)>0) {
760706f2543Smrg	    KeySym	*sym;
761706f2543Smrg	    int		 nSyms;
762706f2543Smrg
763706f2543Smrg	    if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups)
764706f2543Smrg		xkb->ctrls->num_groups= wireMap.num_groups;
765706f2543Smrg	    nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width;
766706f2543Smrg	    sym= XkbResizeKeySyms(xkb,i,nSyms);
767706f2543Smrg	    if (!sym)
768706f2543Smrg		return -1;
769706f2543Smrg	    for (s=0;s<nSyms;s++) {
770706f2543Smrg		*sym++= XkmGetCARD32(file,&nRead);
771706f2543Smrg	    }
772706f2543Smrg	    if (wireMap.flags&XkmKeyHasActions) {
773706f2543Smrg		XkbAction *	act;
774706f2543Smrg		act= XkbResizeKeyActions(xkb,i,nSyms);
775706f2543Smrg		for (s=0;s<nSyms;s++,act++) {
776706f2543Smrg		    tmp=fread(act,SIZEOF(xkmActionDesc),1,file);
777706f2543Smrg		    nRead+= tmp*SIZEOF(xkmActionDesc);
778706f2543Smrg		}
779706f2543Smrg		xkb->server->explicit[i]|= XkbExplicitInterpretMask;
780706f2543Smrg	    }
781706f2543Smrg	}
782706f2543Smrg	for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) {
783706f2543Smrg	    if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) {
784706f2543Smrg		KeySym *tmpSyms;
785706f2543Smrg		tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g);
786706f2543Smrg		type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms);
787706f2543Smrg	    }
788706f2543Smrg	    xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]);
789706f2543Smrg	}
790706f2543Smrg	xkb->map->key_sym_map[i].group_info= wireMap.num_groups;
791706f2543Smrg	xkb->map->key_sym_map[i].width= wireMap.width;
792706f2543Smrg	if (wireMap.flags&XkmKeyHasBehavior) {
793706f2543Smrg	    xkmBehaviorDesc	b;
794706f2543Smrg	    tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file);
795706f2543Smrg	    nRead+= tmp*SIZEOF(xkmBehaviorDesc);
796706f2543Smrg	    xkb->server->behaviors[i].type= b.type;
797706f2543Smrg	    xkb->server->behaviors[i].data= b.data;
798706f2543Smrg	    xkb->server->explicit[i]|= XkbExplicitBehaviorMask;
799706f2543Smrg	}
800706f2543Smrg    }
801706f2543Smrg    if (totalVModMaps>0) {
802706f2543Smrg	xkmVModMapDesc	v;
803706f2543Smrg	for (i=0;i<totalVModMaps;i++) {
804706f2543Smrg	    tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file);
805706f2543Smrg	    nRead+= tmp*SIZEOF(xkmVModMapDesc);
806706f2543Smrg	    if (tmp>0)
807706f2543Smrg		xkb->server->vmodmap[v.key]= v.vmods;
808706f2543Smrg	}
809706f2543Smrg    }
810706f2543Smrg    return nRead;
811706f2543Smrg}
812706f2543Smrg
813706f2543Smrgstatic int
814706f2543SmrgReadXkmGeomDoodad(
815706f2543Smrg    FILE *		file,
816706f2543Smrg    XkbGeometryPtr	geom,
817706f2543Smrg    XkbSectionPtr	section)
818706f2543Smrg{
819706f2543SmrgXkbDoodadPtr	doodad;
820706f2543SmrgxkmDoodadDesc	doodadWire;
821706f2543Smrgchar		buf[100];
822706f2543Smrgunsigned	tmp;
823706f2543Smrgint		nRead=0;
824706f2543Smrg
825706f2543Smrg    nRead+= XkmGetCountedString(file,buf,100);
826706f2543Smrg    tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file);
827706f2543Smrg    nRead+= SIZEOF(xkmDoodadDesc)*tmp;
828706f2543Smrg    doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(buf,FALSE));
829706f2543Smrg    if (!doodad)
830706f2543Smrg	return nRead;
831706f2543Smrg    doodad->any.type= doodadWire.any.type;
832706f2543Smrg    doodad->any.priority= doodadWire.any.priority;
833706f2543Smrg    doodad->any.top= doodadWire.any.top;
834706f2543Smrg    doodad->any.left= doodadWire.any.left;
835706f2543Smrg    switch (doodadWire.any.type) {
836706f2543Smrg	case XkbOutlineDoodad:
837706f2543Smrg	case XkbSolidDoodad:
838706f2543Smrg	    doodad->shape.angle= doodadWire.shape.angle;
839706f2543Smrg	    doodad->shape.color_ndx= doodadWire.shape.color_ndx;
840706f2543Smrg	    doodad->shape.shape_ndx= doodadWire.shape.shape_ndx;
841706f2543Smrg	    break;
842706f2543Smrg	case XkbTextDoodad:
843706f2543Smrg	    doodad->text.angle= doodadWire.text.angle;
844706f2543Smrg	    doodad->text.width= doodadWire.text.width;
845706f2543Smrg	    doodad->text.height= doodadWire.text.height;
846706f2543Smrg	    doodad->text.color_ndx= doodadWire.text.color_ndx;
847706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
848706f2543Smrg	    doodad->text.text= _XkbDupString(buf);
849706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
850706f2543Smrg	    doodad->text.font= _XkbDupString(buf);
851706f2543Smrg	    break;
852706f2543Smrg	case XkbIndicatorDoodad:
853706f2543Smrg	    doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx;
854706f2543Smrg	    doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx;
855706f2543Smrg	    doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx;
856706f2543Smrg	    break;
857706f2543Smrg	case XkbLogoDoodad:
858706f2543Smrg	    doodad->logo.angle= doodadWire.logo.angle;
859706f2543Smrg	    doodad->logo.color_ndx= doodadWire.logo.color_ndx;
860706f2543Smrg	    doodad->logo.shape_ndx= doodadWire.logo.shape_ndx;
861706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
862706f2543Smrg	    doodad->logo.logo_name= _XkbDupString(buf);
863706f2543Smrg	    break;
864706f2543Smrg	default:
865706f2543Smrg	    /* report error? */
866706f2543Smrg	    return nRead;
867706f2543Smrg    }
868706f2543Smrg    return nRead;
869706f2543Smrg}
870706f2543Smrg
871706f2543Smrgstatic int
872706f2543SmrgReadXkmGeomOverlay(	FILE *		file,
873706f2543Smrg			XkbGeometryPtr	geom,
874706f2543Smrg			XkbSectionPtr	section)
875706f2543Smrg{
876706f2543Smrgchar 			buf[100];
877706f2543Smrgunsigned		tmp;
878706f2543Smrgint			nRead=0;
879706f2543SmrgXkbOverlayPtr		ol;
880706f2543SmrgXkbOverlayRowPtr	row;
881706f2543SmrgxkmOverlayDesc 		olWire;
882706f2543SmrgxkmOverlayRowDesc	rowWire;
883706f2543Smrgregister int		r;
884706f2543Smrg
885706f2543Smrg    nRead+= XkmGetCountedString(file,buf,100);
886706f2543Smrg    tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file);
887706f2543Smrg    nRead+= tmp*SIZEOF(xkmOverlayDesc);
888706f2543Smrg    ol= XkbAddGeomOverlay(section,XkbInternAtom(buf,FALSE),
889706f2543Smrg    							olWire.num_rows);
890706f2543Smrg    if (!ol)
891706f2543Smrg	return nRead;
892706f2543Smrg    for (r=0;r<olWire.num_rows;r++)  {
893706f2543Smrg    	int			k;
894706f2543Smrg	xkmOverlayKeyDesc	keyWire;
895706f2543Smrg	tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file);
896706f2543Smrg	nRead+= tmp*SIZEOF(xkmOverlayRowDesc);
897706f2543Smrg	row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys);
898706f2543Smrg	if (!row) {
899706f2543Smrg	    _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0);
900706f2543Smrg	   return nRead;
901706f2543Smrg	}
902706f2543Smrg	for (k=0;k<rowWire.num_keys;k++) {
903706f2543Smrg	    tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file);
904706f2543Smrg	    nRead+= tmp*SIZEOF(xkmOverlayKeyDesc);
905706f2543Smrg	    memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength);
906706f2543Smrg	    memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength);
907706f2543Smrg	}
908706f2543Smrg	row->num_keys= rowWire.num_keys;
909706f2543Smrg    }
910706f2543Smrg    return nRead;
911706f2543Smrg}
912706f2543Smrg
913706f2543Smrgstatic int
914706f2543SmrgReadXkmGeomSection(	FILE *		file,
915706f2543Smrg			XkbGeometryPtr	geom)
916706f2543Smrg{
917706f2543Smrgregister int	i;
918706f2543SmrgXkbSectionPtr	section;
919706f2543SmrgxkmSectionDesc	sectionWire;
920706f2543Smrgunsigned	tmp;
921706f2543Smrgint		nRead= 0;
922706f2543Smrgchar		buf[100];
923706f2543SmrgAtom		nameAtom;
924706f2543Smrg
925706f2543Smrg    nRead+= XkmGetCountedString(file,buf,100);
926706f2543Smrg    nameAtom= XkbInternAtom(buf,FALSE);
927706f2543Smrg    tmp= fread(&sectionWire,SIZEOF(xkmSectionDesc),1,file);
928706f2543Smrg    nRead+= SIZEOF(xkmSectionDesc)*tmp;
929706f2543Smrg    section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows,
930706f2543Smrg			 			sectionWire.num_doodads,
931706f2543Smrg			 			sectionWire.num_overlays);
932706f2543Smrg    if (!section) {
933706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
934706f2543Smrg	return nRead;
935706f2543Smrg    }
936706f2543Smrg    section->top= sectionWire.top;
937706f2543Smrg    section->left= sectionWire.left;
938706f2543Smrg    section->width= sectionWire.width;
939706f2543Smrg    section->height= sectionWire.height;
940706f2543Smrg    section->angle= sectionWire.angle;
941706f2543Smrg    section->priority= sectionWire.priority;
942706f2543Smrg    if (sectionWire.num_rows>0) {
943706f2543Smrg	register int	k;
944706f2543Smrg	XkbRowPtr	row;
945706f2543Smrg	xkmRowDesc	rowWire;
946706f2543Smrg	XkbKeyPtr	key;
947706f2543Smrg	xkmKeyDesc	keyWire;
948706f2543Smrg
949706f2543Smrg	for (i=0;i<sectionWire.num_rows;i++) {
950706f2543Smrg	    tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file);
951706f2543Smrg	    nRead+= SIZEOF(xkmRowDesc)*tmp;
952706f2543Smrg	    row= XkbAddGeomRow(section,rowWire.num_keys);
953706f2543Smrg	    if (!row) {
954706f2543Smrg		_XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
955706f2543Smrg		return nRead;
956706f2543Smrg	    }
957706f2543Smrg	    row->top= rowWire.top;
958706f2543Smrg	    row->left= rowWire.left;
959706f2543Smrg	    row->vertical= rowWire.vertical;
960706f2543Smrg	    for (k=0;k<rowWire.num_keys;k++) {
961706f2543Smrg		tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file);
962706f2543Smrg		nRead+= SIZEOF(xkmKeyDesc)*tmp;
963706f2543Smrg		key= XkbAddGeomKey(row);
964706f2543Smrg		if (!key) {
965706f2543Smrg		    _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
966706f2543Smrg		    return nRead;
967706f2543Smrg		}
968706f2543Smrg		memcpy(key->name.name,keyWire.name,XkbKeyNameLength);
969706f2543Smrg		key->gap= keyWire.gap;
970706f2543Smrg		key->shape_ndx= keyWire.shape_ndx;
971706f2543Smrg		key->color_ndx= keyWire.color_ndx;
972706f2543Smrg	    }
973706f2543Smrg	}
974706f2543Smrg    }
975706f2543Smrg    if (sectionWire.num_doodads>0) {
976706f2543Smrg	for (i=0;i<sectionWire.num_doodads;i++) {
977706f2543Smrg	    tmp= ReadXkmGeomDoodad(file,geom,section);
978706f2543Smrg	    nRead+= tmp;
979706f2543Smrg	    if (tmp<1)
980706f2543Smrg		return nRead;
981706f2543Smrg	}
982706f2543Smrg    }
983706f2543Smrg    if (sectionWire.num_overlays>0) {
984706f2543Smrg	for (i=0;i<sectionWire.num_overlays;i++) {
985706f2543Smrg	    tmp= ReadXkmGeomOverlay(file,geom,section);
986706f2543Smrg	    nRead+= tmp;
987706f2543Smrg	    if (tmp<1)
988706f2543Smrg		return nRead;
989706f2543Smrg	}
990706f2543Smrg    }
991706f2543Smrg    return nRead;
992706f2543Smrg}
993706f2543Smrg
994706f2543Smrgstatic int
995706f2543SmrgReadXkmGeometry(FILE *file,XkbDescPtr xkb)
996706f2543Smrg{
997706f2543Smrgregister int		i;
998706f2543Smrgchar 			buf[100];
999706f2543Smrgunsigned		tmp;
1000706f2543Smrgint			nRead= 0;
1001706f2543SmrgxkmGeometryDesc		wireGeom;
1002706f2543SmrgXkbGeometryPtr		geom;
1003706f2543SmrgXkbGeometrySizesRec	sizes;
1004706f2543Smrg
1005706f2543Smrg    nRead+= XkmGetCountedString(file,buf,100);
1006706f2543Smrg    tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file);
1007706f2543Smrg    nRead+= tmp*SIZEOF(xkmGeometryDesc);
1008706f2543Smrg    sizes.which= XkbGeomAllMask;
1009706f2543Smrg    sizes.num_properties= wireGeom.num_properties;
1010706f2543Smrg    sizes.num_colors= wireGeom.num_colors;
1011706f2543Smrg    sizes.num_shapes= wireGeom.num_shapes;
1012706f2543Smrg    sizes.num_sections= wireGeom.num_sections;
1013706f2543Smrg    sizes.num_doodads= wireGeom.num_doodads;
1014706f2543Smrg    sizes.num_key_aliases= wireGeom.num_key_aliases;
1015706f2543Smrg    if (XkbAllocGeometry(xkb,&sizes)!=Success) {
1016706f2543Smrg	_XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
1017706f2543Smrg	return nRead;
1018706f2543Smrg    }
1019706f2543Smrg    geom= xkb->geom;
1020706f2543Smrg    geom->name= XkbInternAtom(buf,FALSE);
1021706f2543Smrg    geom->width_mm= wireGeom.width_mm;
1022706f2543Smrg    geom->height_mm= wireGeom.height_mm;
1023706f2543Smrg    nRead+= XkmGetCountedString(file,buf,100);
1024706f2543Smrg    geom->label_font= _XkbDupString(buf);
1025706f2543Smrg    if (wireGeom.num_properties>0) {
1026706f2543Smrg	char val[1024];
1027706f2543Smrg	for (i=0;i<wireGeom.num_properties;i++) {
1028706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
1029706f2543Smrg	    nRead+= XkmGetCountedString(file,val,1024);
1030706f2543Smrg	    if (XkbAddGeomProperty(geom,buf,val)==NULL) {
1031706f2543Smrg		_XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
1032706f2543Smrg		return nRead;
1033706f2543Smrg	    }
1034706f2543Smrg	}
1035706f2543Smrg    }
1036706f2543Smrg    if (wireGeom.num_colors>0) {
1037706f2543Smrg	for (i=0;i<wireGeom.num_colors;i++) {
1038706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
1039706f2543Smrg	    if (XkbAddGeomColor(geom,buf,i)==NULL) {
1040706f2543Smrg		_XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
1041706f2543Smrg		return nRead;
1042706f2543Smrg	    }
1043706f2543Smrg	}
1044706f2543Smrg    }
1045706f2543Smrg    geom->base_color= &geom->colors[wireGeom.base_color_ndx];
1046706f2543Smrg    geom->label_color= &geom->colors[wireGeom.label_color_ndx];
1047706f2543Smrg    if (wireGeom.num_shapes>0) {
1048706f2543Smrg	XkbShapePtr	shape;
1049706f2543Smrg	xkmShapeDesc	shapeWire;
1050706f2543Smrg	Atom		nameAtom;
1051706f2543Smrg	for (i=0;i<wireGeom.num_shapes;i++) {
1052706f2543Smrg	    register int 	n;
1053706f2543Smrg	    XkbOutlinePtr	ol;
1054706f2543Smrg	    xkmOutlineDesc	olWire;
1055706f2543Smrg	    nRead+= XkmGetCountedString(file,buf,100);
1056706f2543Smrg	    nameAtom= XkbInternAtom(buf,FALSE);
1057706f2543Smrg	    tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file);
1058706f2543Smrg	    nRead+= tmp*SIZEOF(xkmShapeDesc);
1059706f2543Smrg	    shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines);
1060706f2543Smrg	    if (!shape) {
1061706f2543Smrg		_XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
1062706f2543Smrg		return nRead;
1063706f2543Smrg	    }
1064706f2543Smrg	    for (n=0;n<shapeWire.num_outlines;n++) {
1065706f2543Smrg		register int	p;
1066706f2543Smrg		xkmPointDesc	ptWire;
1067706f2543Smrg		tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file);
1068706f2543Smrg		nRead+= tmp*SIZEOF(xkmOutlineDesc);
1069706f2543Smrg		ol= XkbAddGeomOutline(shape,olWire.num_points);
1070706f2543Smrg		if (!ol) {
1071706f2543Smrg		    _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
1072706f2543Smrg		    return nRead;
1073706f2543Smrg		}
1074706f2543Smrg		ol->num_points= olWire.num_points;
1075706f2543Smrg		ol->corner_radius= olWire.corner_radius;
1076706f2543Smrg		for (p=0;p<olWire.num_points;p++) {
1077706f2543Smrg		    tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file);
1078706f2543Smrg		    nRead+= tmp*SIZEOF(xkmPointDesc);
1079706f2543Smrg		    ol->points[p].x= ptWire.x;
1080706f2543Smrg		    ol->points[p].y= ptWire.y;
1081706f2543Smrg		    if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x;
1082706f2543Smrg		    if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x;
1083706f2543Smrg		    if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y;
1084706f2543Smrg		    if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y;
1085706f2543Smrg		}
1086706f2543Smrg	    }
1087706f2543Smrg	    if (shapeWire.primary_ndx!=XkbNoShape)
1088706f2543Smrg		shape->primary= &shape->outlines[shapeWire.primary_ndx];
1089706f2543Smrg	    if (shapeWire.approx_ndx!=XkbNoShape)
1090706f2543Smrg		shape->approx= &shape->outlines[shapeWire.approx_ndx];
1091706f2543Smrg	}
1092706f2543Smrg    }
1093706f2543Smrg    if (wireGeom.num_sections>0) {
1094706f2543Smrg	for (i=0;i<wireGeom.num_sections;i++) {
1095706f2543Smrg	    tmp= ReadXkmGeomSection(file,geom);
1096706f2543Smrg	    nRead+= tmp;
1097706f2543Smrg	    if (tmp==0)
1098706f2543Smrg		return nRead;
1099706f2543Smrg	}
1100706f2543Smrg    }
1101706f2543Smrg    if (wireGeom.num_doodads>0) {
1102706f2543Smrg	for (i=0;i<wireGeom.num_doodads;i++) {
1103706f2543Smrg	    tmp= ReadXkmGeomDoodad(file,geom,NULL);
1104706f2543Smrg	    nRead+= tmp;
1105706f2543Smrg	    if (tmp==0)
1106706f2543Smrg		return nRead;
1107706f2543Smrg	}
1108706f2543Smrg    }
1109706f2543Smrg    if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) {
1110706f2543Smrg	int sz= XkbKeyNameLength*2;
1111706f2543Smrg	int num= wireGeom.num_key_aliases;
1112706f2543Smrg	if (fread(geom->key_aliases,sz,num,file)!=num) {
1113706f2543Smrg	    _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0);
1114706f2543Smrg	    return -1;
1115706f2543Smrg	}
1116706f2543Smrg	nRead+= (num*sz);
1117706f2543Smrg	geom->num_key_aliases= num;
1118706f2543Smrg    }
1119706f2543Smrg    return nRead;
1120706f2543Smrg}
1121706f2543Smrg
1122706f2543SmrgBool
1123706f2543SmrgXkmProbe(FILE *file)
1124706f2543Smrg{
1125706f2543Smrgunsigned hdr,tmp;
1126706f2543Smrgint	 nRead=0;
1127706f2543Smrg
1128706f2543Smrg    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
1129706f2543Smrg    tmp= XkmGetCARD32(file,&nRead);
1130706f2543Smrg    if (tmp!=hdr) {
1131706f2543Smrg	if ((tmp&(~0xff))==(hdr&(~0xff))) {
1132706f2543Smrg	    _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff);
1133706f2543Smrg	}
1134706f2543Smrg	return 0;
1135706f2543Smrg    }
1136706f2543Smrg    return 1;
1137706f2543Smrg}
1138706f2543Smrg
1139706f2543Smrgstatic Bool
1140706f2543SmrgXkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc)
1141706f2543Smrg{
1142706f2543Smrgunsigned hdr,tmp;
1143706f2543Smrgint	nRead=0;
1144706f2543Smrgunsigned i,size_toc;
1145706f2543Smrg
1146706f2543Smrg    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
1147706f2543Smrg    tmp= XkmGetCARD32(file,&nRead);
1148706f2543Smrg    if (tmp!=hdr) {
1149706f2543Smrg	if ((tmp&(~0xff))==(hdr&(~0xff))) {
1150706f2543Smrg	    _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff);
1151706f2543Smrg	}
1152706f2543Smrg	else {
1153706f2543Smrg	    _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp);
1154706f2543Smrg	}
1155706f2543Smrg	return 0;
1156706f2543Smrg    }
1157706f2543Smrg    fread(file_info,SIZEOF(xkmFileInfo),1,file);
1158706f2543Smrg    size_toc= file_info->num_toc;
1159706f2543Smrg    if (size_toc>max_toc) {
1160706f2543Smrg	DebugF("Warning! Too many TOC entries; last %d ignored\n",
1161706f2543Smrg							size_toc-max_toc);
1162706f2543Smrg	size_toc= max_toc;
1163706f2543Smrg    }
1164706f2543Smrg    for (i=0;i<size_toc;i++) {
1165706f2543Smrg	fread(&toc[i],SIZEOF(xkmSectionInfo),1,file);
1166706f2543Smrg    }
1167706f2543Smrg    return 1;
1168706f2543Smrg}
1169706f2543Smrg
1170706f2543Smrg/***====================================================================***/
1171706f2543Smrg
1172706f2543Smrg#define	MAX_TOC	16
1173706f2543Smrgunsigned
1174706f2543SmrgXkmReadFile(FILE *file,unsigned need,unsigned want,XkbDescPtr *xkb)
1175706f2543Smrg{
1176706f2543Smrgregister unsigned	i;
1177706f2543SmrgxkmSectionInfo		toc[MAX_TOC],tmpTOC;
1178706f2543SmrgxkmFileInfo		fileInfo;
1179706f2543Smrgunsigned		tmp,nRead=0;
1180706f2543Smrgunsigned		which= need|want;
1181706f2543Smrg
1182706f2543Smrg    if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc))
1183706f2543Smrg	return which;
1184706f2543Smrg    if ((fileInfo.present&need)!=need) {
1185706f2543Smrg       _XkbLibError(_XkbErrIllegalContents,"XkmReadFile",
1186706f2543Smrg       						need&(~fileInfo.present));
1187706f2543Smrg       return which;
1188706f2543Smrg    }
1189706f2543Smrg    if (*xkb==NULL)
1190706f2543Smrg	*xkb= XkbAllocKeyboard();
1191706f2543Smrg    for (i=0;i<fileInfo.num_toc;i++) {
1192706f2543Smrg	fseek(file,toc[i].offset,SEEK_SET);
1193706f2543Smrg	tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file);
1194706f2543Smrg	nRead= tmp*SIZEOF(xkmSectionInfo);
1195706f2543Smrg	if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)||
1196706f2543Smrg	    (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) {
1197706f2543Smrg	    return which;
1198706f2543Smrg	}
1199706f2543Smrg	if ((which&(1<<tmpTOC.type))==0) {
1200706f2543Smrg	    continue;
1201706f2543Smrg	}
1202706f2543Smrg	switch (tmpTOC.type) {
1203706f2543Smrg	    case XkmVirtualModsIndex:
1204706f2543Smrg		tmp= ReadXkmVirtualMods(file,*xkb,NULL);
1205706f2543Smrg		break;
1206706f2543Smrg	    case XkmTypesIndex:
1207706f2543Smrg		tmp= ReadXkmKeyTypes(file,*xkb,NULL);
1208706f2543Smrg		break;
1209706f2543Smrg	    case XkmCompatMapIndex:
1210706f2543Smrg		tmp= ReadXkmCompatMap(file,*xkb,NULL);
1211706f2543Smrg		break;
1212706f2543Smrg	    case XkmKeyNamesIndex:
1213706f2543Smrg		tmp= ReadXkmKeycodes(file,*xkb,NULL);
1214706f2543Smrg		break;
1215706f2543Smrg	    case XkmIndicatorsIndex:
1216706f2543Smrg		tmp= ReadXkmIndicators(file,*xkb,NULL);
1217706f2543Smrg		break;
1218706f2543Smrg	    case XkmSymbolsIndex:
1219706f2543Smrg		tmp= ReadXkmSymbols(file,*xkb);
1220706f2543Smrg		break;
1221706f2543Smrg	    case XkmGeometryIndex:
1222706f2543Smrg		tmp= ReadXkmGeometry(file,*xkb);
1223706f2543Smrg		break;
1224706f2543Smrg	    default:
1225706f2543Smrg		_XkbLibError(_XkbErrBadImplementation,
1226706f2543Smrg				XkbConfigText(tmpTOC.type,XkbMessage),0);
1227706f2543Smrg		tmp= 0;
1228706f2543Smrg		break;
1229706f2543Smrg	}
1230706f2543Smrg	if (tmp>0) {
1231706f2543Smrg	    nRead+= tmp;
1232706f2543Smrg	    which&= ~(1<<toc[i].type);
1233706f2543Smrg	    (*xkb)->defined|= (1<<toc[i].type);
1234706f2543Smrg	}
1235706f2543Smrg	if (nRead!=tmpTOC.size) {
1236706f2543Smrg	    _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
1237706f2543Smrg	    						nRead-tmpTOC.size);
1238706f2543Smrg	}
1239706f2543Smrg    }
1240706f2543Smrg    return which;
1241706f2543Smrg}
1242