xref: /OK3568_Linux_fs/external/xserver/xkb/xkmread.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun  Permission to use, copy, modify, and distribute this
5*4882a593Smuzhiyun  software and its documentation for any purpose and without
6*4882a593Smuzhiyun  fee is hereby granted, provided that the above copyright
7*4882a593Smuzhiyun  notice appear in all copies and that both that copyright
8*4882a593Smuzhiyun  notice and this permission notice appear in supporting
9*4882a593Smuzhiyun  documentation, and that the name of Silicon Graphics not be
10*4882a593Smuzhiyun  used in advertising or publicity pertaining to distribution
11*4882a593Smuzhiyun  of the software without specific prior written permission.
12*4882a593Smuzhiyun  Silicon Graphics makes no representation about the suitability
13*4882a593Smuzhiyun  of this software for any purpose. It is provided "as is"
14*4882a593Smuzhiyun  without any express or implied warranty.
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*4882a593Smuzhiyun  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*4882a593Smuzhiyun  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*4882a593Smuzhiyun  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*4882a593Smuzhiyun  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*4882a593Smuzhiyun  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*4882a593Smuzhiyun  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23*4882a593Smuzhiyun  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun  ********************************************************/
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
28*4882a593Smuzhiyun #include <dix-config.h>
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <stdio.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include <X11/Xos.h>
34*4882a593Smuzhiyun #include <X11/Xfuncs.h>
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include <X11/X.h>
37*4882a593Smuzhiyun #include <X11/Xproto.h>
38*4882a593Smuzhiyun #include <X11/keysym.h>
39*4882a593Smuzhiyun #include <X11/extensions/XKMformat.h>
40*4882a593Smuzhiyun #include "misc.h"
41*4882a593Smuzhiyun #include "inputstr.h"
42*4882a593Smuzhiyun #include "xkbstr.h"
43*4882a593Smuzhiyun #include "xkbsrv.h"
44*4882a593Smuzhiyun #include "xkbgeom.h"
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun Atom
XkbInternAtom(char * str,Bool only_if_exists)47*4882a593Smuzhiyun XkbInternAtom(char *str, Bool only_if_exists)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun     if (str == NULL)
50*4882a593Smuzhiyun         return None;
51*4882a593Smuzhiyun     return MakeAtom(str, strlen(str), !only_if_exists);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /***====================================================================***/
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static void *
XkmInsureSize(void * oldPtr,int oldCount,int * newCountRtrn,int elemSize)57*4882a593Smuzhiyun XkmInsureSize(void *oldPtr, int oldCount, int *newCountRtrn, int elemSize)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun     int newCount = *newCountRtrn;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun     if (oldPtr == NULL) {
62*4882a593Smuzhiyun         if (newCount == 0)
63*4882a593Smuzhiyun             return NULL;
64*4882a593Smuzhiyun         oldPtr = calloc(newCount, elemSize);
65*4882a593Smuzhiyun     }
66*4882a593Smuzhiyun     else if (oldCount < newCount) {
67*4882a593Smuzhiyun         oldPtr = reallocarray(oldPtr, newCount, elemSize);
68*4882a593Smuzhiyun         if (oldPtr != NULL) {
69*4882a593Smuzhiyun             char *tmp = (char *) oldPtr;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun             memset(&tmp[oldCount * elemSize], 0,
72*4882a593Smuzhiyun                    (newCount - oldCount) * elemSize);
73*4882a593Smuzhiyun         }
74*4882a593Smuzhiyun     }
75*4882a593Smuzhiyun     else if (newCount < oldCount) {
76*4882a593Smuzhiyun         *newCountRtrn = oldCount;
77*4882a593Smuzhiyun     }
78*4882a593Smuzhiyun     return oldPtr;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #define	XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t))))
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun static CARD8
XkmGetCARD8(FILE * file,int * pNRead)84*4882a593Smuzhiyun XkmGetCARD8(FILE * file, int *pNRead)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun     int tmp;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun     tmp = getc(file);
89*4882a593Smuzhiyun     if (pNRead && (tmp != EOF))
90*4882a593Smuzhiyun         (*pNRead) += 1;
91*4882a593Smuzhiyun     return tmp;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static CARD16
XkmGetCARD16(FILE * file,int * pNRead)95*4882a593Smuzhiyun XkmGetCARD16(FILE * file, int *pNRead)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun     CARD16 val;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     if ((fread(&val, 2, 1, file) == 1) && (pNRead))
100*4882a593Smuzhiyun         (*pNRead) += 2;
101*4882a593Smuzhiyun     return val;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static CARD32
XkmGetCARD32(FILE * file,int * pNRead)105*4882a593Smuzhiyun XkmGetCARD32(FILE * file, int *pNRead)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun     CARD32 val;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun     if ((fread(&val, 4, 1, file) == 1) && (pNRead))
110*4882a593Smuzhiyun         (*pNRead) += 4;
111*4882a593Smuzhiyun     return val;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun static int
XkmSkipPadding(FILE * file,unsigned pad)115*4882a593Smuzhiyun XkmSkipPadding(FILE * file, unsigned pad)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun     register int i, nRead = 0;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun     for (i = 0; i < pad; i++) {
120*4882a593Smuzhiyun         if (getc(file) != EOF)
121*4882a593Smuzhiyun             nRead++;
122*4882a593Smuzhiyun     }
123*4882a593Smuzhiyun     return nRead;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun static int
XkmGetCountedString(FILE * file,char * str,int max_len)127*4882a593Smuzhiyun XkmGetCountedString(FILE * file, char *str, int max_len)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun     int count, nRead = 0;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     count = XkmGetCARD16(file, &nRead);
132*4882a593Smuzhiyun     if (count > 0) {
133*4882a593Smuzhiyun         int tmp;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun         if (count > max_len) {
136*4882a593Smuzhiyun             tmp = fread(str, 1, max_len, file);
137*4882a593Smuzhiyun             while (tmp < count) {
138*4882a593Smuzhiyun                 if ((getc(file)) != EOF)
139*4882a593Smuzhiyun                     tmp++;
140*4882a593Smuzhiyun                 else
141*4882a593Smuzhiyun                     break;
142*4882a593Smuzhiyun             }
143*4882a593Smuzhiyun         }
144*4882a593Smuzhiyun         else {
145*4882a593Smuzhiyun             tmp = fread(str, 1, count, file);
146*4882a593Smuzhiyun         }
147*4882a593Smuzhiyun         nRead += tmp;
148*4882a593Smuzhiyun     }
149*4882a593Smuzhiyun     if (count >= max_len)
150*4882a593Smuzhiyun         str[max_len - 1] = '\0';
151*4882a593Smuzhiyun     else
152*4882a593Smuzhiyun         str[count] = '\0';
153*4882a593Smuzhiyun     count = XkbPaddedSize(nRead) - nRead;
154*4882a593Smuzhiyun     if (count > 0)
155*4882a593Smuzhiyun         nRead += XkmSkipPadding(file, count);
156*4882a593Smuzhiyun     return nRead;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /***====================================================================***/
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun static int
ReadXkmVirtualMods(FILE * file,XkbDescPtr xkb,XkbChangesPtr changes)162*4882a593Smuzhiyun ReadXkmVirtualMods(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     register unsigned int i, bit;
165*4882a593Smuzhiyun     unsigned int bound, named, tmp;
166*4882a593Smuzhiyun     int nRead = 0;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     if (XkbAllocServerMap(xkb, XkbVirtualModsMask, 0) != Success) {
169*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmVirtualMods", 0);
170*4882a593Smuzhiyun         return -1;
171*4882a593Smuzhiyun     }
172*4882a593Smuzhiyun     bound = XkmGetCARD16(file, &nRead);
173*4882a593Smuzhiyun     named = XkmGetCARD16(file, &nRead);
174*4882a593Smuzhiyun     for (i = tmp = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
175*4882a593Smuzhiyun         if (bound & bit) {
176*4882a593Smuzhiyun             xkb->server->vmods[i] = XkmGetCARD8(file, &nRead);
177*4882a593Smuzhiyun             if (changes)
178*4882a593Smuzhiyun                 changes->map.vmods |= bit;
179*4882a593Smuzhiyun             tmp++;
180*4882a593Smuzhiyun         }
181*4882a593Smuzhiyun     }
182*4882a593Smuzhiyun     if ((i = XkbPaddedSize(tmp) - tmp) > 0)
183*4882a593Smuzhiyun         nRead += XkmSkipPadding(file, i);
184*4882a593Smuzhiyun     if (XkbAllocNames(xkb, XkbVirtualModNamesMask, 0, 0) != Success) {
185*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmVirtualMods", 0);
186*4882a593Smuzhiyun         return -1;
187*4882a593Smuzhiyun     }
188*4882a593Smuzhiyun     for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
189*4882a593Smuzhiyun         char name[100];
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun         if (named & bit) {
192*4882a593Smuzhiyun             if (nRead += XkmGetCountedString(file, name, 100)) {
193*4882a593Smuzhiyun                 xkb->names->vmods[i] = XkbInternAtom(name, FALSE);
194*4882a593Smuzhiyun                 if (changes)
195*4882a593Smuzhiyun                     changes->names.changed_vmods |= bit;
196*4882a593Smuzhiyun             }
197*4882a593Smuzhiyun         }
198*4882a593Smuzhiyun     }
199*4882a593Smuzhiyun     return nRead;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun /***====================================================================***/
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static int
ReadXkmKeycodes(FILE * file,XkbDescPtr xkb,XkbChangesPtr changes)205*4882a593Smuzhiyun ReadXkmKeycodes(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun     register int i;
208*4882a593Smuzhiyun     unsigned minKC, maxKC, nAl;
209*4882a593Smuzhiyun     int nRead = 0;
210*4882a593Smuzhiyun     char name[100];
211*4882a593Smuzhiyun     XkbKeyNamePtr pN;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun     name[0] = '\0';
214*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, name, 100);
215*4882a593Smuzhiyun     minKC = XkmGetCARD8(file, &nRead);
216*4882a593Smuzhiyun     maxKC = XkmGetCARD8(file, &nRead);
217*4882a593Smuzhiyun     if (xkb->min_key_code == 0) {
218*4882a593Smuzhiyun         xkb->min_key_code = minKC;
219*4882a593Smuzhiyun         xkb->max_key_code = maxKC;
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun     else {
222*4882a593Smuzhiyun         if (minKC < xkb->min_key_code)
223*4882a593Smuzhiyun             xkb->min_key_code = minKC;
224*4882a593Smuzhiyun         if (maxKC > xkb->max_key_code) {
225*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadValue, "ReadXkmKeycodes", maxKC);
226*4882a593Smuzhiyun             return -1;
227*4882a593Smuzhiyun         }
228*4882a593Smuzhiyun     }
229*4882a593Smuzhiyun     nAl = XkmGetCARD8(file, &nRead);
230*4882a593Smuzhiyun     nRead += XkmSkipPadding(file, 1);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask)
233*4882a593Smuzhiyun     if (XkbAllocNames(xkb, WANTED, 0, nAl) != Success) {
234*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeycodes", 0);
235*4882a593Smuzhiyun         return -1;
236*4882a593Smuzhiyun     }
237*4882a593Smuzhiyun     if (name[0] != '\0') {
238*4882a593Smuzhiyun         xkb->names->keycodes = XkbInternAtom(name, FALSE);
239*4882a593Smuzhiyun     }
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun     for (pN = &xkb->names->keys[minKC], i = minKC; i <= (int) maxKC; i++, pN++) {
242*4882a593Smuzhiyun         if (fread(pN, 1, XkbKeyNameLength, file) != XkbKeyNameLength) {
243*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
244*4882a593Smuzhiyun             return -1;
245*4882a593Smuzhiyun         }
246*4882a593Smuzhiyun         nRead += XkbKeyNameLength;
247*4882a593Smuzhiyun     }
248*4882a593Smuzhiyun     if (nAl > 0) {
249*4882a593Smuzhiyun         XkbKeyAliasPtr pAl;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun         for (pAl = xkb->names->key_aliases, i = 0; i < nAl; i++, pAl++) {
252*4882a593Smuzhiyun             int tmp;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun             tmp = fread(pAl, 1, 2 * XkbKeyNameLength, file);
255*4882a593Smuzhiyun             if (tmp != 2 * XkbKeyNameLength) {
256*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
257*4882a593Smuzhiyun                 return -1;
258*4882a593Smuzhiyun             }
259*4882a593Smuzhiyun             nRead += 2 * XkbKeyNameLength;
260*4882a593Smuzhiyun         }
261*4882a593Smuzhiyun         if (changes)
262*4882a593Smuzhiyun             changes->names.changed |= XkbKeyAliasesMask;
263*4882a593Smuzhiyun     }
264*4882a593Smuzhiyun     if (changes)
265*4882a593Smuzhiyun         changes->names.changed |= XkbKeyNamesMask;
266*4882a593Smuzhiyun     return nRead;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun /***====================================================================***/
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun static int
ReadXkmKeyTypes(FILE * file,XkbDescPtr xkb,XkbChangesPtr changes)272*4882a593Smuzhiyun ReadXkmKeyTypes(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun     register unsigned i, n;
275*4882a593Smuzhiyun     unsigned num_types;
276*4882a593Smuzhiyun     int nRead = 0;
277*4882a593Smuzhiyun     int tmp;
278*4882a593Smuzhiyun     XkbKeyTypePtr type;
279*4882a593Smuzhiyun     xkmKeyTypeDesc wire;
280*4882a593Smuzhiyun     XkbKTMapEntryPtr entry;
281*4882a593Smuzhiyun     xkmKTMapEntryDesc wire_entry;
282*4882a593Smuzhiyun     char buf[100];
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     if ((tmp = XkmGetCountedString(file, buf, 100)) < 1) {
285*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
286*4882a593Smuzhiyun         return -1;
287*4882a593Smuzhiyun     }
288*4882a593Smuzhiyun     nRead += tmp;
289*4882a593Smuzhiyun     if (buf[0] != '\0') {
290*4882a593Smuzhiyun         if (XkbAllocNames(xkb, XkbTypesNameMask, 0, 0) != Success) {
291*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeyTypes", 0);
292*4882a593Smuzhiyun             return -1;
293*4882a593Smuzhiyun         }
294*4882a593Smuzhiyun         xkb->names->types = XkbInternAtom(buf, FALSE);
295*4882a593Smuzhiyun     }
296*4882a593Smuzhiyun     num_types = XkmGetCARD16(file, &nRead);
297*4882a593Smuzhiyun     nRead += XkmSkipPadding(file, 2);
298*4882a593Smuzhiyun     if (num_types < 1)
299*4882a593Smuzhiyun         return nRead;
300*4882a593Smuzhiyun     if (XkbAllocClientMap(xkb, XkbKeyTypesMask, num_types) != Success) {
301*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeyTypes", 0);
302*4882a593Smuzhiyun         return nRead;
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun     xkb->map->num_types = num_types;
305*4882a593Smuzhiyun     if (num_types < XkbNumRequiredTypes) {
306*4882a593Smuzhiyun         _XkbLibError(_XkbErrMissingReqTypes, "ReadXkmKeyTypes", 0);
307*4882a593Smuzhiyun         return -1;
308*4882a593Smuzhiyun     }
309*4882a593Smuzhiyun     type = xkb->map->types;
310*4882a593Smuzhiyun     for (i = 0; i < num_types; i++, type++) {
311*4882a593Smuzhiyun         if ((int) fread(&wire, SIZEOF(xkmKeyTypeDesc), 1, file) < 1) {
312*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
313*4882a593Smuzhiyun             return -1;
314*4882a593Smuzhiyun         }
315*4882a593Smuzhiyun         nRead += SIZEOF(xkmKeyTypeDesc);
316*4882a593Smuzhiyun         if (((i == XkbOneLevelIndex) && (wire.numLevels != 1)) ||
317*4882a593Smuzhiyun             (((i == XkbTwoLevelIndex) || (i == XkbAlphabeticIndex) ||
318*4882a593Smuzhiyun               ((i) == XkbKeypadIndex)) && (wire.numLevels != 2))) {
319*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadTypeWidth, "ReadXkmKeyTypes", i);
320*4882a593Smuzhiyun             return -1;
321*4882a593Smuzhiyun         }
322*4882a593Smuzhiyun         tmp = wire.nMapEntries;
323*4882a593Smuzhiyun         XkmInsureTypedSize(type->map, type->map_count, &tmp, XkbKTMapEntryRec);
324*4882a593Smuzhiyun         if ((wire.nMapEntries > 0) && (type->map == NULL)) {
325*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadValue, "ReadXkmKeyTypes", wire.nMapEntries);
326*4882a593Smuzhiyun             return -1;
327*4882a593Smuzhiyun         }
328*4882a593Smuzhiyun         for (n = 0, entry = type->map; n < wire.nMapEntries; n++, entry++) {
329*4882a593Smuzhiyun             if (fread(&wire_entry, SIZEOF(xkmKTMapEntryDesc), 1, file) <
330*4882a593Smuzhiyun                 (int) 1) {
331*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadLength, "ReadXkmKeyTypes", 0);
332*4882a593Smuzhiyun                 return -1;
333*4882a593Smuzhiyun             }
334*4882a593Smuzhiyun             nRead += SIZEOF(xkmKTMapEntryDesc);
335*4882a593Smuzhiyun             entry->active = (wire_entry.virtualMods == 0);
336*4882a593Smuzhiyun             entry->level = wire_entry.level;
337*4882a593Smuzhiyun             entry->mods.mask = wire_entry.realMods;
338*4882a593Smuzhiyun             entry->mods.real_mods = wire_entry.realMods;
339*4882a593Smuzhiyun             entry->mods.vmods = wire_entry.virtualMods;
340*4882a593Smuzhiyun         }
341*4882a593Smuzhiyun         nRead += XkmGetCountedString(file, buf, 100);
342*4882a593Smuzhiyun         if (((i == XkbOneLevelIndex) && (strcmp(buf, "ONE_LEVEL") != 0)) ||
343*4882a593Smuzhiyun             ((i == XkbTwoLevelIndex) && (strcmp(buf, "TWO_LEVEL") != 0)) ||
344*4882a593Smuzhiyun             ((i == XkbAlphabeticIndex) && (strcmp(buf, "ALPHABETIC") != 0)) ||
345*4882a593Smuzhiyun             ((i == XkbKeypadIndex) && (strcmp(buf, "KEYPAD") != 0))) {
346*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadTypeName, "ReadXkmKeyTypes", 0);
347*4882a593Smuzhiyun             return -1;
348*4882a593Smuzhiyun         }
349*4882a593Smuzhiyun         if (buf[0] != '\0') {
350*4882a593Smuzhiyun             type->name = XkbInternAtom(buf, FALSE);
351*4882a593Smuzhiyun         }
352*4882a593Smuzhiyun         else
353*4882a593Smuzhiyun             type->name = None;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun         if (wire.preserve) {
356*4882a593Smuzhiyun             xkmModsDesc p_entry;
357*4882a593Smuzhiyun             XkbModsPtr pre;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun             XkmInsureTypedSize(type->preserve, type->map_count, &tmp,
360*4882a593Smuzhiyun                                XkbModsRec);
361*4882a593Smuzhiyun             if (type->preserve == NULL) {
362*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadMatch, "ReadXkmKeycodes", 0);
363*4882a593Smuzhiyun                 return -1;
364*4882a593Smuzhiyun             }
365*4882a593Smuzhiyun             for (n = 0, pre = type->preserve; n < wire.nMapEntries; n++, pre++) {
366*4882a593Smuzhiyun                 if (fread(&p_entry, SIZEOF(xkmModsDesc), 1, file) < 1) {
367*4882a593Smuzhiyun                     _XkbLibError(_XkbErrBadLength, "ReadXkmKeycodes", 0);
368*4882a593Smuzhiyun                     return -1;
369*4882a593Smuzhiyun                 }
370*4882a593Smuzhiyun                 nRead += SIZEOF(xkmModsDesc);
371*4882a593Smuzhiyun                 pre->mask = p_entry.realMods;
372*4882a593Smuzhiyun                 pre->real_mods = p_entry.realMods;
373*4882a593Smuzhiyun                 pre->vmods = p_entry.virtualMods;
374*4882a593Smuzhiyun             }
375*4882a593Smuzhiyun         }
376*4882a593Smuzhiyun         if (wire.nLevelNames > 0) {
377*4882a593Smuzhiyun             int width = wire.numLevels;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun             if (wire.nLevelNames > (unsigned) width) {
380*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadMatch, "ReadXkmKeycodes", 0);
381*4882a593Smuzhiyun                 return -1;
382*4882a593Smuzhiyun             }
383*4882a593Smuzhiyun             XkmInsureTypedSize(type->level_names, type->num_levels, &width,
384*4882a593Smuzhiyun                                Atom);
385*4882a593Smuzhiyun             if (type->level_names != NULL) {
386*4882a593Smuzhiyun                 for (n = 0; n < wire.nLevelNames; n++) {
387*4882a593Smuzhiyun                     if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
388*4882a593Smuzhiyun                         return -1;
389*4882a593Smuzhiyun                     nRead += tmp;
390*4882a593Smuzhiyun                     if (strlen(buf) == 0)
391*4882a593Smuzhiyun                         type->level_names[n] = None;
392*4882a593Smuzhiyun                     else
393*4882a593Smuzhiyun                         type->level_names[n] = XkbInternAtom(buf, 0);
394*4882a593Smuzhiyun                 }
395*4882a593Smuzhiyun             }
396*4882a593Smuzhiyun         }
397*4882a593Smuzhiyun         type->mods.mask = wire.realMods;
398*4882a593Smuzhiyun         type->mods.real_mods = wire.realMods;
399*4882a593Smuzhiyun         type->mods.vmods = wire.virtualMods;
400*4882a593Smuzhiyun         type->num_levels = wire.numLevels;
401*4882a593Smuzhiyun         type->map_count = wire.nMapEntries;
402*4882a593Smuzhiyun     }
403*4882a593Smuzhiyun     if (changes) {
404*4882a593Smuzhiyun         changes->map.changed |= XkbKeyTypesMask;
405*4882a593Smuzhiyun         changes->map.first_type = 0;
406*4882a593Smuzhiyun         changes->map.num_types = xkb->map->num_types;
407*4882a593Smuzhiyun     }
408*4882a593Smuzhiyun     return nRead;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun /***====================================================================***/
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun static int
ReadXkmCompatMap(FILE * file,XkbDescPtr xkb,XkbChangesPtr changes)414*4882a593Smuzhiyun ReadXkmCompatMap(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun     register int i;
417*4882a593Smuzhiyun     unsigned num_si, groups;
418*4882a593Smuzhiyun     char name[100];
419*4882a593Smuzhiyun     XkbSymInterpretPtr interp;
420*4882a593Smuzhiyun     xkmSymInterpretDesc wire;
421*4882a593Smuzhiyun     unsigned tmp;
422*4882a593Smuzhiyun     int nRead = 0;
423*4882a593Smuzhiyun     XkbCompatMapPtr compat;
424*4882a593Smuzhiyun     XkbAction *act;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun     if ((tmp = XkmGetCountedString(file, name, 100)) < 1) {
427*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadLength, "ReadXkmCompatMap", 0);
428*4882a593Smuzhiyun         return -1;
429*4882a593Smuzhiyun     }
430*4882a593Smuzhiyun     nRead += tmp;
431*4882a593Smuzhiyun     if (name[0] != '\0') {
432*4882a593Smuzhiyun         if (XkbAllocNames(xkb, XkbCompatNameMask, 0, 0) != Success) {
433*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadAlloc, "ReadXkmCompatMap", 0);
434*4882a593Smuzhiyun             return -1;
435*4882a593Smuzhiyun         }
436*4882a593Smuzhiyun         xkb->names->compat = XkbInternAtom(name, FALSE);
437*4882a593Smuzhiyun     }
438*4882a593Smuzhiyun     num_si = XkmGetCARD16(file, &nRead);
439*4882a593Smuzhiyun     groups = XkmGetCARD8(file, &nRead);
440*4882a593Smuzhiyun     nRead += XkmSkipPadding(file, 1);
441*4882a593Smuzhiyun     if (XkbAllocCompatMap(xkb, XkbAllCompatMask, num_si) != Success)
442*4882a593Smuzhiyun         return -1;
443*4882a593Smuzhiyun     compat = xkb->compat;
444*4882a593Smuzhiyun     compat->num_si = 0;
445*4882a593Smuzhiyun     interp = compat->sym_interpret;
446*4882a593Smuzhiyun     for (i = 0; i < num_si; i++) {
447*4882a593Smuzhiyun         tmp = fread(&wire, SIZEOF(xkmSymInterpretDesc), 1, file);
448*4882a593Smuzhiyun         nRead += tmp * SIZEOF(xkmSymInterpretDesc);
449*4882a593Smuzhiyun         interp->sym = wire.sym;
450*4882a593Smuzhiyun         interp->mods = wire.mods;
451*4882a593Smuzhiyun         interp->match = wire.match;
452*4882a593Smuzhiyun         interp->virtual_mod = wire.virtualMod;
453*4882a593Smuzhiyun         interp->flags = wire.flags;
454*4882a593Smuzhiyun         interp->act.type = wire.actionType;
455*4882a593Smuzhiyun         act = (XkbAction *) &interp->act;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun         switch (interp->act.type) {
458*4882a593Smuzhiyun         case XkbSA_SetMods:
459*4882a593Smuzhiyun         case XkbSA_LatchMods:
460*4882a593Smuzhiyun         case XkbSA_LockMods:
461*4882a593Smuzhiyun             act->mods.flags = wire.actionData[0];
462*4882a593Smuzhiyun             act->mods.mask = wire.actionData[1];
463*4882a593Smuzhiyun             act->mods.real_mods = wire.actionData[2];
464*4882a593Smuzhiyun             act->mods.vmods1 = wire.actionData[3];
465*4882a593Smuzhiyun             act->mods.vmods2 = wire.actionData[4];
466*4882a593Smuzhiyun             break;
467*4882a593Smuzhiyun         case XkbSA_SetGroup:
468*4882a593Smuzhiyun         case XkbSA_LatchGroup:
469*4882a593Smuzhiyun         case XkbSA_LockGroup:
470*4882a593Smuzhiyun             act->group.flags = wire.actionData[0];
471*4882a593Smuzhiyun             act->group.group_XXX = wire.actionData[1];
472*4882a593Smuzhiyun             break;
473*4882a593Smuzhiyun         case XkbSA_MovePtr:
474*4882a593Smuzhiyun             act->ptr.flags = wire.actionData[0];
475*4882a593Smuzhiyun             act->ptr.high_XXX = wire.actionData[1];
476*4882a593Smuzhiyun             act->ptr.low_XXX = wire.actionData[2];
477*4882a593Smuzhiyun             act->ptr.high_YYY = wire.actionData[3];
478*4882a593Smuzhiyun             act->ptr.low_YYY = wire.actionData[4];
479*4882a593Smuzhiyun             break;
480*4882a593Smuzhiyun         case XkbSA_PtrBtn:
481*4882a593Smuzhiyun         case XkbSA_LockPtrBtn:
482*4882a593Smuzhiyun             act->btn.flags = wire.actionData[0];
483*4882a593Smuzhiyun             act->btn.count = wire.actionData[1];
484*4882a593Smuzhiyun             act->btn.button = wire.actionData[2];
485*4882a593Smuzhiyun             break;
486*4882a593Smuzhiyun         case XkbSA_DeviceBtn:
487*4882a593Smuzhiyun         case XkbSA_LockDeviceBtn:
488*4882a593Smuzhiyun             act->devbtn.flags = wire.actionData[0];
489*4882a593Smuzhiyun             act->devbtn.count = wire.actionData[1];
490*4882a593Smuzhiyun             act->devbtn.button = wire.actionData[2];
491*4882a593Smuzhiyun             act->devbtn.device = wire.actionData[3];
492*4882a593Smuzhiyun             break;
493*4882a593Smuzhiyun         case XkbSA_SetPtrDflt:
494*4882a593Smuzhiyun             act->dflt.flags = wire.actionData[0];
495*4882a593Smuzhiyun             act->dflt.affect = wire.actionData[1];
496*4882a593Smuzhiyun             act->dflt.valueXXX = wire.actionData[2];
497*4882a593Smuzhiyun             break;
498*4882a593Smuzhiyun         case XkbSA_ISOLock:
499*4882a593Smuzhiyun             act->iso.flags = wire.actionData[0];
500*4882a593Smuzhiyun             act->iso.mask = wire.actionData[1];
501*4882a593Smuzhiyun             act->iso.real_mods = wire.actionData[2];
502*4882a593Smuzhiyun             act->iso.group_XXX = wire.actionData[3];
503*4882a593Smuzhiyun             act->iso.affect = wire.actionData[4];
504*4882a593Smuzhiyun             act->iso.vmods1 = wire.actionData[5];
505*4882a593Smuzhiyun             act->iso.vmods2 = wire.actionData[6];
506*4882a593Smuzhiyun             break;
507*4882a593Smuzhiyun         case XkbSA_SwitchScreen:
508*4882a593Smuzhiyun             act->screen.flags = wire.actionData[0];
509*4882a593Smuzhiyun             act->screen.screenXXX = wire.actionData[1];
510*4882a593Smuzhiyun             break;
511*4882a593Smuzhiyun         case XkbSA_SetControls:
512*4882a593Smuzhiyun         case XkbSA_LockControls:
513*4882a593Smuzhiyun             act->ctrls.flags = wire.actionData[0];
514*4882a593Smuzhiyun             act->ctrls.ctrls3 = wire.actionData[1];
515*4882a593Smuzhiyun             act->ctrls.ctrls2 = wire.actionData[2];
516*4882a593Smuzhiyun             act->ctrls.ctrls1 = wire.actionData[3];
517*4882a593Smuzhiyun             act->ctrls.ctrls0 = wire.actionData[4];
518*4882a593Smuzhiyun             break;
519*4882a593Smuzhiyun         case XkbSA_RedirectKey:
520*4882a593Smuzhiyun             act->redirect.new_key = wire.actionData[0];
521*4882a593Smuzhiyun             act->redirect.mods_mask = wire.actionData[1];
522*4882a593Smuzhiyun             act->redirect.mods = wire.actionData[2];
523*4882a593Smuzhiyun             act->redirect.vmods_mask0 = wire.actionData[3];
524*4882a593Smuzhiyun             act->redirect.vmods_mask1 = wire.actionData[4];
525*4882a593Smuzhiyun             act->redirect.vmods0 = wire.actionData[4];
526*4882a593Smuzhiyun             act->redirect.vmods1 = wire.actionData[5];
527*4882a593Smuzhiyun             break;
528*4882a593Smuzhiyun         case XkbSA_DeviceValuator:
529*4882a593Smuzhiyun             act->devval.device = wire.actionData[0];
530*4882a593Smuzhiyun             act->devval.v1_what = wire.actionData[1];
531*4882a593Smuzhiyun             act->devval.v1_ndx = wire.actionData[2];
532*4882a593Smuzhiyun             act->devval.v1_value = wire.actionData[3];
533*4882a593Smuzhiyun             act->devval.v2_what = wire.actionData[4];
534*4882a593Smuzhiyun             act->devval.v2_ndx = wire.actionData[5];
535*4882a593Smuzhiyun             act->devval.v2_what = wire.actionData[6];
536*4882a593Smuzhiyun             break;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun         case XkbSA_XFree86Private:
539*4882a593Smuzhiyun             /*
540*4882a593Smuzhiyun              * Bugfix for broken xkbcomp: if we encounter an XFree86Private
541*4882a593Smuzhiyun              * action with Any+AnyOfOrNone(All), then we skip the interp as
542*4882a593Smuzhiyun              * broken.  Versions of xkbcomp below 1.2.2 had a bug where they
543*4882a593Smuzhiyun              * would interpret a symbol that couldn't be found in an interpret
544*4882a593Smuzhiyun              * as Any.  So, an XF86LogWindowTree+AnyOfOrNone(All) interp that
545*4882a593Smuzhiyun              * triggered the PrWins action would make every key without an
546*4882a593Smuzhiyun              * action trigger PrWins if libX11 didn't yet know about the
547*4882a593Smuzhiyun              * XF86LogWindowTree keysym.  None too useful.
548*4882a593Smuzhiyun              *
549*4882a593Smuzhiyun              * We only do this for XFree86 actions, as the current XKB
550*4882a593Smuzhiyun              * dataset relies on Any+AnyOfOrNone(All) -> SetMods for Ctrl in
551*4882a593Smuzhiyun              * particular.
552*4882a593Smuzhiyun              *
553*4882a593Smuzhiyun              * See xkbcomp commits 2a473b906943ffd807ad81960c47530ee7ae9a60 and
554*4882a593Smuzhiyun              * 3caab5aa37decb7b5dc1642a0452efc3e1f5100e for more details.
555*4882a593Smuzhiyun              */
556*4882a593Smuzhiyun             if (interp->sym == NoSymbol && interp->match == XkbSI_AnyOfOrNone &&
557*4882a593Smuzhiyun                 (interp->mods & 0xff) == 0xff) {
558*4882a593Smuzhiyun                 ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
559*4882a593Smuzhiyun                        "action from compiled keymap\n");
560*4882a593Smuzhiyun                 continue;
561*4882a593Smuzhiyun             }
562*4882a593Smuzhiyun             /* copy the kind of action */
563*4882a593Smuzhiyun             memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize);
564*4882a593Smuzhiyun             break;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun         case XkbSA_Terminate:
567*4882a593Smuzhiyun             /* no args, kinda (note: untrue for xfree86). */
568*4882a593Smuzhiyun             break;
569*4882a593Smuzhiyun         case XkbSA_ActionMessage:
570*4882a593Smuzhiyun             /* unsupported. */
571*4882a593Smuzhiyun             break;
572*4882a593Smuzhiyun         }
573*4882a593Smuzhiyun         interp++;
574*4882a593Smuzhiyun         compat->num_si++;
575*4882a593Smuzhiyun     }
576*4882a593Smuzhiyun     if ((num_si > 0) && (changes)) {
577*4882a593Smuzhiyun         changes->compat.first_si = 0;
578*4882a593Smuzhiyun         changes->compat.num_si = compat->num_si;
579*4882a593Smuzhiyun     }
580*4882a593Smuzhiyun     if (groups) {
581*4882a593Smuzhiyun         register unsigned bit;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun         for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
584*4882a593Smuzhiyun             xkmModsDesc md;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun             if (groups & bit) {
587*4882a593Smuzhiyun                 tmp = fread(&md, SIZEOF(xkmModsDesc), 1, file);
588*4882a593Smuzhiyun                 nRead += tmp * SIZEOF(xkmModsDesc);
589*4882a593Smuzhiyun                 xkb->compat->groups[i].real_mods = md.realMods;
590*4882a593Smuzhiyun                 xkb->compat->groups[i].vmods = md.virtualMods;
591*4882a593Smuzhiyun                 if (md.virtualMods != 0) {
592*4882a593Smuzhiyun                     unsigned mask;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun                     if (XkbVirtualModsToReal(xkb, md.virtualMods, &mask))
595*4882a593Smuzhiyun                         xkb->compat->groups[i].mask = md.realMods | mask;
596*4882a593Smuzhiyun                 }
597*4882a593Smuzhiyun                 else
598*4882a593Smuzhiyun                     xkb->compat->groups[i].mask = md.realMods;
599*4882a593Smuzhiyun             }
600*4882a593Smuzhiyun         }
601*4882a593Smuzhiyun         if (changes)
602*4882a593Smuzhiyun             changes->compat.changed_groups |= groups;
603*4882a593Smuzhiyun     }
604*4882a593Smuzhiyun     return nRead;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun static int
ReadXkmIndicators(FILE * file,XkbDescPtr xkb,XkbChangesPtr changes)608*4882a593Smuzhiyun ReadXkmIndicators(FILE * file, XkbDescPtr xkb, XkbChangesPtr changes)
609*4882a593Smuzhiyun {
610*4882a593Smuzhiyun     register unsigned nLEDs;
611*4882a593Smuzhiyun     xkmIndicatorMapDesc wire;
612*4882a593Smuzhiyun     char buf[100];
613*4882a593Smuzhiyun     unsigned tmp;
614*4882a593Smuzhiyun     int nRead = 0;
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun     if ((xkb->indicators == NULL) && (XkbAllocIndicatorMaps(xkb) != Success)) {
617*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "indicator rec", 0);
618*4882a593Smuzhiyun         return -1;
619*4882a593Smuzhiyun     }
620*4882a593Smuzhiyun     if (XkbAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success) {
621*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "indicator names", 0);
622*4882a593Smuzhiyun         return -1;
623*4882a593Smuzhiyun     }
624*4882a593Smuzhiyun     nLEDs = XkmGetCARD8(file, &nRead);
625*4882a593Smuzhiyun     nRead += XkmSkipPadding(file, 3);
626*4882a593Smuzhiyun     xkb->indicators->phys_indicators = XkmGetCARD32(file, &nRead);
627*4882a593Smuzhiyun     while (nLEDs-- > 0) {
628*4882a593Smuzhiyun         Atom name;
629*4882a593Smuzhiyun         XkbIndicatorMapPtr map;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun         if ((tmp = XkmGetCountedString(file, buf, 100)) < 1) {
632*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmIndicators", 0);
633*4882a593Smuzhiyun             return -1;
634*4882a593Smuzhiyun         }
635*4882a593Smuzhiyun         nRead += tmp;
636*4882a593Smuzhiyun         if (buf[0] != '\0')
637*4882a593Smuzhiyun             name = XkbInternAtom(buf, FALSE);
638*4882a593Smuzhiyun         else
639*4882a593Smuzhiyun             name = None;
640*4882a593Smuzhiyun         if ((tmp = fread(&wire, SIZEOF(xkmIndicatorMapDesc), 1, file)) < 1) {
641*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmIndicators", 0);
642*4882a593Smuzhiyun             return -1;
643*4882a593Smuzhiyun         }
644*4882a593Smuzhiyun         nRead += tmp * SIZEOF(xkmIndicatorMapDesc);
645*4882a593Smuzhiyun         if (xkb->names) {
646*4882a593Smuzhiyun             xkb->names->indicators[wire.indicator - 1] = name;
647*4882a593Smuzhiyun             if (changes)
648*4882a593Smuzhiyun                 changes->names.changed_indicators |=
649*4882a593Smuzhiyun                     (1 << (wire.indicator - 1));
650*4882a593Smuzhiyun         }
651*4882a593Smuzhiyun         map = &xkb->indicators->maps[wire.indicator - 1];
652*4882a593Smuzhiyun         map->flags = wire.flags;
653*4882a593Smuzhiyun         map->which_groups = wire.which_groups;
654*4882a593Smuzhiyun         map->groups = wire.groups;
655*4882a593Smuzhiyun         map->which_mods = wire.which_mods;
656*4882a593Smuzhiyun         map->mods.mask = wire.real_mods;
657*4882a593Smuzhiyun         map->mods.real_mods = wire.real_mods;
658*4882a593Smuzhiyun         map->mods.vmods = wire.vmods;
659*4882a593Smuzhiyun         map->ctrls = wire.ctrls;
660*4882a593Smuzhiyun     }
661*4882a593Smuzhiyun     return nRead;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun static XkbKeyTypePtr
FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym * syms)665*4882a593Smuzhiyun FindTypeForKey(XkbDescPtr xkb, Atom name, unsigned width, KeySym * syms)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun     if ((!xkb) || (!xkb->map))
668*4882a593Smuzhiyun         return NULL;
669*4882a593Smuzhiyun     if (name != None) {
670*4882a593Smuzhiyun         register unsigned i;
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun         for (i = 0; i < xkb->map->num_types; i++) {
673*4882a593Smuzhiyun             if (xkb->map->types[i].name == name) {
674*4882a593Smuzhiyun                 if (xkb->map->types[i].num_levels != width)
675*4882a593Smuzhiyun                     DebugF("Group width mismatch between key and type\n");
676*4882a593Smuzhiyun                 return &xkb->map->types[i];
677*4882a593Smuzhiyun             }
678*4882a593Smuzhiyun         }
679*4882a593Smuzhiyun     }
680*4882a593Smuzhiyun     if ((width < 2) || ((syms != NULL) && (syms[1] == NoSymbol)))
681*4882a593Smuzhiyun         return &xkb->map->types[XkbOneLevelIndex];
682*4882a593Smuzhiyun     if (syms != NULL) {
683*4882a593Smuzhiyun         if (XkbKSIsLower(syms[0]) && XkbKSIsUpper(syms[1]))
684*4882a593Smuzhiyun             return &xkb->map->types[XkbAlphabeticIndex];
685*4882a593Smuzhiyun         else if (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1]))
686*4882a593Smuzhiyun             return &xkb->map->types[XkbKeypadIndex];
687*4882a593Smuzhiyun     }
688*4882a593Smuzhiyun     return &xkb->map->types[XkbTwoLevelIndex];
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun static int
ReadXkmSymbols(FILE * file,XkbDescPtr xkb)692*4882a593Smuzhiyun ReadXkmSymbols(FILE * file, XkbDescPtr xkb)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun     register int i, g, s, totalVModMaps;
695*4882a593Smuzhiyun     xkmKeySymMapDesc wireMap;
696*4882a593Smuzhiyun     char buf[100];
697*4882a593Smuzhiyun     unsigned minKC, maxKC, groupNames, tmp;
698*4882a593Smuzhiyun     int nRead = 0;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
701*4882a593Smuzhiyun         return -1;
702*4882a593Smuzhiyun     nRead += tmp;
703*4882a593Smuzhiyun     minKC = XkmGetCARD8(file, &nRead);
704*4882a593Smuzhiyun     maxKC = XkmGetCARD8(file, &nRead);
705*4882a593Smuzhiyun     groupNames = XkmGetCARD8(file, &nRead);
706*4882a593Smuzhiyun     totalVModMaps = XkmGetCARD8(file, &nRead);
707*4882a593Smuzhiyun     if (XkbAllocNames(xkb,
708*4882a593Smuzhiyun                       XkbSymbolsNameMask | XkbPhysSymbolsNameMask |
709*4882a593Smuzhiyun                       XkbGroupNamesMask, 0, 0) != Success) {
710*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "physical names", 0);
711*4882a593Smuzhiyun         return -1;
712*4882a593Smuzhiyun     }
713*4882a593Smuzhiyun     if ((buf[0] != '\0') && (xkb->names)) {
714*4882a593Smuzhiyun         Atom name;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun         name = XkbInternAtom(buf, 0);
717*4882a593Smuzhiyun         xkb->names->symbols = name;
718*4882a593Smuzhiyun         xkb->names->phys_symbols = name;
719*4882a593Smuzhiyun     }
720*4882a593Smuzhiyun     for (i = 0, g = 1; i < XkbNumKbdGroups; i++, g <<= 1) {
721*4882a593Smuzhiyun         if (groupNames & g) {
722*4882a593Smuzhiyun             if ((tmp = XkmGetCountedString(file, buf, 100)) < 1)
723*4882a593Smuzhiyun                 return -1;
724*4882a593Smuzhiyun             nRead += tmp;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun             if (!xkb->names)
727*4882a593Smuzhiyun                 continue;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun             if (buf[0] != '\0') {
730*4882a593Smuzhiyun                 Atom name;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun                 name = XkbInternAtom(buf, 0);
733*4882a593Smuzhiyun                 xkb->names->groups[i] = name;
734*4882a593Smuzhiyun             }
735*4882a593Smuzhiyun             else
736*4882a593Smuzhiyun                 xkb->names->groups[i] = None;
737*4882a593Smuzhiyun         }
738*4882a593Smuzhiyun     }
739*4882a593Smuzhiyun     if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, 0) != Success) {
740*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "server map", 0);
741*4882a593Smuzhiyun         return -1;
742*4882a593Smuzhiyun     }
743*4882a593Smuzhiyun     if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success) {
744*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "client map", 0);
745*4882a593Smuzhiyun         return -1;
746*4882a593Smuzhiyun     }
747*4882a593Smuzhiyun     if (XkbAllocControls(xkb, XkbAllControlsMask) != Success) {
748*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "controls", 0);
749*4882a593Smuzhiyun         return -1;
750*4882a593Smuzhiyun     }
751*4882a593Smuzhiyun     if ((xkb->map == NULL) || (xkb->server == NULL))
752*4882a593Smuzhiyun         return -1;
753*4882a593Smuzhiyun     if (xkb->min_key_code < 8)
754*4882a593Smuzhiyun         xkb->min_key_code = minKC;
755*4882a593Smuzhiyun     if (xkb->max_key_code < 8)
756*4882a593Smuzhiyun         xkb->max_key_code = maxKC;
757*4882a593Smuzhiyun     if ((minKC >= 8) && (minKC < xkb->min_key_code))
758*4882a593Smuzhiyun         xkb->min_key_code = minKC;
759*4882a593Smuzhiyun     if ((maxKC >= 8) && (maxKC > xkb->max_key_code)) {
760*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadValue, "keys in symbol map", maxKC);
761*4882a593Smuzhiyun         return -1;
762*4882a593Smuzhiyun     }
763*4882a593Smuzhiyun     for (i = minKC; i <= (int) maxKC; i++) {
764*4882a593Smuzhiyun         Atom typeName[XkbNumKbdGroups];
765*4882a593Smuzhiyun         XkbKeyTypePtr type[XkbNumKbdGroups];
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun         if ((tmp = fread(&wireMap, SIZEOF(xkmKeySymMapDesc), 1, file)) < 1) {
768*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmSymbols", 0);
769*4882a593Smuzhiyun             return -1;
770*4882a593Smuzhiyun         }
771*4882a593Smuzhiyun         nRead += tmp * SIZEOF(xkmKeySymMapDesc);
772*4882a593Smuzhiyun         memset((char *) typeName, 0, XkbNumKbdGroups * sizeof(Atom));
773*4882a593Smuzhiyun         memset((char *) type, 0, XkbNumKbdGroups * sizeof(XkbKeyTypePtr));
774*4882a593Smuzhiyun         if (wireMap.flags & XkmKeyHasTypes) {
775*4882a593Smuzhiyun             for (g = 0; g < XkbNumKbdGroups; g++) {
776*4882a593Smuzhiyun                 if ((wireMap.flags & (1 << g)) &&
777*4882a593Smuzhiyun                     ((tmp = XkmGetCountedString(file, buf, 100)) > 0)) {
778*4882a593Smuzhiyun                     typeName[g] = XkbInternAtom(buf, 1);
779*4882a593Smuzhiyun                     nRead += tmp;
780*4882a593Smuzhiyun                 }
781*4882a593Smuzhiyun                 type[g] = FindTypeForKey(xkb, typeName[g], wireMap.width, NULL);
782*4882a593Smuzhiyun                 if (type[g] == NULL) {
783*4882a593Smuzhiyun                     _XkbLibError(_XkbErrMissingTypes, "ReadXkmSymbols", 0);
784*4882a593Smuzhiyun                     return -1;
785*4882a593Smuzhiyun                 }
786*4882a593Smuzhiyun                 if (typeName[g] == type[g]->name)
787*4882a593Smuzhiyun                     xkb->server->explicit[i] |= (1 << g);
788*4882a593Smuzhiyun             }
789*4882a593Smuzhiyun         }
790*4882a593Smuzhiyun         if (wireMap.flags & XkmRepeatingKey) {
791*4882a593Smuzhiyun             xkb->ctrls->per_key_repeat[i / 8] |= (1 << (i % 8));
792*4882a593Smuzhiyun             xkb->server->explicit[i] |= XkbExplicitAutoRepeatMask;
793*4882a593Smuzhiyun         }
794*4882a593Smuzhiyun         else if (wireMap.flags & XkmNonRepeatingKey) {
795*4882a593Smuzhiyun             xkb->ctrls->per_key_repeat[i / 8] &= ~(1 << (i % 8));
796*4882a593Smuzhiyun             xkb->server->explicit[i] |= XkbExplicitAutoRepeatMask;
797*4882a593Smuzhiyun         }
798*4882a593Smuzhiyun         xkb->map->modmap[i] = wireMap.modifier_map;
799*4882a593Smuzhiyun         if (XkbNumGroups(wireMap.num_groups) > 0) {
800*4882a593Smuzhiyun             KeySym *sym;
801*4882a593Smuzhiyun             int nSyms;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun             if (XkbNumGroups(wireMap.num_groups) > xkb->ctrls->num_groups)
804*4882a593Smuzhiyun                 xkb->ctrls->num_groups = wireMap.num_groups;
805*4882a593Smuzhiyun             nSyms = XkbNumGroups(wireMap.num_groups) * wireMap.width;
806*4882a593Smuzhiyun             sym = XkbResizeKeySyms(xkb, i, nSyms);
807*4882a593Smuzhiyun             if (!sym)
808*4882a593Smuzhiyun                 return -1;
809*4882a593Smuzhiyun             for (s = 0; s < nSyms; s++) {
810*4882a593Smuzhiyun                 *sym++ = XkmGetCARD32(file, &nRead);
811*4882a593Smuzhiyun             }
812*4882a593Smuzhiyun             if (wireMap.flags & XkmKeyHasActions) {
813*4882a593Smuzhiyun                 XkbAction *act;
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun                 act = XkbResizeKeyActions(xkb, i, nSyms);
816*4882a593Smuzhiyun                 for (s = 0; s < nSyms; s++, act++) {
817*4882a593Smuzhiyun                     tmp = fread(act, SIZEOF(xkmActionDesc), 1, file);
818*4882a593Smuzhiyun                     nRead += tmp * SIZEOF(xkmActionDesc);
819*4882a593Smuzhiyun                 }
820*4882a593Smuzhiyun                 xkb->server->explicit[i] |= XkbExplicitInterpretMask;
821*4882a593Smuzhiyun             }
822*4882a593Smuzhiyun         }
823*4882a593Smuzhiyun         for (g = 0; g < XkbNumGroups(wireMap.num_groups); g++) {
824*4882a593Smuzhiyun             if (((xkb->server->explicit[i] & (1 << g)) == 0) ||
825*4882a593Smuzhiyun                 (type[g] == NULL)) {
826*4882a593Smuzhiyun                 KeySym *tmpSyms;
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun                 tmpSyms = XkbKeySymsPtr(xkb, i) + (wireMap.width * g);
829*4882a593Smuzhiyun                 type[g] = FindTypeForKey(xkb, None, wireMap.width, tmpSyms);
830*4882a593Smuzhiyun             }
831*4882a593Smuzhiyun             xkb->map->key_sym_map[i].kt_index[g] =
832*4882a593Smuzhiyun                 type[g] - (&xkb->map->types[0]);
833*4882a593Smuzhiyun         }
834*4882a593Smuzhiyun         xkb->map->key_sym_map[i].group_info = wireMap.num_groups;
835*4882a593Smuzhiyun         xkb->map->key_sym_map[i].width = wireMap.width;
836*4882a593Smuzhiyun         if (wireMap.flags & XkmKeyHasBehavior) {
837*4882a593Smuzhiyun             xkmBehaviorDesc b;
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun             tmp = fread(&b, SIZEOF(xkmBehaviorDesc), 1, file);
840*4882a593Smuzhiyun             nRead += tmp * SIZEOF(xkmBehaviorDesc);
841*4882a593Smuzhiyun             xkb->server->behaviors[i].type = b.type;
842*4882a593Smuzhiyun             xkb->server->behaviors[i].data = b.data;
843*4882a593Smuzhiyun             xkb->server->explicit[i] |= XkbExplicitBehaviorMask;
844*4882a593Smuzhiyun         }
845*4882a593Smuzhiyun     }
846*4882a593Smuzhiyun     if (totalVModMaps > 0) {
847*4882a593Smuzhiyun         xkmVModMapDesc v;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun         for (i = 0; i < totalVModMaps; i++) {
850*4882a593Smuzhiyun             tmp = fread(&v, SIZEOF(xkmVModMapDesc), 1, file);
851*4882a593Smuzhiyun             nRead += tmp * SIZEOF(xkmVModMapDesc);
852*4882a593Smuzhiyun             if (tmp > 0)
853*4882a593Smuzhiyun                 xkb->server->vmodmap[v.key] = v.vmods;
854*4882a593Smuzhiyun         }
855*4882a593Smuzhiyun     }
856*4882a593Smuzhiyun     return nRead;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun static int
ReadXkmGeomDoodad(FILE * file,XkbGeometryPtr geom,XkbSectionPtr section)860*4882a593Smuzhiyun ReadXkmGeomDoodad(FILE * file, XkbGeometryPtr geom, XkbSectionPtr section)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun     XkbDoodadPtr doodad;
863*4882a593Smuzhiyun     xkmDoodadDesc doodadWire;
864*4882a593Smuzhiyun     char buf[100];
865*4882a593Smuzhiyun     unsigned tmp;
866*4882a593Smuzhiyun     int nRead = 0;
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, buf, 100);
869*4882a593Smuzhiyun     tmp = fread(&doodadWire, SIZEOF(xkmDoodadDesc), 1, file);
870*4882a593Smuzhiyun     nRead += SIZEOF(xkmDoodadDesc) * tmp;
871*4882a593Smuzhiyun     doodad = XkbAddGeomDoodad(geom, section, XkbInternAtom(buf, FALSE));
872*4882a593Smuzhiyun     if (!doodad)
873*4882a593Smuzhiyun         return nRead;
874*4882a593Smuzhiyun     doodad->any.type = doodadWire.any.type;
875*4882a593Smuzhiyun     doodad->any.priority = doodadWire.any.priority;
876*4882a593Smuzhiyun     doodad->any.top = doodadWire.any.top;
877*4882a593Smuzhiyun     doodad->any.left = doodadWire.any.left;
878*4882a593Smuzhiyun     switch (doodadWire.any.type) {
879*4882a593Smuzhiyun     case XkbOutlineDoodad:
880*4882a593Smuzhiyun     case XkbSolidDoodad:
881*4882a593Smuzhiyun         doodad->shape.angle = doodadWire.shape.angle;
882*4882a593Smuzhiyun         doodad->shape.color_ndx = doodadWire.shape.color_ndx;
883*4882a593Smuzhiyun         doodad->shape.shape_ndx = doodadWire.shape.shape_ndx;
884*4882a593Smuzhiyun         break;
885*4882a593Smuzhiyun     case XkbTextDoodad:
886*4882a593Smuzhiyun         doodad->text.angle = doodadWire.text.angle;
887*4882a593Smuzhiyun         doodad->text.width = doodadWire.text.width;
888*4882a593Smuzhiyun         doodad->text.height = doodadWire.text.height;
889*4882a593Smuzhiyun         doodad->text.color_ndx = doodadWire.text.color_ndx;
890*4882a593Smuzhiyun         nRead += XkmGetCountedString(file, buf, 100);
891*4882a593Smuzhiyun         doodad->text.text = Xstrdup(buf);
892*4882a593Smuzhiyun         nRead += XkmGetCountedString(file, buf, 100);
893*4882a593Smuzhiyun         doodad->text.font = Xstrdup(buf);
894*4882a593Smuzhiyun         break;
895*4882a593Smuzhiyun     case XkbIndicatorDoodad:
896*4882a593Smuzhiyun         doodad->indicator.shape_ndx = doodadWire.indicator.shape_ndx;
897*4882a593Smuzhiyun         doodad->indicator.on_color_ndx = doodadWire.indicator.on_color_ndx;
898*4882a593Smuzhiyun         doodad->indicator.off_color_ndx = doodadWire.indicator.off_color_ndx;
899*4882a593Smuzhiyun         break;
900*4882a593Smuzhiyun     case XkbLogoDoodad:
901*4882a593Smuzhiyun         doodad->logo.angle = doodadWire.logo.angle;
902*4882a593Smuzhiyun         doodad->logo.color_ndx = doodadWire.logo.color_ndx;
903*4882a593Smuzhiyun         doodad->logo.shape_ndx = doodadWire.logo.shape_ndx;
904*4882a593Smuzhiyun         nRead += XkmGetCountedString(file, buf, 100);
905*4882a593Smuzhiyun         doodad->logo.logo_name = Xstrdup(buf);
906*4882a593Smuzhiyun         break;
907*4882a593Smuzhiyun     default:
908*4882a593Smuzhiyun         /* report error? */
909*4882a593Smuzhiyun         return nRead;
910*4882a593Smuzhiyun     }
911*4882a593Smuzhiyun     return nRead;
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun static int
ReadXkmGeomOverlay(FILE * file,XkbGeometryPtr geom,XkbSectionPtr section)915*4882a593Smuzhiyun ReadXkmGeomOverlay(FILE * file, XkbGeometryPtr geom, XkbSectionPtr section)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun     char buf[100];
918*4882a593Smuzhiyun     unsigned tmp;
919*4882a593Smuzhiyun     int nRead = 0;
920*4882a593Smuzhiyun     XkbOverlayPtr ol;
921*4882a593Smuzhiyun     XkbOverlayRowPtr row;
922*4882a593Smuzhiyun     xkmOverlayDesc olWire;
923*4882a593Smuzhiyun     xkmOverlayRowDesc rowWire;
924*4882a593Smuzhiyun     register int r;
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, buf, 100);
927*4882a593Smuzhiyun     tmp = fread(&olWire, SIZEOF(xkmOverlayDesc), 1, file);
928*4882a593Smuzhiyun     nRead += tmp * SIZEOF(xkmOverlayDesc);
929*4882a593Smuzhiyun     ol = XkbAddGeomOverlay(section, XkbInternAtom(buf, FALSE), olWire.num_rows);
930*4882a593Smuzhiyun     if (!ol)
931*4882a593Smuzhiyun         return nRead;
932*4882a593Smuzhiyun     for (r = 0; r < olWire.num_rows; r++) {
933*4882a593Smuzhiyun         int k;
934*4882a593Smuzhiyun         xkmOverlayKeyDesc keyWire;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun         tmp = fread(&rowWire, SIZEOF(xkmOverlayRowDesc), 1, file);
937*4882a593Smuzhiyun         nRead += tmp * SIZEOF(xkmOverlayRowDesc);
938*4882a593Smuzhiyun         row = XkbAddGeomOverlayRow(ol, rowWire.row_under, rowWire.num_keys);
939*4882a593Smuzhiyun         if (!row) {
940*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomOverlay", 0);
941*4882a593Smuzhiyun             return nRead;
942*4882a593Smuzhiyun         }
943*4882a593Smuzhiyun         for (k = 0; k < rowWire.num_keys; k++) {
944*4882a593Smuzhiyun             tmp = fread(&keyWire, SIZEOF(xkmOverlayKeyDesc), 1, file);
945*4882a593Smuzhiyun             nRead += tmp * SIZEOF(xkmOverlayKeyDesc);
946*4882a593Smuzhiyun             memcpy(row->keys[k].over.name, keyWire.over, XkbKeyNameLength);
947*4882a593Smuzhiyun             memcpy(row->keys[k].under.name, keyWire.under, XkbKeyNameLength);
948*4882a593Smuzhiyun         }
949*4882a593Smuzhiyun         row->num_keys = rowWire.num_keys;
950*4882a593Smuzhiyun     }
951*4882a593Smuzhiyun     return nRead;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun static int
ReadXkmGeomSection(FILE * file,XkbGeometryPtr geom)955*4882a593Smuzhiyun ReadXkmGeomSection(FILE * file, XkbGeometryPtr geom)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun     register int i;
958*4882a593Smuzhiyun     XkbSectionPtr section;
959*4882a593Smuzhiyun     xkmSectionDesc sectionWire;
960*4882a593Smuzhiyun     unsigned tmp;
961*4882a593Smuzhiyun     int nRead = 0;
962*4882a593Smuzhiyun     char buf[100];
963*4882a593Smuzhiyun     Atom nameAtom;
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, buf, 100);
966*4882a593Smuzhiyun     nameAtom = XkbInternAtom(buf, FALSE);
967*4882a593Smuzhiyun     tmp = fread(&sectionWire, SIZEOF(xkmSectionDesc), 1, file);
968*4882a593Smuzhiyun     nRead += SIZEOF(xkmSectionDesc) * tmp;
969*4882a593Smuzhiyun     section = XkbAddGeomSection(geom, nameAtom, sectionWire.num_rows,
970*4882a593Smuzhiyun                                 sectionWire.num_doodads,
971*4882a593Smuzhiyun                                 sectionWire.num_overlays);
972*4882a593Smuzhiyun     if (!section) {
973*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomSection", 0);
974*4882a593Smuzhiyun         return nRead;
975*4882a593Smuzhiyun     }
976*4882a593Smuzhiyun     section->top = sectionWire.top;
977*4882a593Smuzhiyun     section->left = sectionWire.left;
978*4882a593Smuzhiyun     section->width = sectionWire.width;
979*4882a593Smuzhiyun     section->height = sectionWire.height;
980*4882a593Smuzhiyun     section->angle = sectionWire.angle;
981*4882a593Smuzhiyun     section->priority = sectionWire.priority;
982*4882a593Smuzhiyun     if (sectionWire.num_rows > 0) {
983*4882a593Smuzhiyun         register int k;
984*4882a593Smuzhiyun         XkbRowPtr row;
985*4882a593Smuzhiyun         xkmRowDesc rowWire;
986*4882a593Smuzhiyun         XkbKeyPtr key;
987*4882a593Smuzhiyun         xkmKeyDesc keyWire;
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun         for (i = 0; i < sectionWire.num_rows; i++) {
990*4882a593Smuzhiyun             tmp = fread(&rowWire, SIZEOF(xkmRowDesc), 1, file);
991*4882a593Smuzhiyun             nRead += SIZEOF(xkmRowDesc) * tmp;
992*4882a593Smuzhiyun             row = XkbAddGeomRow(section, rowWire.num_keys);
993*4882a593Smuzhiyun             if (!row) {
994*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadAlloc, "ReadXkmKeycodes", 0);
995*4882a593Smuzhiyun                 return nRead;
996*4882a593Smuzhiyun             }
997*4882a593Smuzhiyun             row->top = rowWire.top;
998*4882a593Smuzhiyun             row->left = rowWire.left;
999*4882a593Smuzhiyun             row->vertical = rowWire.vertical;
1000*4882a593Smuzhiyun             for (k = 0; k < rowWire.num_keys; k++) {
1001*4882a593Smuzhiyun                 tmp = fread(&keyWire, SIZEOF(xkmKeyDesc), 1, file);
1002*4882a593Smuzhiyun                 nRead += SIZEOF(xkmKeyDesc) * tmp;
1003*4882a593Smuzhiyun                 key = XkbAddGeomKey(row);
1004*4882a593Smuzhiyun                 if (!key) {
1005*4882a593Smuzhiyun                     _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeomSection", 0);
1006*4882a593Smuzhiyun                     return nRead;
1007*4882a593Smuzhiyun                 }
1008*4882a593Smuzhiyun                 memcpy(key->name.name, keyWire.name, XkbKeyNameLength);
1009*4882a593Smuzhiyun                 key->gap = keyWire.gap;
1010*4882a593Smuzhiyun                 key->shape_ndx = keyWire.shape_ndx;
1011*4882a593Smuzhiyun                 key->color_ndx = keyWire.color_ndx;
1012*4882a593Smuzhiyun             }
1013*4882a593Smuzhiyun         }
1014*4882a593Smuzhiyun     }
1015*4882a593Smuzhiyun     if (sectionWire.num_doodads > 0) {
1016*4882a593Smuzhiyun         for (i = 0; i < sectionWire.num_doodads; i++) {
1017*4882a593Smuzhiyun             tmp = ReadXkmGeomDoodad(file, geom, section);
1018*4882a593Smuzhiyun             nRead += tmp;
1019*4882a593Smuzhiyun             if (tmp < 1)
1020*4882a593Smuzhiyun                 return nRead;
1021*4882a593Smuzhiyun         }
1022*4882a593Smuzhiyun     }
1023*4882a593Smuzhiyun     if (sectionWire.num_overlays > 0) {
1024*4882a593Smuzhiyun         for (i = 0; i < sectionWire.num_overlays; i++) {
1025*4882a593Smuzhiyun             tmp = ReadXkmGeomOverlay(file, geom, section);
1026*4882a593Smuzhiyun             nRead += tmp;
1027*4882a593Smuzhiyun             if (tmp < 1)
1028*4882a593Smuzhiyun                 return nRead;
1029*4882a593Smuzhiyun         }
1030*4882a593Smuzhiyun     }
1031*4882a593Smuzhiyun     return nRead;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun static int
ReadXkmGeometry(FILE * file,XkbDescPtr xkb)1035*4882a593Smuzhiyun ReadXkmGeometry(FILE * file, XkbDescPtr xkb)
1036*4882a593Smuzhiyun {
1037*4882a593Smuzhiyun     register int i;
1038*4882a593Smuzhiyun     char buf[100];
1039*4882a593Smuzhiyun     unsigned tmp;
1040*4882a593Smuzhiyun     int nRead = 0;
1041*4882a593Smuzhiyun     xkmGeometryDesc wireGeom;
1042*4882a593Smuzhiyun     XkbGeometryPtr geom;
1043*4882a593Smuzhiyun     XkbGeometrySizesRec sizes;
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, buf, 100);
1046*4882a593Smuzhiyun     tmp = fread(&wireGeom, SIZEOF(xkmGeometryDesc), 1, file);
1047*4882a593Smuzhiyun     nRead += tmp * SIZEOF(xkmGeometryDesc);
1048*4882a593Smuzhiyun     sizes.which = XkbGeomAllMask;
1049*4882a593Smuzhiyun     sizes.num_properties = wireGeom.num_properties;
1050*4882a593Smuzhiyun     sizes.num_colors = wireGeom.num_colors;
1051*4882a593Smuzhiyun     sizes.num_shapes = wireGeom.num_shapes;
1052*4882a593Smuzhiyun     sizes.num_sections = wireGeom.num_sections;
1053*4882a593Smuzhiyun     sizes.num_doodads = wireGeom.num_doodads;
1054*4882a593Smuzhiyun     sizes.num_key_aliases = wireGeom.num_key_aliases;
1055*4882a593Smuzhiyun     if (XkbAllocGeometry(xkb, &sizes) != Success) {
1056*4882a593Smuzhiyun         _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
1057*4882a593Smuzhiyun         return nRead;
1058*4882a593Smuzhiyun     }
1059*4882a593Smuzhiyun     geom = xkb->geom;
1060*4882a593Smuzhiyun     geom->name = XkbInternAtom(buf, FALSE);
1061*4882a593Smuzhiyun     geom->width_mm = wireGeom.width_mm;
1062*4882a593Smuzhiyun     geom->height_mm = wireGeom.height_mm;
1063*4882a593Smuzhiyun     nRead += XkmGetCountedString(file, buf, 100);
1064*4882a593Smuzhiyun     geom->label_font = Xstrdup(buf);
1065*4882a593Smuzhiyun     if (wireGeom.num_properties > 0) {
1066*4882a593Smuzhiyun         char val[1024];
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun         for (i = 0; i < wireGeom.num_properties; i++) {
1069*4882a593Smuzhiyun             nRead += XkmGetCountedString(file, buf, 100);
1070*4882a593Smuzhiyun             nRead += XkmGetCountedString(file, val, 1024);
1071*4882a593Smuzhiyun             if (XkbAddGeomProperty(geom, buf, val) == NULL) {
1072*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
1073*4882a593Smuzhiyun                 return nRead;
1074*4882a593Smuzhiyun             }
1075*4882a593Smuzhiyun         }
1076*4882a593Smuzhiyun     }
1077*4882a593Smuzhiyun     if (wireGeom.num_colors > 0) {
1078*4882a593Smuzhiyun         for (i = 0; i < wireGeom.num_colors; i++) {
1079*4882a593Smuzhiyun             nRead += XkmGetCountedString(file, buf, 100);
1080*4882a593Smuzhiyun             if (XkbAddGeomColor(geom, buf, i) == NULL) {
1081*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
1082*4882a593Smuzhiyun                 return nRead;
1083*4882a593Smuzhiyun             }
1084*4882a593Smuzhiyun         }
1085*4882a593Smuzhiyun     }
1086*4882a593Smuzhiyun     geom->base_color = &geom->colors[wireGeom.base_color_ndx];
1087*4882a593Smuzhiyun     geom->label_color = &geom->colors[wireGeom.label_color_ndx];
1088*4882a593Smuzhiyun     if (wireGeom.num_shapes > 0) {
1089*4882a593Smuzhiyun         XkbShapePtr shape;
1090*4882a593Smuzhiyun         xkmShapeDesc shapeWire;
1091*4882a593Smuzhiyun         Atom nameAtom;
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun         for (i = 0; i < wireGeom.num_shapes; i++) {
1094*4882a593Smuzhiyun             register int n;
1095*4882a593Smuzhiyun             XkbOutlinePtr ol;
1096*4882a593Smuzhiyun             xkmOutlineDesc olWire;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun             nRead += XkmGetCountedString(file, buf, 100);
1099*4882a593Smuzhiyun             nameAtom = XkbInternAtom(buf, FALSE);
1100*4882a593Smuzhiyun             tmp = fread(&shapeWire, SIZEOF(xkmShapeDesc), 1, file);
1101*4882a593Smuzhiyun             nRead += tmp * SIZEOF(xkmShapeDesc);
1102*4882a593Smuzhiyun             shape = XkbAddGeomShape(geom, nameAtom, shapeWire.num_outlines);
1103*4882a593Smuzhiyun             if (!shape) {
1104*4882a593Smuzhiyun                 _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
1105*4882a593Smuzhiyun                 return nRead;
1106*4882a593Smuzhiyun             }
1107*4882a593Smuzhiyun             for (n = 0; n < shapeWire.num_outlines; n++) {
1108*4882a593Smuzhiyun                 register int p;
1109*4882a593Smuzhiyun                 xkmPointDesc ptWire;
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun                 tmp = fread(&olWire, SIZEOF(xkmOutlineDesc), 1, file);
1112*4882a593Smuzhiyun                 nRead += tmp * SIZEOF(xkmOutlineDesc);
1113*4882a593Smuzhiyun                 ol = XkbAddGeomOutline(shape, olWire.num_points);
1114*4882a593Smuzhiyun                 if (!ol) {
1115*4882a593Smuzhiyun                     _XkbLibError(_XkbErrBadAlloc, "ReadXkmGeometry", 0);
1116*4882a593Smuzhiyun                     return nRead;
1117*4882a593Smuzhiyun                 }
1118*4882a593Smuzhiyun                 ol->num_points = olWire.num_points;
1119*4882a593Smuzhiyun                 ol->corner_radius = olWire.corner_radius;
1120*4882a593Smuzhiyun                 for (p = 0; p < olWire.num_points; p++) {
1121*4882a593Smuzhiyun                     tmp = fread(&ptWire, SIZEOF(xkmPointDesc), 1, file);
1122*4882a593Smuzhiyun                     nRead += tmp * SIZEOF(xkmPointDesc);
1123*4882a593Smuzhiyun                     ol->points[p].x = ptWire.x;
1124*4882a593Smuzhiyun                     ol->points[p].y = ptWire.y;
1125*4882a593Smuzhiyun                     if (ptWire.x < shape->bounds.x1)
1126*4882a593Smuzhiyun                         shape->bounds.x1 = ptWire.x;
1127*4882a593Smuzhiyun                     if (ptWire.x > shape->bounds.x2)
1128*4882a593Smuzhiyun                         shape->bounds.x2 = ptWire.x;
1129*4882a593Smuzhiyun                     if (ptWire.y < shape->bounds.y1)
1130*4882a593Smuzhiyun                         shape->bounds.y1 = ptWire.y;
1131*4882a593Smuzhiyun                     if (ptWire.y > shape->bounds.y2)
1132*4882a593Smuzhiyun                         shape->bounds.y2 = ptWire.y;
1133*4882a593Smuzhiyun                 }
1134*4882a593Smuzhiyun             }
1135*4882a593Smuzhiyun             if (shapeWire.primary_ndx != XkbNoShape)
1136*4882a593Smuzhiyun                 shape->primary = &shape->outlines[shapeWire.primary_ndx];
1137*4882a593Smuzhiyun             if (shapeWire.approx_ndx != XkbNoShape)
1138*4882a593Smuzhiyun                 shape->approx = &shape->outlines[shapeWire.approx_ndx];
1139*4882a593Smuzhiyun         }
1140*4882a593Smuzhiyun     }
1141*4882a593Smuzhiyun     if (wireGeom.num_sections > 0) {
1142*4882a593Smuzhiyun         for (i = 0; i < wireGeom.num_sections; i++) {
1143*4882a593Smuzhiyun             tmp = ReadXkmGeomSection(file, geom);
1144*4882a593Smuzhiyun             nRead += tmp;
1145*4882a593Smuzhiyun             if (tmp == 0)
1146*4882a593Smuzhiyun                 return nRead;
1147*4882a593Smuzhiyun         }
1148*4882a593Smuzhiyun     }
1149*4882a593Smuzhiyun     if (wireGeom.num_doodads > 0) {
1150*4882a593Smuzhiyun         for (i = 0; i < wireGeom.num_doodads; i++) {
1151*4882a593Smuzhiyun             tmp = ReadXkmGeomDoodad(file, geom, NULL);
1152*4882a593Smuzhiyun             nRead += tmp;
1153*4882a593Smuzhiyun             if (tmp == 0)
1154*4882a593Smuzhiyun                 return nRead;
1155*4882a593Smuzhiyun         }
1156*4882a593Smuzhiyun     }
1157*4882a593Smuzhiyun     if ((wireGeom.num_key_aliases > 0) && (geom->key_aliases)) {
1158*4882a593Smuzhiyun         int sz = XkbKeyNameLength * 2;
1159*4882a593Smuzhiyun         int num = wireGeom.num_key_aliases;
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun         if (fread(geom->key_aliases, sz, num, file) != num) {
1162*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength, "ReadXkmGeometry", 0);
1163*4882a593Smuzhiyun             return -1;
1164*4882a593Smuzhiyun         }
1165*4882a593Smuzhiyun         nRead += (num * sz);
1166*4882a593Smuzhiyun         geom->num_key_aliases = num;
1167*4882a593Smuzhiyun     }
1168*4882a593Smuzhiyun     return nRead;
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun Bool
XkmProbe(FILE * file)1172*4882a593Smuzhiyun XkmProbe(FILE * file)
1173*4882a593Smuzhiyun {
1174*4882a593Smuzhiyun     unsigned hdr, tmp;
1175*4882a593Smuzhiyun     int nRead = 0;
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun     hdr = (('x' << 24) | ('k' << 16) | ('m' << 8) | XkmFileVersion);
1178*4882a593Smuzhiyun     tmp = XkmGetCARD32(file, &nRead);
1179*4882a593Smuzhiyun     if (tmp != hdr) {
1180*4882a593Smuzhiyun         if ((tmp & (~0xff)) == (hdr & (~0xff))) {
1181*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadFileVersion, "XkmProbe", tmp & 0xff);
1182*4882a593Smuzhiyun         }
1183*4882a593Smuzhiyun         return 0;
1184*4882a593Smuzhiyun     }
1185*4882a593Smuzhiyun     return 1;
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun static Bool
XkmReadTOC(FILE * file,xkmFileInfo * file_info,int max_toc,xkmSectionInfo * toc)1189*4882a593Smuzhiyun XkmReadTOC(FILE * file, xkmFileInfo * file_info, int max_toc,
1190*4882a593Smuzhiyun            xkmSectionInfo * toc)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun     unsigned hdr, tmp;
1193*4882a593Smuzhiyun     int nRead = 0;
1194*4882a593Smuzhiyun     unsigned i, size_toc;
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun     hdr = (('x' << 24) | ('k' << 16) | ('m' << 8) | XkmFileVersion);
1197*4882a593Smuzhiyun     tmp = XkmGetCARD32(file, &nRead);
1198*4882a593Smuzhiyun     if (tmp != hdr) {
1199*4882a593Smuzhiyun         if ((tmp & (~0xff)) == (hdr & (~0xff))) {
1200*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadFileVersion, "XkmReadTOC", tmp & 0xff);
1201*4882a593Smuzhiyun         }
1202*4882a593Smuzhiyun         else {
1203*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadFileType, "XkmReadTOC", tmp);
1204*4882a593Smuzhiyun         }
1205*4882a593Smuzhiyun         return 0;
1206*4882a593Smuzhiyun     }
1207*4882a593Smuzhiyun     if (fread(file_info, SIZEOF(xkmFileInfo), 1, file) != 1)
1208*4882a593Smuzhiyun         return 0;
1209*4882a593Smuzhiyun     size_toc = file_info->num_toc;
1210*4882a593Smuzhiyun     if (size_toc > max_toc) {
1211*4882a593Smuzhiyun         DebugF("Warning! Too many TOC entries; last %d ignored\n",
1212*4882a593Smuzhiyun                size_toc - max_toc);
1213*4882a593Smuzhiyun         size_toc = max_toc;
1214*4882a593Smuzhiyun     }
1215*4882a593Smuzhiyun     for (i = 0; i < size_toc; i++) {
1216*4882a593Smuzhiyun         if (fread(&toc[i], SIZEOF(xkmSectionInfo), 1, file) != 1)
1217*4882a593Smuzhiyun             return 0;
1218*4882a593Smuzhiyun     }
1219*4882a593Smuzhiyun     return 1;
1220*4882a593Smuzhiyun }
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun /***====================================================================***/
1223*4882a593Smuzhiyun 
1224*4882a593Smuzhiyun #define	MAX_TOC	16
1225*4882a593Smuzhiyun unsigned
XkmReadFile(FILE * file,unsigned need,unsigned want,XkbDescPtr * xkb)1226*4882a593Smuzhiyun XkmReadFile(FILE * file, unsigned need, unsigned want, XkbDescPtr *xkb)
1227*4882a593Smuzhiyun {
1228*4882a593Smuzhiyun     register unsigned i;
1229*4882a593Smuzhiyun     xkmSectionInfo toc[MAX_TOC], tmpTOC;
1230*4882a593Smuzhiyun     xkmFileInfo fileInfo;
1231*4882a593Smuzhiyun     unsigned tmp, nRead = 0;
1232*4882a593Smuzhiyun     unsigned which = need | want;
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun     if (!XkmReadTOC(file, &fileInfo, MAX_TOC, toc))
1235*4882a593Smuzhiyun         return which;
1236*4882a593Smuzhiyun     if ((fileInfo.present & need) != need) {
1237*4882a593Smuzhiyun         _XkbLibError(_XkbErrIllegalContents, "XkmReadFile",
1238*4882a593Smuzhiyun                      need & (~fileInfo.present));
1239*4882a593Smuzhiyun         return which;
1240*4882a593Smuzhiyun     }
1241*4882a593Smuzhiyun     if (*xkb == NULL)
1242*4882a593Smuzhiyun         *xkb = XkbAllocKeyboard();
1243*4882a593Smuzhiyun     for (i = 0; i < fileInfo.num_toc; i++) {
1244*4882a593Smuzhiyun         fseek(file, toc[i].offset, SEEK_SET);
1245*4882a593Smuzhiyun         tmp = fread(&tmpTOC, SIZEOF(xkmSectionInfo), 1, file);
1246*4882a593Smuzhiyun         nRead = tmp * SIZEOF(xkmSectionInfo);
1247*4882a593Smuzhiyun         if ((tmpTOC.type != toc[i].type) || (tmpTOC.format != toc[i].format) ||
1248*4882a593Smuzhiyun             (tmpTOC.size != toc[i].size) || (tmpTOC.offset != toc[i].offset)) {
1249*4882a593Smuzhiyun             return which;
1250*4882a593Smuzhiyun         }
1251*4882a593Smuzhiyun         if ((which & (1 << tmpTOC.type)) == 0) {
1252*4882a593Smuzhiyun             continue;
1253*4882a593Smuzhiyun         }
1254*4882a593Smuzhiyun         switch (tmpTOC.type) {
1255*4882a593Smuzhiyun         case XkmVirtualModsIndex:
1256*4882a593Smuzhiyun             tmp = ReadXkmVirtualMods(file, *xkb, NULL);
1257*4882a593Smuzhiyun             break;
1258*4882a593Smuzhiyun         case XkmTypesIndex:
1259*4882a593Smuzhiyun             tmp = ReadXkmKeyTypes(file, *xkb, NULL);
1260*4882a593Smuzhiyun             break;
1261*4882a593Smuzhiyun         case XkmCompatMapIndex:
1262*4882a593Smuzhiyun             tmp = ReadXkmCompatMap(file, *xkb, NULL);
1263*4882a593Smuzhiyun             break;
1264*4882a593Smuzhiyun         case XkmKeyNamesIndex:
1265*4882a593Smuzhiyun             tmp = ReadXkmKeycodes(file, *xkb, NULL);
1266*4882a593Smuzhiyun             break;
1267*4882a593Smuzhiyun         case XkmIndicatorsIndex:
1268*4882a593Smuzhiyun             tmp = ReadXkmIndicators(file, *xkb, NULL);
1269*4882a593Smuzhiyun             break;
1270*4882a593Smuzhiyun         case XkmSymbolsIndex:
1271*4882a593Smuzhiyun             tmp = ReadXkmSymbols(file, *xkb);
1272*4882a593Smuzhiyun             break;
1273*4882a593Smuzhiyun         case XkmGeometryIndex:
1274*4882a593Smuzhiyun             tmp = ReadXkmGeometry(file, *xkb);
1275*4882a593Smuzhiyun             break;
1276*4882a593Smuzhiyun         default:
1277*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadImplementation,
1278*4882a593Smuzhiyun                          XkbConfigText(tmpTOC.type, XkbMessage), 0);
1279*4882a593Smuzhiyun             tmp = 0;
1280*4882a593Smuzhiyun             break;
1281*4882a593Smuzhiyun         }
1282*4882a593Smuzhiyun         if (tmp > 0) {
1283*4882a593Smuzhiyun             nRead += tmp;
1284*4882a593Smuzhiyun             which &= ~(1 << toc[i].type);
1285*4882a593Smuzhiyun             (*xkb)->defined |= (1 << toc[i].type);
1286*4882a593Smuzhiyun         }
1287*4882a593Smuzhiyun         if (nRead != tmpTOC.size) {
1288*4882a593Smuzhiyun             _XkbLibError(_XkbErrBadLength,
1289*4882a593Smuzhiyun                          XkbConfigText(tmpTOC.type, XkbMessage),
1290*4882a593Smuzhiyun                          nRead - tmpTOC.size);
1291*4882a593Smuzhiyun         }
1292*4882a593Smuzhiyun     }
1293*4882a593Smuzhiyun     return which;
1294*4882a593Smuzhiyun }
1295