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