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