1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3 
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15 
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 
25 ********************************************************/
26 
27 #define	NEED_MAP_READERS
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "Xlibint.h"
32 #include <X11/extensions/XKBproto.h>
33 #include "XKBlibint.h"
34 
35 static Status
_XkbReadKeyTypes(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)36 _XkbReadKeyTypes(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
37 {
38     int i, n, lastMapCount;
39     XkbKeyTypePtr type;
40 
41     if (rep->nTypes > 0) {
42         n = rep->firstType + rep->nTypes;
43         if (xkb->map->num_types >= n)
44             n = xkb->map->num_types;
45         else if (XkbAllocClientMap(xkb, XkbKeyTypesMask, n) != Success)
46             return BadAlloc;
47 
48         type = &xkb->map->types[rep->firstType];
49         for (i = 0; i < (int) rep->nTypes; i++, type++) {
50             xkbKeyTypeWireDesc *desc;
51             register int ndx;
52 
53             ndx = i + rep->firstType;
54             if (ndx >= xkb->map->num_types)
55                 xkb->map->num_types = ndx + 1;
56 
57             desc = (xkbKeyTypeWireDesc *)
58                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbKeyTypeWireDesc));
59             if (desc == NULL)
60                 return BadLength;
61 
62             lastMapCount = type->map_count;
63             if (desc->nMapEntries > 0) {
64                 if ((type->map == NULL) ||
65                     (desc->nMapEntries > type->map_count)) {
66                     _XkbResizeArray(type->map, type->map_count,
67                                   desc->nMapEntries, XkbKTMapEntryRec);
68                     if (type->map == NULL) {
69                         return BadAlloc;
70                     }
71                 }
72             }
73             else if (type->map != NULL) {
74                 Xfree(type->map);
75                 type->map_count = 0;
76                 type->map = NULL;
77             }
78 
79             if (desc->preserve && (desc->nMapEntries > 0)) {
80                 if ((!type->preserve) || (desc->nMapEntries > lastMapCount)) {
81                     _XkbResizeArray(type->preserve, lastMapCount,
82                                     desc->nMapEntries, XkbModsRec);
83                     if (type->preserve == NULL) {
84                         return BadAlloc;
85                     }
86                 }
87             }
88             else if (type->preserve != NULL) {
89                 Xfree(type->preserve);
90                 type->preserve = NULL;
91             }
92 
93             type->mods.mask = desc->mask;
94             type->mods.real_mods = desc->realMods;
95             type->mods.vmods = desc->virtualMods;
96             type->num_levels = desc->numLevels;
97             type->map_count = desc->nMapEntries;
98             if (desc->nMapEntries > 0) {
99                 register xkbKTMapEntryWireDesc *wire;
100                 register XkbKTMapEntryPtr entry;
101                 register int size;
102 
103                 size = type->map_count * SIZEOF(xkbKTMapEntryWireDesc);
104                 wire =
105                     (xkbKTMapEntryWireDesc *) _XkbGetReadBufferPtr(buf, size);
106                 if (wire == NULL)
107                     return BadLength;
108                 entry = type->map;
109                 for (n = 0; n < type->map_count; n++, wire++, entry++) {
110                     entry->active = wire->active;
111                     entry->level = wire->level;
112                     entry->mods.mask = wire->mask;
113                     entry->mods.real_mods = wire->realMods;
114                     entry->mods.vmods = wire->virtualMods;
115                 }
116 
117                 if (desc->preserve) {
118                     register xkbModsWireDesc *pwire;
119                     register XkbModsPtr preserve;
120                     register int sz;
121 
122                     sz = desc->nMapEntries * SIZEOF(xkbModsWireDesc);
123                     pwire = (xkbModsWireDesc *) _XkbGetReadBufferPtr(buf, sz);
124                     if (pwire == NULL)
125                         return BadLength;
126                     preserve = type->preserve;
127                     for (n = 0; n < desc->nMapEntries; n++, pwire++, preserve++) {
128                         preserve->mask = pwire->mask;
129                         preserve->vmods = pwire->virtualMods;
130                         preserve->real_mods = pwire->realMods;
131                     }
132                 }
133             }
134         }
135     }
136     return Success;
137 }
138 
139 static Status
_XkbReadKeySyms(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)140 _XkbReadKeySyms(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
141 {
142     register int i;
143     XkbClientMapPtr map;
144     int size = xkb->max_key_code + 1;
145 
146     if (((unsigned short) rep->firstKeySym + rep->nKeySyms) > size)
147         return BadLength;
148 
149     map = xkb->map;
150     if (map->key_sym_map == NULL) {
151         register int offset;
152         XkbSymMapPtr oldMap;
153         xkbSymMapWireDesc *newMap;
154 
155         map->key_sym_map = _XkbTypedCalloc(size, XkbSymMapRec);
156         if (map->key_sym_map == NULL)
157             return BadAlloc;
158         if (map->syms == NULL) {
159             int sz;
160 
161             sz = (rep->totalSyms * 12) / 10;
162             sz = ((sz + (unsigned) 128) / 128) * 128;
163             map->syms = _XkbTypedCalloc(sz, KeySym);
164             if (map->syms == NULL)
165                 return BadAlloc;
166             map->size_syms = sz;
167         }
168         offset = 1;
169         oldMap = &map->key_sym_map[rep->firstKeySym];
170         for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
171             newMap = (xkbSymMapWireDesc *)
172                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
173             if (newMap == NULL)
174                 return BadLength;
175             oldMap->kt_index[0] = newMap->ktIndex[0];
176             oldMap->kt_index[1] = newMap->ktIndex[1];
177             oldMap->kt_index[2] = newMap->ktIndex[2];
178             oldMap->kt_index[3] = newMap->ktIndex[3];
179             oldMap->group_info = newMap->groupInfo;
180             oldMap->width = newMap->width;
181             oldMap->offset = offset;
182             if (offset + newMap->nSyms >= map->size_syms) {
183                 register int sz;
184 
185                 sz = map->size_syms + 128;
186                 _XkbResizeArray(map->syms, map->size_syms, sz, KeySym);
187                 if (map->syms == NULL) {
188                     map->size_syms = 0;
189                     return BadAlloc;
190                 }
191                 map->size_syms = sz;
192             }
193             if (newMap->nSyms > 0) {
194                 _XkbReadBufferCopyKeySyms(buf, (KeySym *) &map->syms[offset],
195                                           newMap->nSyms);
196                 offset += newMap->nSyms;
197             }
198             else {
199                 map->syms[offset] = 0;
200             }
201         }
202         map->num_syms = offset;
203     }
204     else {
205         XkbSymMapPtr oldMap = &map->key_sym_map[rep->firstKeySym];
206 
207         for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
208             xkbSymMapWireDesc *newMap;
209             KeySym *newSyms;
210             int tmp;
211 
212             newMap = (xkbSymMapWireDesc *)
213                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
214             if (newMap == NULL)
215                 return BadLength;
216 
217             if (newMap->nSyms > 0)
218                 tmp = newMap->nSyms;
219             else
220                 tmp = 0;
221 
222             newSyms = XkbResizeKeySyms(xkb, i + rep->firstKeySym, tmp);
223             if (newSyms == NULL)
224                 return BadAlloc;
225             if (newMap->nSyms > 0)
226                 _XkbReadBufferCopyKeySyms(buf, newSyms, newMap->nSyms);
227             else
228                 newSyms[0] = NoSymbol;
229             oldMap->kt_index[0] = newMap->ktIndex[0];
230             oldMap->kt_index[1] = newMap->ktIndex[1];
231             oldMap->kt_index[2] = newMap->ktIndex[2];
232             oldMap->kt_index[3] = newMap->ktIndex[3];
233             oldMap->group_info = newMap->groupInfo;
234             oldMap->width = newMap->width;
235         }
236     }
237     return Success;
238 }
239 
240 static Status
_XkbReadKeyActions(XkbReadBufferPtr buf,XkbDescPtr info,xkbGetMapReply * rep)241 _XkbReadKeyActions(XkbReadBufferPtr buf, XkbDescPtr info, xkbGetMapReply *rep)
242 {
243     int i;
244     CARD8 numDescBuf[248];
245     CARD8 *numDesc = NULL;
246     register int nKeyActs;
247     Status ret = Success;
248 
249     if ((nKeyActs = rep->nKeyActs) > 0) {
250         XkbSymMapPtr symMap;
251 
252         if (nKeyActs < sizeof numDescBuf)
253             numDesc = numDescBuf;
254         else
255             numDesc = Xmallocarray(nKeyActs, sizeof(CARD8));
256 
257         if (!_XkbCopyFromReadBuffer(buf, (char *) numDesc, nKeyActs)) {
258             ret = BadLength;
259             goto done;
260         }
261         i = XkbPaddedSize(nKeyActs) - nKeyActs;
262         if ((i > 0) && (!_XkbSkipReadBufferData(buf, i))) {
263             ret = BadLength;
264             goto done;
265         }
266         symMap = &info->map->key_sym_map[rep->firstKeyAct];
267         for (i = 0; i < (int) rep->nKeyActs; i++, symMap++) {
268             if (numDesc[i] == 0) {
269                 if ((i + rep->firstKeyAct) > (info->max_key_code + 1)) {
270                     ret = BadLength;
271                     goto done;
272                 }
273                 info->server->key_acts[i + rep->firstKeyAct] = 0;
274             }
275             else {
276                 XkbAction *newActs;
277 
278                 /* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
279                 /*                 either zero or XkbKeyNumSyms(info,key) */
280                 newActs = XkbResizeKeyActions(info, i + rep->firstKeyAct,
281                                               numDesc[i]);
282                 if (newActs == NULL) {
283                     ret = BadAlloc;
284                     goto done;
285                 }
286                 if (!_XkbCopyFromReadBuffer(buf, (char *) newActs,
287                             (int) (numDesc[i] * sizeof(XkbAction)))) {
288                     ret = BadLength;
289                     goto done;
290                 }
291             }
292         }
293     }
294  done:
295     if (numDesc != NULL && numDesc != numDescBuf)
296         Xfree(numDesc);
297     return ret;
298 }
299 
300 static Status
_XkbReadKeyBehaviors(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)301 _XkbReadKeyBehaviors(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
302 {
303     register int i;
304 
305     if (rep->totalKeyBehaviors > 0) {
306         int size = xkb->max_key_code + 1;
307 
308         if (((int) rep->firstKeyBehavior + rep->nKeyBehaviors) > size)
309             return BadLength;
310         if (xkb->server->behaviors == NULL) {
311             xkb->server->behaviors = _XkbTypedCalloc(size, XkbBehavior);
312             if (xkb->server->behaviors == NULL)
313                 return BadAlloc;
314         }
315         else {
316             bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
317                   (rep->nKeyBehaviors * sizeof(XkbBehavior)));
318         }
319         for (i = 0; i < rep->totalKeyBehaviors; i++) {
320             xkbBehaviorWireDesc *wire;
321 
322             wire = (xkbBehaviorWireDesc *) _XkbGetReadBufferPtr(buf,
323                                                SIZEOF(xkbBehaviorWireDesc));
324             if (wire == NULL || wire->key >= size)
325                 return BadLength;
326             xkb->server->behaviors[wire->key].type = wire->type;
327             xkb->server->behaviors[wire->key].data = wire->data;
328         }
329     }
330     return Success;
331 }
332 
333 static Status
_XkbReadVirtualMods(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)334 _XkbReadVirtualMods(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
335 {
336     if (rep->virtualMods) {
337         register int i, bit, nVMods;
338         register char *data;
339 
340         for (i = nVMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
341             if (rep->virtualMods & bit)
342                 nVMods++;
343         }
344         data = _XkbGetReadBufferPtr(buf, XkbPaddedSize(nVMods));
345         if (data == NULL)
346             return BadLength;
347         for (i = 0, bit = 1; (i < XkbNumVirtualMods) && (nVMods > 0);
348              i++, bit <<= 1) {
349             if (rep->virtualMods & bit) {
350                 xkb->server->vmods[i] = *data++;
351                 nVMods--;
352             }
353         }
354     }
355     return Success;
356 }
357 
358 static Status
_XkbReadExplicitComponents(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)359 _XkbReadExplicitComponents(XkbReadBufferPtr buf,
360                            XkbDescPtr xkb,
361                            xkbGetMapReply *rep)
362 {
363     register int i;
364     unsigned char *wire;
365 
366     if (rep->totalKeyExplicit > 0) {
367         int size = xkb->max_key_code + 1;
368 
369         if (((int) rep->firstKeyExplicit + rep->nKeyExplicit) > size)
370             return BadLength;
371         if (xkb->server->explicit == NULL) {
372             xkb->server->explicit = _XkbTypedCalloc(size, unsigned char);
373 
374             if (xkb->server->explicit == NULL)
375                 return BadAlloc;
376         }
377         else {
378             bzero(&xkb->server->explicit[rep->firstKeyExplicit],
379                   rep->nKeyExplicit);
380         }
381         i = XkbPaddedSize(2 * rep->totalKeyExplicit);
382         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
383         if (!wire)
384             return BadLength;
385         for (i = 0; i < rep->totalKeyExplicit; i++, wire += 2) {
386             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
387                 return BadLength;
388             xkb->server->explicit[wire[0]] = wire[1];
389         }
390     }
391     return Success;
392 }
393 
394 static Status
_XkbReadModifierMap(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)395 _XkbReadModifierMap(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
396 {
397     register int i;
398     unsigned char *wire;
399 
400     if (rep->totalModMapKeys > 0) {
401         if (((int) rep->firstModMapKey + rep->nModMapKeys) >
402             (xkb->max_key_code + 1))
403             return BadLength;
404         if ((xkb->map->modmap == NULL) &&
405             (XkbAllocClientMap(xkb, XkbModifierMapMask, 0) != Success)) {
406             return BadAlloc;
407         }
408         else {
409             bzero(&xkb->map->modmap[rep->firstModMapKey], rep->nModMapKeys);
410         }
411         i = XkbPaddedSize(2 * rep->totalModMapKeys);
412         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
413         if (!wire)
414             return BadLength;
415         for (i = 0; i < rep->totalModMapKeys; i++, wire += 2) {
416             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
417                 return BadLength;
418             xkb->map->modmap[wire[0]] = wire[1];
419         }
420     }
421     return Success;
422 }
423 
424 static Status
_XkbReadVirtualModMap(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply * rep)425 _XkbReadVirtualModMap(XkbReadBufferPtr buf,
426                       XkbDescPtr xkb,
427                       xkbGetMapReply *rep)
428 {
429     register int i;
430     xkbVModMapWireDesc *wire;
431     XkbServerMapPtr srv;
432 
433     if (rep->totalVModMapKeys > 0) {
434         if (((int) rep->firstVModMapKey + rep->nVModMapKeys)
435             > xkb->max_key_code + 1)
436             return BadLength;
437         if (((xkb->server == NULL) || (xkb->server->vmodmap == NULL)) &&
438             (XkbAllocServerMap(xkb, XkbVirtualModMapMask, 0) != Success)) {
439             return BadAlloc;
440         }
441         else {
442             srv = xkb->server;
443             if (rep->nVModMapKeys > rep->firstVModMapKey)
444                 bzero((char *) &srv->vmodmap[rep->firstVModMapKey],
445                       (rep->nVModMapKeys - rep->firstVModMapKey) *
446                       sizeof(unsigned short));
447         }
448         srv = xkb->server;
449         i = rep->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
450         wire = (xkbVModMapWireDesc *) _XkbGetReadBufferPtr(buf, i);
451         if (!wire)
452             return BadLength;
453         for (i = 0; i < rep->totalVModMapKeys; i++, wire++) {
454             if ((wire->key >= xkb->min_key_code) &&
455                 (wire->key <= xkb->max_key_code))
456                 srv->vmodmap[wire->key] = wire->vmods;
457         }
458     }
459     return Success;
460 }
461 
462 static xkbGetMapReq *
_XkbGetGetMapReq(Display * dpy,XkbDescPtr xkb)463 _XkbGetGetMapReq(Display *dpy, XkbDescPtr xkb)
464 {
465     xkbGetMapReq *req;
466 
467     GetReq(kbGetMap, req);
468     req->reqType = dpy->xkb_info->codes->major_opcode;
469     req->xkbReqType = X_kbGetMap;
470     req->deviceSpec = xkb->device_spec;
471     req->full = req->partial = 0;
472     req->firstType = req->nTypes = 0;
473     req->firstKeySym = req->nKeySyms = 0;
474     req->firstKeyAct = req->nKeyActs = 0;
475     req->firstKeyBehavior = req->nKeyBehaviors = 0;
476     req->virtualMods = 0;
477     req->firstKeyExplicit = req->nKeyExplicit = 0;
478     req->firstModMapKey = req->nModMapKeys = 0;
479     req->firstVModMapKey = req->nVModMapKeys = 0;
480     return req;
481 }
482 
483 Status
_XkbReadGetMapReply(Display * dpy,xkbGetMapReply * rep,XkbDescPtr xkb,int * nread_rtrn)484 _XkbReadGetMapReply(Display *dpy,
485                     xkbGetMapReply *rep,
486                     XkbDescPtr xkb,
487                     int *nread_rtrn)
488 {
489     int extraData;
490     unsigned mask;
491 
492     if (xkb->device_spec == XkbUseCoreKbd)
493         xkb->device_spec = rep->deviceID;
494     if (rep->maxKeyCode < rep->minKeyCode)
495         return BadImplementation;
496     xkb->min_key_code = rep->minKeyCode;
497     xkb->max_key_code = rep->maxKeyCode;
498 
499     if (!xkb->map) {
500         mask = rep->present & XkbAllClientInfoMask;
501         if (mask && (XkbAllocClientMap(xkb, mask, rep->nTypes) != Success))
502             return BadAlloc;
503     }
504     if (!xkb->server) {
505         mask = rep->present & XkbAllServerInfoMask;
506         if (mask && (XkbAllocServerMap(xkb, mask, rep->totalActs) != Success))
507             return BadAlloc;
508     }
509     extraData = (int) (rep->length * 4);
510     extraData -= (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
511     if (rep->length) {
512         XkbReadBufferRec buf;
513         int left;
514 
515         if (_XkbInitReadBuffer(dpy, &buf, extraData)) {
516             Status status = Success;
517 
518             if (nread_rtrn != NULL)
519                 *nread_rtrn = extraData;
520             if (status == Success)
521                 status = _XkbReadKeyTypes(&buf, xkb, rep);
522             if (status == Success)
523                 status = _XkbReadKeySyms(&buf, xkb, rep);
524             if (status == Success)
525                 status = _XkbReadKeyActions(&buf, xkb, rep);
526             if (status == Success)
527                 status = _XkbReadKeyBehaviors(&buf, xkb, rep);
528             if (status == Success)
529                 status = _XkbReadVirtualMods(&buf, xkb, rep);
530             if (status == Success)
531                 status = _XkbReadExplicitComponents(&buf, xkb, rep);
532             if (status == Success)
533                 status = _XkbReadModifierMap(&buf, xkb, rep);
534             if (status == Success)
535                 status = _XkbReadVirtualModMap(&buf, xkb, rep);
536             left = _XkbFreeReadBuffer(&buf);
537             if (status != Success)
538                 return status;
539             else if (left || buf.error)
540                 return BadLength;
541         }
542         else
543             return BadAlloc;
544     }
545     return Success;
546 }
547 
548 static Status
_XkbHandleGetMapReply(Display * dpy,XkbDescPtr xkb)549 _XkbHandleGetMapReply(Display *dpy, XkbDescPtr xkb)
550 {
551     xkbGetMapReply rep;
552 
553     if (!_XReply(dpy, (xReply *) &rep,
554                  ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2),
555                  xFalse)) {
556         return BadImplementation;
557     }
558     return _XkbReadGetMapReply(dpy, &rep, xkb, NULL);
559 }
560 
561 Status
XkbGetUpdatedMap(Display * dpy,unsigned which,XkbDescPtr xkb)562 XkbGetUpdatedMap(Display *dpy, unsigned which, XkbDescPtr xkb)
563 {
564     if ((dpy->flags & XlibDisplayNoXkb) ||
565         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
566         return BadAccess;
567     if (which) {
568         register xkbGetMapReq *req;
569         Status status;
570 
571         LockDisplay(dpy);
572 
573         req = _XkbGetGetMapReq(dpy, xkb);
574         req->full = which;
575         status = _XkbHandleGetMapReply(dpy, xkb);
576 
577         UnlockDisplay(dpy);
578         SyncHandle();
579         return status;
580     }
581     return Success;
582 }
583 
584 XkbDescPtr
XkbGetMap(Display * dpy,unsigned which,unsigned deviceSpec)585 XkbGetMap(Display *dpy, unsigned which, unsigned deviceSpec)
586 {
587     XkbDescPtr xkb;
588 
589     xkb = _XkbTypedCalloc(1, XkbDescRec);
590     if (xkb) {
591         xkb->device_spec = deviceSpec;
592         xkb->map = _XkbTypedCalloc(1, XkbClientMapRec);
593         if ((xkb->map == NULL) ||
594             ((which) && (XkbGetUpdatedMap(dpy, which, xkb) != Success))) {
595             if (xkb->map) {
596                 Xfree(xkb->map);
597                 xkb->map = NULL;
598             }
599             Xfree(xkb);
600             return NULL;
601         }
602         xkb->dpy = dpy;
603     }
604     return xkb;
605 }
606 
607 Status
XkbGetKeyTypes(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)608 XkbGetKeyTypes(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
609 {
610     register xkbGetMapReq *req;
611     Status status;
612 
613     if ((dpy->flags & XlibDisplayNoXkb) ||
614         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
615         return BadAccess;
616     if ((num < 1) || (num > XkbMaxKeyTypes))
617         return BadValue;
618 
619     LockDisplay(dpy);
620 
621     req = _XkbGetGetMapReq(dpy, xkb);
622     req->firstType = first;
623     req->nTypes = num;
624     status = _XkbHandleGetMapReply(dpy, xkb);
625 
626     UnlockDisplay(dpy);
627     SyncHandle();
628     return status;
629 }
630 
631 Status
XkbGetKeyActions(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)632 XkbGetKeyActions(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
633 {
634     register xkbGetMapReq *req;
635     Status status;
636 
637     if ((dpy->flags & XlibDisplayNoXkb) ||
638         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
639         return BadAccess;
640 
641     if ((num < 1) || (num > XkbMaxKeyCount))
642         return BadValue;
643 
644     LockDisplay(dpy);
645 
646     req = _XkbGetGetMapReq(dpy, xkb);
647     req->firstKeyAct = first;
648     req->nKeyActs = num;
649     status = _XkbHandleGetMapReply(dpy, xkb);
650 
651     UnlockDisplay(dpy);
652     SyncHandle();
653     return status;
654 }
655 
656 Status
XkbGetKeySyms(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)657 XkbGetKeySyms(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
658 {
659     register xkbGetMapReq *req;
660     Status status;
661 
662     if ((dpy->flags & XlibDisplayNoXkb) ||
663         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
664         return BadAccess;
665 
666     if ((num < 1) || (num > XkbMaxKeyCount))
667         return BadValue;
668 
669     LockDisplay(dpy);
670 
671     req = _XkbGetGetMapReq(dpy, xkb);
672     req->firstKeySym = first;
673     req->nKeySyms = num;
674     status = _XkbHandleGetMapReply(dpy, xkb);
675 
676     UnlockDisplay(dpy);
677     SyncHandle();
678 
679     return status;
680 }
681 
682 Status
XkbGetKeyBehaviors(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)683 XkbGetKeyBehaviors(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
684 {
685     register xkbGetMapReq *req;
686     Status status;
687 
688     if ((dpy->flags & XlibDisplayNoXkb) ||
689         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
690         return BadAccess;
691 
692     if ((num < 1) || (num > XkbMaxKeyCount))
693         return BadValue;
694 
695     LockDisplay(dpy);
696 
697     req = _XkbGetGetMapReq(dpy, xkb);
698     req->firstKeyBehavior = first;
699     req->nKeyBehaviors = num;
700     status = _XkbHandleGetMapReply(dpy, xkb);
701 
702     UnlockDisplay(dpy);
703     SyncHandle();
704     return status;
705 }
706 
707 Status
XkbGetVirtualMods(Display * dpy,unsigned which,XkbDescPtr xkb)708 XkbGetVirtualMods(Display *dpy, unsigned which, XkbDescPtr xkb)
709 {
710     register xkbGetMapReq *req;
711     Status status;
712 
713     if ((dpy->flags & XlibDisplayNoXkb) ||
714         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
715         return BadAccess;
716 
717     LockDisplay(dpy);
718 
719     req = _XkbGetGetMapReq(dpy, xkb);
720     req->virtualMods = which;
721     status = _XkbHandleGetMapReply(dpy, xkb);
722 
723     UnlockDisplay(dpy);
724     SyncHandle();
725     return status;
726 }
727 
728 Status
XkbGetKeyExplicitComponents(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)729 XkbGetKeyExplicitComponents(Display *dpy,
730                             unsigned first,
731                             unsigned num,
732                             XkbDescPtr xkb)
733 {
734     register xkbGetMapReq *req;
735     Status status;
736 
737     if ((dpy->flags & XlibDisplayNoXkb) ||
738         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
739         return BadAccess;
740 
741     if ((num < 1) || (num > XkbMaxKeyCount))
742         return BadValue;
743 
744     LockDisplay(dpy);
745 
746     req = _XkbGetGetMapReq(dpy, xkb);
747     req->firstKeyExplicit = first;
748     req->nKeyExplicit = num;
749     if ((xkb != NULL) && (xkb->server != NULL) &&
750         (xkb->server->explicit != NULL)) {
751         if ((num > 0) && (first >= xkb->min_key_code) &&
752             (first + num <= xkb->max_key_code))
753             bzero(&xkb->server->explicit[first], num);
754     }
755     if (xkb)
756         status = _XkbHandleGetMapReply(dpy, xkb);
757     else
758         status = BadMatch;
759 
760     UnlockDisplay(dpy);
761     SyncHandle();
762     return status;
763 }
764 
765 Status
XkbGetKeyModifierMap(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)766 XkbGetKeyModifierMap(Display *dpy,
767                      unsigned first,
768                      unsigned num,
769                      XkbDescPtr xkb)
770 {
771     register xkbGetMapReq *req;
772     Status status;
773 
774     if ((dpy->flags & XlibDisplayNoXkb) ||
775         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
776         return BadAccess;
777 
778     if ((num < 1) || (num > XkbMaxKeyCount))
779         return BadValue;
780 
781     LockDisplay(dpy);
782 
783     req = _XkbGetGetMapReq(dpy, xkb);
784     req->firstModMapKey = first;
785     req->nModMapKeys = num;
786     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
787         if ((num > 0) && (first >= xkb->min_key_code) &&
788             (first + num <= xkb->max_key_code))
789             bzero(&xkb->map->modmap[first], num);
790     }
791     if (xkb)
792         status = _XkbHandleGetMapReply(dpy, xkb);
793     else
794         status = BadMatch;
795 
796     UnlockDisplay(dpy);
797     SyncHandle();
798     return status;
799 }
800 
801 Status
XkbGetKeyVirtualModMap(Display * dpy,unsigned first,unsigned num,XkbDescPtr xkb)802 XkbGetKeyVirtualModMap(Display *dpy, unsigned first, unsigned num,
803                        XkbDescPtr xkb)
804 {
805     register xkbGetMapReq *req;
806     Status status;
807 
808     if ((dpy->flags & XlibDisplayNoXkb) ||
809         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
810         return BadAccess;
811 
812     if ((num < 1) || (num > XkbMaxKeyCount))
813         return BadValue;
814 
815     LockDisplay(dpy);
816 
817     req = _XkbGetGetMapReq(dpy, xkb);
818     req->firstVModMapKey = first;
819     req->nVModMapKeys = num;
820     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
821         if ((num > 0) && (first >= xkb->min_key_code) &&
822             (first + num <= xkb->max_key_code))
823             bzero(&xkb->server->vmodmap[first], num * sizeof(unsigned short));
824     }
825 
826     if (xkb)
827         status = _XkbHandleGetMapReply(dpy, xkb);
828     else
829         status = BadMatch;
830 
831     UnlockDisplay(dpy);
832     SyncHandle();
833     return status;
834 }
835 
836 Status
XkbGetMapChanges(Display * dpy,XkbDescPtr xkb,XkbMapChangesPtr changes)837 XkbGetMapChanges(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
838 {
839     xkbGetMapReq *req;
840 
841     if ((dpy->flags & XlibDisplayNoXkb) ||
842         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
843         return BadAccess;
844     LockDisplay(dpy);
845     if (changes->changed) {
846         Status status = Success;
847 
848         req = _XkbGetGetMapReq(dpy, xkb);
849         req->full = 0;
850         req->partial = changes->changed;
851         req->firstType = changes->first_type;
852         req->nTypes = changes->num_types;
853         req->firstKeySym = changes->first_key_sym;
854         req->nKeySyms = changes->num_key_syms;
855         req->firstKeyAct = changes->first_key_act;
856         req->nKeyActs = changes->num_key_acts;
857         req->firstKeyBehavior = changes->first_key_behavior;
858         req->nKeyBehaviors = changes->num_key_behaviors;
859         req->virtualMods = changes->vmods;
860         req->firstKeyExplicit = changes->first_key_explicit;
861         req->nKeyExplicit = changes->num_key_explicit;
862         req->firstModMapKey = changes->first_modmap_key;
863         req->nModMapKeys = changes->num_modmap_keys;
864         req->firstVModMapKey = changes->first_vmodmap_key;
865         req->nVModMapKeys = changes->num_vmodmap_keys;
866         status = _XkbHandleGetMapReply(dpy, xkb);
867         UnlockDisplay(dpy);
868         SyncHandle();
869         return status;
870     }
871     UnlockDisplay(dpy);
872     return Success;
873 }
874