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(§ionWire, 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