XKBGetMap.c revision 818534a1
11ab64890Smrg/************************************************************
21ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
31ab64890Smrg
41ab64890SmrgPermission to use, copy, modify, and distribute this
51ab64890Smrgsoftware and its documentation for any purpose and without
61ab64890Smrgfee is hereby granted, provided that the above copyright
71ab64890Smrgnotice appear in all copies and that both that copyright
81ab64890Smrgnotice and this permission notice appear in supporting
961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1061b2299dSmrgused in advertising or publicity pertaining to distribution
111ab64890Smrgof the software without specific prior written permission.
1261b2299dSmrgSilicon Graphics makes no representation about the suitability
131ab64890Smrgof this software for any purpose. It is provided "as is"
141ab64890Smrgwithout any express or implied warranty.
151ab64890Smrg
1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241ab64890Smrg
251ab64890Smrg********************************************************/
261ab64890Smrg
271ab64890Smrg#define	NEED_MAP_READERS
281ab64890Smrg#ifdef HAVE_CONFIG_H
291ab64890Smrg#include <config.h>
301ab64890Smrg#endif
311ab64890Smrg#include "Xlibint.h"
321ab64890Smrg#include <X11/extensions/XKBproto.h>
331ab64890Smrg#include "XKBlibint.h"
341ab64890Smrg
351ab64890Smrgstatic Status
36818534a1Smrg_XkbReadKeyTypes(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
371ab64890Smrg{
38818534a1Smrg    int i, n, lastMapCount;
39818534a1Smrg    XkbKeyTypePtr type;
40818534a1Smrg
41818534a1Smrg    if (rep->nTypes > 0) {
42818534a1Smrg        n = rep->firstType + rep->nTypes;
43818534a1Smrg        if (xkb->map->num_types >= n)
44818534a1Smrg            n = xkb->map->num_types;
45818534a1Smrg        else if (XkbAllocClientMap(xkb, XkbKeyTypesMask, n) != Success)
46818534a1Smrg            return BadAlloc;
47818534a1Smrg
48818534a1Smrg        type = &xkb->map->types[rep->firstType];
49818534a1Smrg        for (i = 0; i < (int) rep->nTypes; i++, type++) {
50818534a1Smrg            xkbKeyTypeWireDesc *desc;
51818534a1Smrg            register int ndx;
52818534a1Smrg
53818534a1Smrg            ndx = i + rep->firstType;
54818534a1Smrg            if (ndx >= xkb->map->num_types)
55818534a1Smrg                xkb->map->num_types = ndx + 1;
56818534a1Smrg
57818534a1Smrg            desc = (xkbKeyTypeWireDesc *)
58818534a1Smrg                _XkbGetReadBufferPtr(buf, SIZEOF(xkbKeyTypeWireDesc));
59818534a1Smrg            if (desc == NULL)
60818534a1Smrg                return BadLength;
61818534a1Smrg
62818534a1Smrg            lastMapCount = type->map_count;
63818534a1Smrg            if (desc->nMapEntries > 0) {
64818534a1Smrg                if ((type->map == NULL) ||
65818534a1Smrg                    (desc->nMapEntries > type->map_count)) {
66818534a1Smrg                    XkbKTMapEntryRec *prev_map = type->map;
67818534a1Smrg
68818534a1Smrg                    type->map = _XkbTypedRealloc(type->map, desc->nMapEntries,
69818534a1Smrg                                                 XkbKTMapEntryRec);
70818534a1Smrg                    if (type->map == NULL) {
71818534a1Smrg                        _XkbFree(prev_map);
72818534a1Smrg                        return BadAlloc;
73818534a1Smrg                    }
74818534a1Smrg                }
75818534a1Smrg            }
76818534a1Smrg            else if (type->map != NULL) {
77818534a1Smrg                Xfree(type->map);
78818534a1Smrg                type->map_count = 0;
79818534a1Smrg                type->map = NULL;
80818534a1Smrg            }
81818534a1Smrg
82818534a1Smrg            if (desc->preserve && (desc->nMapEntries > 0)) {
83818534a1Smrg                if ((!type->preserve) || (desc->nMapEntries > lastMapCount)) {
84818534a1Smrg                    XkbModsRec *prev_preserve = type->preserve;
85818534a1Smrg
86818534a1Smrg                    type->preserve = _XkbTypedRealloc(type->preserve,
87818534a1Smrg                                                      desc->nMapEntries,
88818534a1Smrg                                                      XkbModsRec);
89818534a1Smrg                    if (type->preserve == NULL) {
90818534a1Smrg                        _XkbFree(prev_preserve);
91818534a1Smrg                        return BadAlloc;
92818534a1Smrg                    }
93818534a1Smrg                }
94818534a1Smrg            }
95818534a1Smrg            else if (type->preserve != NULL) {
96818534a1Smrg                Xfree(type->preserve);
97818534a1Smrg                type->preserve = NULL;
98818534a1Smrg            }
99818534a1Smrg
100818534a1Smrg            type->mods.mask = desc->mask;
101818534a1Smrg            type->mods.real_mods = desc->realMods;
102818534a1Smrg            type->mods.vmods = desc->virtualMods;
103818534a1Smrg            type->num_levels = desc->numLevels;
104818534a1Smrg            type->map_count = desc->nMapEntries;
105818534a1Smrg            if (desc->nMapEntries > 0) {
106818534a1Smrg                register xkbKTMapEntryWireDesc *wire;
107818534a1Smrg                register XkbKTMapEntryPtr entry;
108818534a1Smrg                register int size;
109818534a1Smrg
110818534a1Smrg                size = type->map_count * SIZEOF(xkbKTMapEntryWireDesc);
111818534a1Smrg                wire =
112818534a1Smrg                    (xkbKTMapEntryWireDesc *) _XkbGetReadBufferPtr(buf, size);
113818534a1Smrg                if (wire == NULL)
114818534a1Smrg                    return BadLength;
115818534a1Smrg                entry = type->map;
116818534a1Smrg                for (n = 0; n < type->map_count; n++, wire++, entry++) {
117818534a1Smrg                    entry->active = wire->active;
118818534a1Smrg                    entry->level = wire->level;
119818534a1Smrg                    entry->mods.mask = wire->mask;
120818534a1Smrg                    entry->mods.real_mods = wire->realMods;
121818534a1Smrg                    entry->mods.vmods = wire->virtualMods;
122818534a1Smrg                }
123818534a1Smrg
124818534a1Smrg                if (desc->preserve) {
125818534a1Smrg                    register xkbModsWireDesc *pwire;
126818534a1Smrg                    register XkbModsPtr preserve;
127818534a1Smrg                    register int sz;
128818534a1Smrg
129818534a1Smrg                    sz = desc->nMapEntries * SIZEOF(xkbModsWireDesc);
130818534a1Smrg                    pwire = (xkbModsWireDesc *) _XkbGetReadBufferPtr(buf, sz);
131818534a1Smrg                    if (pwire == NULL)
132818534a1Smrg                        return BadLength;
133818534a1Smrg                    preserve = type->preserve;
134818534a1Smrg                    for (n = 0; n < desc->nMapEntries; n++, pwire++, preserve++) {
135818534a1Smrg                        preserve->mask = pwire->mask;
136818534a1Smrg                        preserve->vmods = pwire->virtualMods;
137818534a1Smrg                        preserve->real_mods = pwire->realMods;
138818534a1Smrg                    }
139818534a1Smrg                }
140818534a1Smrg            }
141818534a1Smrg        }
1421ab64890Smrg    }
1431ab64890Smrg    return Success;
1441ab64890Smrg}
1451ab64890Smrg
1461ab64890Smrgstatic Status
147818534a1Smrg_XkbReadKeySyms(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
1481ab64890Smrg{
149818534a1Smrg    register int i;
150818534a1Smrg    XkbClientMapPtr map;
151818534a1Smrg    int size = xkb->max_key_code + 1;
152818534a1Smrg
153818534a1Smrg    if (((unsigned short) rep->firstKeySym + rep->nKeySyms) > size)
154818534a1Smrg        return BadLength;
155818534a1Smrg
156818534a1Smrg    map = xkb->map;
157818534a1Smrg    if (map->key_sym_map == NULL) {
158818534a1Smrg        register int offset;
159818534a1Smrg        XkbSymMapPtr oldMap;
160818534a1Smrg        xkbSymMapWireDesc *newMap;
161818534a1Smrg
162818534a1Smrg        map->key_sym_map = _XkbTypedCalloc(size, XkbSymMapRec);
163818534a1Smrg        if (map->key_sym_map == NULL)
164818534a1Smrg            return BadAlloc;
165818534a1Smrg        if (map->syms == NULL) {
166818534a1Smrg            int sz;
167818534a1Smrg
168818534a1Smrg            sz = (rep->totalSyms * 12) / 10;
169818534a1Smrg            sz = ((sz + (unsigned) 128) / 128) * 128;
170818534a1Smrg            map->syms = _XkbTypedCalloc(sz, KeySym);
171818534a1Smrg            if (map->syms == NULL)
172818534a1Smrg                return BadAlloc;
173818534a1Smrg            map->size_syms = sz;
174818534a1Smrg        }
175818534a1Smrg        offset = 1;
176818534a1Smrg        oldMap = &map->key_sym_map[rep->firstKeySym];
177818534a1Smrg        for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
178818534a1Smrg            newMap = (xkbSymMapWireDesc *)
179818534a1Smrg                _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
180818534a1Smrg            if (newMap == NULL)
181818534a1Smrg                return BadLength;
182818534a1Smrg            oldMap->kt_index[0] = newMap->ktIndex[0];
183818534a1Smrg            oldMap->kt_index[1] = newMap->ktIndex[1];
184818534a1Smrg            oldMap->kt_index[2] = newMap->ktIndex[2];
185818534a1Smrg            oldMap->kt_index[3] = newMap->ktIndex[3];
186818534a1Smrg            oldMap->group_info = newMap->groupInfo;
187818534a1Smrg            oldMap->width = newMap->width;
188818534a1Smrg            oldMap->offset = offset;
189818534a1Smrg            if (offset + newMap->nSyms >= map->size_syms) {
190818534a1Smrg                register int sz;
191818534a1Smrg                KeySym *prev_syms = map->syms;
192818534a1Smrg
193818534a1Smrg                sz = map->size_syms + 128;
194818534a1Smrg                map->syms = _XkbTypedRealloc(map->syms, sz, KeySym);
195818534a1Smrg                if (map->syms == NULL) {
196818534a1Smrg                    _XkbFree(prev_syms);
197818534a1Smrg                    map->size_syms = 0;
198818534a1Smrg                    return BadAlloc;
199818534a1Smrg                }
200818534a1Smrg                map->size_syms = sz;
201818534a1Smrg            }
202818534a1Smrg            if (newMap->nSyms > 0) {
203818534a1Smrg                _XkbReadBufferCopyKeySyms(buf, (KeySym *) &map->syms[offset],
204818534a1Smrg                                          newMap->nSyms);
205818534a1Smrg                offset += newMap->nSyms;
206818534a1Smrg            }
207818534a1Smrg            else {
208818534a1Smrg                map->syms[offset] = 0;
209818534a1Smrg            }
210818534a1Smrg        }
211818534a1Smrg        map->num_syms = offset;
2121ab64890Smrg    }
2131ab64890Smrg    else {
214818534a1Smrg        XkbSymMapPtr oldMap = &map->key_sym_map[rep->firstKeySym];
215818534a1Smrg
216818534a1Smrg        for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
217818534a1Smrg            xkbSymMapWireDesc *newMap;
218818534a1Smrg            KeySym *newSyms;
219818534a1Smrg            int tmp;
220818534a1Smrg
221818534a1Smrg            newMap = (xkbSymMapWireDesc *)
222818534a1Smrg                _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
223818534a1Smrg            if (newMap == NULL)
224818534a1Smrg                return BadLength;
225818534a1Smrg
226818534a1Smrg            if (newMap->nSyms > 0)
227818534a1Smrg                tmp = newMap->nSyms;
228818534a1Smrg            else
229818534a1Smrg                tmp = 0;
230818534a1Smrg
231818534a1Smrg            newSyms = XkbResizeKeySyms(xkb, i + rep->firstKeySym, tmp);
232818534a1Smrg            if (newSyms == NULL)
233818534a1Smrg                return BadAlloc;
234818534a1Smrg            if (newMap->nSyms > 0)
235818534a1Smrg                _XkbReadBufferCopyKeySyms(buf, newSyms, newMap->nSyms);
236818534a1Smrg            else
237818534a1Smrg                newSyms[0] = NoSymbol;
238818534a1Smrg            oldMap->kt_index[0] = newMap->ktIndex[0];
239818534a1Smrg            oldMap->kt_index[1] = newMap->ktIndex[1];
240818534a1Smrg            oldMap->kt_index[2] = newMap->ktIndex[2];
241818534a1Smrg            oldMap->kt_index[3] = newMap->ktIndex[3];
242818534a1Smrg            oldMap->group_info = newMap->groupInfo;
243818534a1Smrg            oldMap->width = newMap->width;
244818534a1Smrg        }
2451ab64890Smrg    }
2461ab64890Smrg    return Success;
2471ab64890Smrg}
2481ab64890Smrg
2491ab64890Smrgstatic Status
250818534a1Smrg_XkbReadKeyActions(XkbReadBufferPtr buf, XkbDescPtr info, xkbGetMapReply *rep)
2511ab64890Smrg{
252818534a1Smrg    int i;
253818534a1Smrg    CARD8 numDescBuf[248];
254818534a1Smrg    CARD8 *numDesc = NULL;
255818534a1Smrg    register int nKeyActs;
256818534a1Smrg    Status ret = Success;
257818534a1Smrg
258818534a1Smrg    if ((nKeyActs = rep->nKeyActs) > 0) {
259818534a1Smrg        XkbSymMapPtr symMap;
260818534a1Smrg
261818534a1Smrg        if (nKeyActs < sizeof numDescBuf)
262818534a1Smrg            numDesc = numDescBuf;
263818534a1Smrg        else
264818534a1Smrg            numDesc = Xmalloc(nKeyActs * sizeof(CARD8));
265818534a1Smrg
266818534a1Smrg        if (!_XkbCopyFromReadBuffer(buf, (char *) numDesc, nKeyActs)) {
267818534a1Smrg            ret = BadLength;
268818534a1Smrg            goto done;
269818534a1Smrg        }
270818534a1Smrg        i = XkbPaddedSize(nKeyActs) - nKeyActs;
271818534a1Smrg        if ((i > 0) && (!_XkbSkipReadBufferData(buf, i))) {
272818534a1Smrg            ret = BadLength;
273818534a1Smrg            goto done;
274818534a1Smrg        }
275818534a1Smrg        symMap = &info->map->key_sym_map[rep->firstKeyAct];
276818534a1Smrg        for (i = 0; i < (int) rep->nKeyActs; i++, symMap++) {
277818534a1Smrg            if (numDesc[i] == 0) {
278818534a1Smrg                if ((i + rep->firstKeyAct) > (info->max_key_code + 1)) {
279818534a1Smrg                    ret = BadLength;
280818534a1Smrg                    goto done;
281818534a1Smrg                }
282818534a1Smrg                info->server->key_acts[i + rep->firstKeyAct] = 0;
283818534a1Smrg            }
284818534a1Smrg            else {
285818534a1Smrg                XkbAction *newActs;
286818534a1Smrg
287818534a1Smrg                /* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
288818534a1Smrg                /*                 either zero or XkbKeyNumSyms(info,key) */
289818534a1Smrg                newActs = XkbResizeKeyActions(info, i + rep->firstKeyAct,
290818534a1Smrg                                              numDesc[i]);
291818534a1Smrg                if (newActs == NULL) {
292818534a1Smrg                    ret = BadAlloc;
293818534a1Smrg                    goto done;
294818534a1Smrg                }
295818534a1Smrg                if (!_XkbCopyFromReadBuffer(buf, (char *) newActs,
296818534a1Smrg                            (int) (numDesc[i] * sizeof(XkbAction)))) {
297818534a1Smrg                    ret = BadLength;
298818534a1Smrg                    goto done;
299818534a1Smrg                }
300818534a1Smrg            }
301818534a1Smrg        }
3021ab64890Smrg    }
303818534a1Smrg done:
304818534a1Smrg    if (numDesc != NULL && numDesc != numDescBuf)
305818534a1Smrg        Xfree(numDesc);
3061ab64890Smrg    return ret;
3071ab64890Smrg}
3081ab64890Smrg
3091ab64890Smrgstatic Status
310818534a1Smrg_XkbReadKeyBehaviors(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
3111ab64890Smrg{
312818534a1Smrg    register int i;
313818534a1Smrg
314818534a1Smrg    if (rep->totalKeyBehaviors > 0) {
315818534a1Smrg        int size = xkb->max_key_code + 1;
316818534a1Smrg
317818534a1Smrg        if (((int) rep->firstKeyBehavior + rep->nKeyBehaviors) > size)
318818534a1Smrg            return BadLength;
319818534a1Smrg        if (xkb->server->behaviors == NULL) {
320818534a1Smrg            xkb->server->behaviors = _XkbTypedCalloc(size, XkbBehavior);
321818534a1Smrg            if (xkb->server->behaviors == NULL)
322818534a1Smrg                return BadAlloc;
323818534a1Smrg        }
324818534a1Smrg        else {
325818534a1Smrg            bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
326818534a1Smrg                  (rep->nKeyBehaviors * sizeof(XkbBehavior)));
327818534a1Smrg        }
328818534a1Smrg        for (i = 0; i < rep->totalKeyBehaviors; i++) {
329818534a1Smrg            xkbBehaviorWireDesc *wire;
330818534a1Smrg
331818534a1Smrg            wire = (xkbBehaviorWireDesc *) _XkbGetReadBufferPtr(buf,
332818534a1Smrg                                               SIZEOF(xkbBehaviorWireDesc));
333818534a1Smrg            if (wire == NULL || wire->key >= size)
334818534a1Smrg                return BadLength;
335818534a1Smrg            xkb->server->behaviors[wire->key].type = wire->type;
336818534a1Smrg            xkb->server->behaviors[wire->key].data = wire->data;
337818534a1Smrg        }
3381ab64890Smrg    }
3391ab64890Smrg    return Success;
3401ab64890Smrg}
3411ab64890Smrg
3421ab64890Smrgstatic Status
343818534a1Smrg_XkbReadVirtualMods(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
3441ab64890Smrg{
345818534a1Smrg    if (rep->virtualMods) {
346818534a1Smrg        register int i, bit, nVMods;
347818534a1Smrg        register char *data;
348818534a1Smrg
349818534a1Smrg        for (i = nVMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
350818534a1Smrg            if (rep->virtualMods & bit)
351818534a1Smrg                nVMods++;
352818534a1Smrg        }
353818534a1Smrg        data = _XkbGetReadBufferPtr(buf, XkbPaddedSize(nVMods));
354818534a1Smrg        if (data == NULL)
355818534a1Smrg            return BadLength;
356818534a1Smrg        for (i = 0, bit = 1; (i < XkbNumVirtualMods) && (nVMods > 0);
357818534a1Smrg             i++, bit <<= 1) {
358818534a1Smrg            if (rep->virtualMods & bit) {
359818534a1Smrg                xkb->server->vmods[i] = *data++;
360818534a1Smrg                nVMods--;
361818534a1Smrg            }
362818534a1Smrg        }
3631ab64890Smrg    }
3641ab64890Smrg    return Success;
3651ab64890Smrg}
3661ab64890Smrg
3671ab64890Smrgstatic Status
368818534a1Smrg_XkbReadExplicitComponents(XkbReadBufferPtr buf,
369818534a1Smrg                           XkbDescPtr xkb,
370818534a1Smrg                           xkbGetMapReply *rep)
3711ab64890Smrg{
372818534a1Smrg    register int i;
373818534a1Smrg    unsigned char *wire;
374818534a1Smrg
375818534a1Smrg    if (rep->totalKeyExplicit > 0) {
376818534a1Smrg        int size = xkb->max_key_code + 1;
377818534a1Smrg
378818534a1Smrg        if (((int) rep->firstKeyExplicit + rep->nKeyExplicit) > size)
379818534a1Smrg            return BadLength;
380818534a1Smrg        if (xkb->server->explicit == NULL) {
381818534a1Smrg            xkb->server->explicit = _XkbTypedCalloc(size, unsigned char);
382818534a1Smrg
383818534a1Smrg            if (xkb->server->explicit == NULL)
384818534a1Smrg                return BadAlloc;
385818534a1Smrg        }
386818534a1Smrg        else {
387818534a1Smrg            bzero(&xkb->server->explicit[rep->firstKeyExplicit],
388818534a1Smrg                  rep->nKeyExplicit);
389818534a1Smrg        }
390818534a1Smrg        i = XkbPaddedSize(2 * rep->totalKeyExplicit);
391818534a1Smrg        wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
392818534a1Smrg        if (!wire)
393818534a1Smrg            return BadLength;
394818534a1Smrg        for (i = 0; i < rep->totalKeyExplicit; i++, wire += 2) {
395818534a1Smrg            if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
396818534a1Smrg                return BadLength;
397818534a1Smrg            xkb->server->explicit[wire[0]] = wire[1];
398818534a1Smrg        }
3991ab64890Smrg    }
4001ab64890Smrg    return Success;
4011ab64890Smrg}
4021ab64890Smrg
4031ab64890Smrgstatic Status
404818534a1Smrg_XkbReadModifierMap(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
4051ab64890Smrg{
406818534a1Smrg    register int i;
407818534a1Smrg    unsigned char *wire;
408818534a1Smrg
409818534a1Smrg    if (rep->totalModMapKeys > 0) {
410818534a1Smrg        if (((int) rep->firstModMapKey + rep->nModMapKeys) >
411818534a1Smrg            (xkb->max_key_code + 1))
412818534a1Smrg            return BadLength;
413818534a1Smrg        if ((xkb->map->modmap == NULL) &&
414818534a1Smrg            (XkbAllocClientMap(xkb, XkbModifierMapMask, 0) != Success)) {
415818534a1Smrg            return BadAlloc;
416818534a1Smrg        }
417818534a1Smrg        else {
418818534a1Smrg            bzero(&xkb->map->modmap[rep->firstModMapKey], rep->nModMapKeys);
419818534a1Smrg        }
420818534a1Smrg        i = XkbPaddedSize(2 * rep->totalModMapKeys);
421818534a1Smrg        wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
422818534a1Smrg        if (!wire)
423818534a1Smrg            return BadLength;
424818534a1Smrg        for (i = 0; i < rep->totalModMapKeys; i++, wire += 2) {
425818534a1Smrg            if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
426818534a1Smrg                return BadLength;
427818534a1Smrg            xkb->map->modmap[wire[0]] = wire[1];
428818534a1Smrg        }
4291ab64890Smrg    }
4301ab64890Smrg    return Success;
4311ab64890Smrg}
4321ab64890Smrg
4331ab64890Smrgstatic Status
434818534a1Smrg_XkbReadVirtualModMap(XkbReadBufferPtr buf,
435818534a1Smrg                      XkbDescPtr xkb,
436818534a1Smrg                      xkbGetMapReply *rep)
4371ab64890Smrg{
438818534a1Smrg    register int i;
439818534a1Smrg    xkbVModMapWireDesc *wire;
440818534a1Smrg    XkbServerMapPtr srv;
441818534a1Smrg
442818534a1Smrg    if (rep->totalVModMapKeys > 0) {
443818534a1Smrg        if (((int) rep->firstVModMapKey + rep->nVModMapKeys)
444818534a1Smrg            > xkb->max_key_code + 1)
445818534a1Smrg            return BadLength;
446818534a1Smrg        if (((xkb->server == NULL) || (xkb->server->vmodmap == NULL)) &&
447818534a1Smrg            (XkbAllocServerMap(xkb, XkbVirtualModMapMask, 0) != Success)) {
448818534a1Smrg            return BadAlloc;
449818534a1Smrg        }
450818534a1Smrg        else {
451818534a1Smrg            srv = xkb->server;
452818534a1Smrg            if (rep->nVModMapKeys > rep->firstVModMapKey)
453818534a1Smrg                bzero((char *) &srv->vmodmap[rep->firstVModMapKey],
454818534a1Smrg                      (rep->nVModMapKeys - rep->firstVModMapKey) *
455818534a1Smrg                      sizeof(unsigned short));
456818534a1Smrg        }
457818534a1Smrg        srv = xkb->server;
458818534a1Smrg        i = rep->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
459818534a1Smrg        wire = (xkbVModMapWireDesc *) _XkbGetReadBufferPtr(buf, i);
460818534a1Smrg        if (!wire)
461818534a1Smrg            return BadLength;
462818534a1Smrg        for (i = 0; i < rep->totalVModMapKeys; i++, wire++) {
463818534a1Smrg            if ((wire->key >= xkb->min_key_code) &&
464818534a1Smrg                (wire->key <= xkb->max_key_code))
465818534a1Smrg                srv->vmodmap[wire->key] = wire->vmods;
466818534a1Smrg        }
4671ab64890Smrg    }
4681ab64890Smrg    return Success;
4691ab64890Smrg}
4701ab64890Smrg
4711ab64890Smrgstatic xkbGetMapReq *
472818534a1Smrg_XkbGetGetMapReq(Display *dpy, XkbDescPtr xkb)
4731ab64890Smrg{
474818534a1Smrg    xkbGetMapReq *req;
4751ab64890Smrg
4761ab64890Smrg    GetReq(kbGetMap, req);
4771ab64890Smrg    req->reqType = dpy->xkb_info->codes->major_opcode;
4781ab64890Smrg    req->xkbReqType = X_kbGetMap;
4791ab64890Smrg    req->deviceSpec = xkb->device_spec;
4801ab64890Smrg    req->full = req->partial = 0;
4811ab64890Smrg    req->firstType = req->nTypes = 0;
4821ab64890Smrg    req->firstKeySym = req->nKeySyms = 0;
4831ab64890Smrg    req->firstKeyAct = req->nKeyActs = 0;
4841ab64890Smrg    req->firstKeyBehavior = req->nKeyBehaviors = 0;
4851ab64890Smrg    req->virtualMods = 0;
4861ab64890Smrg    req->firstKeyExplicit = req->nKeyExplicit = 0;
4871ab64890Smrg    req->firstModMapKey = req->nModMapKeys = 0;
4881ab64890Smrg    req->firstVModMapKey = req->nVModMapKeys = 0;
4891ab64890Smrg    return req;
4901ab64890Smrg}
4911ab64890Smrg
4921ab64890SmrgStatus
493818534a1Smrg_XkbReadGetMapReply(Display *dpy,
494818534a1Smrg                    xkbGetMapReply *rep,
495818534a1Smrg                    XkbDescPtr xkb,
496818534a1Smrg                    int *nread_rtrn)
4971ab64890Smrg{
498818534a1Smrg    int extraData;
499818534a1Smrg    unsigned mask;
5001ab64890Smrg
501818534a1Smrg    if (xkb->device_spec == XkbUseCoreKbd)
502818534a1Smrg        xkb->device_spec = rep->deviceID;
503818534a1Smrg    if (rep->maxKeyCode < rep->minKeyCode)
504818534a1Smrg        return BadImplementation;
5051ab64890Smrg    xkb->min_key_code = rep->minKeyCode;
5061ab64890Smrg    xkb->max_key_code = rep->maxKeyCode;
5071ab64890Smrg
5081ab64890Smrg    if (!xkb->map) {
509818534a1Smrg        mask = rep->present & XkbAllClientInfoMask;
510818534a1Smrg        if (mask && (XkbAllocClientMap(xkb, mask, rep->nTypes) != Success))
511818534a1Smrg            return BadAlloc;
5121ab64890Smrg    }
5131ab64890Smrg    if (!xkb->server) {
514818534a1Smrg        mask = rep->present & XkbAllServerInfoMask;
515818534a1Smrg        if (mask && (XkbAllocServerMap(xkb, mask, rep->totalActs) != Success))
516818534a1Smrg            return BadAlloc;
5171ab64890Smrg    }
518818534a1Smrg    extraData = (int) (rep->length * 4);
519818534a1Smrg    extraData -= (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
5201ab64890Smrg    if (rep->length) {
521818534a1Smrg        XkbReadBufferRec buf;
522818534a1Smrg        int left;
523818534a1Smrg
524818534a1Smrg        if (_XkbInitReadBuffer(dpy, &buf, extraData)) {
525818534a1Smrg            Status status = Success;
526818534a1Smrg
527818534a1Smrg            if (nread_rtrn != NULL)
528818534a1Smrg                *nread_rtrn = extraData;
529818534a1Smrg            if (status == Success)
530818534a1Smrg                status = _XkbReadKeyTypes(&buf, xkb, rep);
531818534a1Smrg            if (status == Success)
532818534a1Smrg                status = _XkbReadKeySyms(&buf, xkb, rep);
533818534a1Smrg            if (status == Success)
534818534a1Smrg                status = _XkbReadKeyActions(&buf, xkb, rep);
535818534a1Smrg            if (status == Success)
536818534a1Smrg                status = _XkbReadKeyBehaviors(&buf, xkb, rep);
537818534a1Smrg            if (status == Success)
538818534a1Smrg                status = _XkbReadVirtualMods(&buf, xkb, rep);
539818534a1Smrg            if (status == Success)
540818534a1Smrg                status = _XkbReadExplicitComponents(&buf, xkb, rep);
541818534a1Smrg            if (status == Success)
542818534a1Smrg                status = _XkbReadModifierMap(&buf, xkb, rep);
543818534a1Smrg            if (status == Success)
544818534a1Smrg                status = _XkbReadVirtualModMap(&buf, xkb, rep);
545818534a1Smrg            left = _XkbFreeReadBuffer(&buf);
546818534a1Smrg            if (status != Success)
547818534a1Smrg                return status;
548818534a1Smrg            else if (left || buf.error)
549818534a1Smrg                return BadLength;
550818534a1Smrg        }
551818534a1Smrg        else
552818534a1Smrg            return BadAlloc;
5531ab64890Smrg    }
5541ab64890Smrg    return Success;
5551ab64890Smrg}
5561ab64890Smrg
5571ab64890Smrgstatic Status
558818534a1Smrg_XkbHandleGetMapReply(Display *dpy, XkbDescPtr xkb)
5591ab64890Smrg{
560818534a1Smrg    xkbGetMapReply rep;
5611ab64890Smrg
562818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep,
563818534a1Smrg                 ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2),
564818534a1Smrg                 xFalse)) {
565818534a1Smrg        return BadImplementation;
5661ab64890Smrg    }
567818534a1Smrg    return _XkbReadGetMapReply(dpy, &rep, xkb, NULL);
5681ab64890Smrg}
5691ab64890Smrg
5701ab64890SmrgStatus
571818534a1SmrgXkbGetUpdatedMap(Display *dpy, unsigned which, XkbDescPtr xkb)
5721ab64890Smrg{
5731ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
574818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
575818534a1Smrg        return BadAccess;
5761ab64890Smrg    if (which) {
577818534a1Smrg        register xkbGetMapReq *req;
578818534a1Smrg        Status status;
5791ab64890Smrg
580818534a1Smrg        LockDisplay(dpy);
5811ab64890Smrg
582818534a1Smrg        req = _XkbGetGetMapReq(dpy, xkb);
583818534a1Smrg        req->full = which;
584818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
5851ab64890Smrg
586818534a1Smrg        UnlockDisplay(dpy);
587818534a1Smrg        SyncHandle();
588818534a1Smrg        return status;
5891ab64890Smrg    }
5901ab64890Smrg    return Success;
5911ab64890Smrg}
5921ab64890Smrg
5931ab64890SmrgXkbDescPtr
594818534a1SmrgXkbGetMap(Display *dpy, unsigned which, unsigned deviceSpec)
5951ab64890Smrg{
596818534a1Smrg    XkbDescPtr xkb;
5971ab64890Smrg
598818534a1Smrg    xkb = _XkbTypedCalloc(1, XkbDescRec);
5991ab64890Smrg    if (xkb) {
600818534a1Smrg        xkb->device_spec = deviceSpec;
601818534a1Smrg        xkb->map = _XkbTypedCalloc(1, XkbClientMapRec);
602818534a1Smrg        if ((xkb->map == NULL) ||
603818534a1Smrg            ((which) && (XkbGetUpdatedMap(dpy, which, xkb) != Success))) {
604818534a1Smrg            if (xkb->map) {
605818534a1Smrg                Xfree(xkb->map);
606818534a1Smrg                xkb->map = NULL;
607818534a1Smrg            }
608818534a1Smrg            Xfree(xkb);
609818534a1Smrg            return NULL;
610818534a1Smrg        }
611818534a1Smrg        xkb->dpy = dpy;
6121ab64890Smrg    }
6131ab64890Smrg    return xkb;
6141ab64890Smrg}
6151ab64890Smrg
6161ab64890SmrgStatus
617818534a1SmrgXkbGetKeyTypes(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6181ab64890Smrg{
6191ab64890Smrg    register xkbGetMapReq *req;
6201ab64890Smrg    Status status;
6211ab64890Smrg
6221ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
623818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
624818534a1Smrg        return BadAccess;
625818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyTypes))
626818534a1Smrg        return BadValue;
6271ab64890Smrg
6281ab64890Smrg    LockDisplay(dpy);
6291ab64890Smrg
6301ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6311ab64890Smrg    req->firstType = first;
6321ab64890Smrg    req->nTypes = num;
633818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6341ab64890Smrg
6351ab64890Smrg    UnlockDisplay(dpy);
6361ab64890Smrg    SyncHandle();
6371ab64890Smrg    return status;
6381ab64890Smrg}
6391ab64890Smrg
6401ab64890SmrgStatus
641818534a1SmrgXkbGetKeyActions(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6421ab64890Smrg{
6431ab64890Smrg    register xkbGetMapReq *req;
6441ab64890Smrg    Status status;
6451ab64890Smrg
6461ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
647818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
648818534a1Smrg        return BadAccess;
6491ab64890Smrg
650818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
651818534a1Smrg        return BadValue;
6521ab64890Smrg
6531ab64890Smrg    LockDisplay(dpy);
6541ab64890Smrg
6551ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6561ab64890Smrg    req->firstKeyAct = first;
6571ab64890Smrg    req->nKeyActs = num;
658818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6591ab64890Smrg
6601ab64890Smrg    UnlockDisplay(dpy);
6611ab64890Smrg    SyncHandle();
6621ab64890Smrg    return status;
6631ab64890Smrg}
6641ab64890Smrg
6651ab64890SmrgStatus
666818534a1SmrgXkbGetKeySyms(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6671ab64890Smrg{
6681ab64890Smrg    register xkbGetMapReq *req;
6691ab64890Smrg    Status status;
6701ab64890Smrg
6711ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
672818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
673818534a1Smrg        return BadAccess;
6741ab64890Smrg
675818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
676818534a1Smrg        return BadValue;
6771ab64890Smrg
6781ab64890Smrg    LockDisplay(dpy);
6791ab64890Smrg
6801ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6811ab64890Smrg    req->firstKeySym = first;
6821ab64890Smrg    req->nKeySyms = num;
683818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6841ab64890Smrg
6851ab64890Smrg    UnlockDisplay(dpy);
6861ab64890Smrg    SyncHandle();
6871ab64890Smrg
6881ab64890Smrg    return status;
6891ab64890Smrg}
6901ab64890Smrg
6911ab64890SmrgStatus
692818534a1SmrgXkbGetKeyBehaviors(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6931ab64890Smrg{
6941ab64890Smrg    register xkbGetMapReq *req;
6951ab64890Smrg    Status status;
6961ab64890Smrg
6971ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
698818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
699818534a1Smrg        return BadAccess;
7001ab64890Smrg
701818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
702818534a1Smrg        return BadValue;
7031ab64890Smrg
7041ab64890Smrg    LockDisplay(dpy);
7051ab64890Smrg
7061ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7071ab64890Smrg    req->firstKeyBehavior = first;
7081ab64890Smrg    req->nKeyBehaviors = num;
709818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
7101ab64890Smrg
7111ab64890Smrg    UnlockDisplay(dpy);
7121ab64890Smrg    SyncHandle();
7131ab64890Smrg    return status;
7141ab64890Smrg}
7151ab64890Smrg
7161ab64890SmrgStatus
717818534a1SmrgXkbGetVirtualMods(Display *dpy, unsigned which, XkbDescPtr xkb)
7181ab64890Smrg{
7191ab64890Smrg    register xkbGetMapReq *req;
7201ab64890Smrg    Status status;
7211ab64890Smrg
7221ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
723818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
724818534a1Smrg        return BadAccess;
7251ab64890Smrg
7261ab64890Smrg    LockDisplay(dpy);
7271ab64890Smrg
7281ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7291ab64890Smrg    req->virtualMods = which;
730818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
7311ab64890Smrg
7321ab64890Smrg    UnlockDisplay(dpy);
7331ab64890Smrg    SyncHandle();
7341ab64890Smrg    return status;
7351ab64890Smrg}
7361ab64890Smrg
7371ab64890SmrgStatus
738818534a1SmrgXkbGetKeyExplicitComponents(Display *dpy,
739818534a1Smrg                            unsigned first,
740818534a1Smrg                            unsigned num,
741818534a1Smrg                            XkbDescPtr xkb)
7421ab64890Smrg{
7431ab64890Smrg    register xkbGetMapReq *req;
7441ab64890Smrg    Status status;
7451ab64890Smrg
7461ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
747818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
748818534a1Smrg        return BadAccess;
7491ab64890Smrg
750818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
751818534a1Smrg        return BadValue;
7521ab64890Smrg
7531ab64890Smrg    LockDisplay(dpy);
7541ab64890Smrg
7551ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7561ab64890Smrg    req->firstKeyExplicit = first;
7571ab64890Smrg    req->nKeyExplicit = num;
758818534a1Smrg    if ((xkb != NULL) && (xkb->server != NULL) &&
759818534a1Smrg        (xkb->server->explicit != NULL)) {
760818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
761818534a1Smrg            (first + num <= xkb->max_key_code))
762818534a1Smrg            bzero(&xkb->server->explicit[first], num);
7631ab64890Smrg    }
7641ab64890Smrg    if (xkb)
765818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
7661ab64890Smrg    else
7671ab64890Smrg        status = BadMatch;
7681ab64890Smrg
7691ab64890Smrg    UnlockDisplay(dpy);
7701ab64890Smrg    SyncHandle();
7711ab64890Smrg    return status;
7721ab64890Smrg}
7731ab64890Smrg
7741ab64890SmrgStatus
775818534a1SmrgXkbGetKeyModifierMap(Display *dpy,
776818534a1Smrg                     unsigned first,
777818534a1Smrg                     unsigned num,
778818534a1Smrg                     XkbDescPtr xkb)
7791ab64890Smrg{
7801ab64890Smrg    register xkbGetMapReq *req;
7811ab64890Smrg    Status status;
7821ab64890Smrg
7831ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
784818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
785818534a1Smrg        return BadAccess;
7861ab64890Smrg
787818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
788818534a1Smrg        return BadValue;
7891ab64890Smrg
7901ab64890Smrg    LockDisplay(dpy);
7911ab64890Smrg
7921ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7931ab64890Smrg    req->firstModMapKey = first;
7941ab64890Smrg    req->nModMapKeys = num;
795818534a1Smrg    if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
796818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
797818534a1Smrg            (first + num <= xkb->max_key_code))
798818534a1Smrg            bzero(&xkb->map->modmap[first], num);
7991ab64890Smrg    }
8001ab64890Smrg    if (xkb)
801818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
8021ab64890Smrg    else
8031ab64890Smrg        status = BadMatch;
8041ab64890Smrg
8051ab64890Smrg    UnlockDisplay(dpy);
8061ab64890Smrg    SyncHandle();
8071ab64890Smrg    return status;
8081ab64890Smrg}
8091ab64890Smrg
8101ab64890SmrgStatus
811818534a1SmrgXkbGetKeyVirtualModMap(Display *dpy, unsigned first, unsigned num,
812818534a1Smrg                       XkbDescPtr xkb)
8131ab64890Smrg{
8141ab64890Smrg    register xkbGetMapReq *req;
8151ab64890Smrg    Status status;
8161ab64890Smrg
8171ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
818818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
819818534a1Smrg        return BadAccess;
8201ab64890Smrg
821818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
822818534a1Smrg        return BadValue;
8231ab64890Smrg
8241ab64890Smrg    LockDisplay(dpy);
8251ab64890Smrg
8261ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
8271ab64890Smrg    req->firstVModMapKey = first;
8281ab64890Smrg    req->nVModMapKeys = num;
829818534a1Smrg    if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
830818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
831818534a1Smrg            (first + num <= xkb->max_key_code))
832818534a1Smrg            bzero(&xkb->server->vmodmap[first], num * sizeof(unsigned short));
8331ab64890Smrg    }
8341ab64890Smrg
8351ab64890Smrg    if (xkb)
836818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
8371ab64890Smrg    else
8381ab64890Smrg        status = BadMatch;
8391ab64890Smrg
8401ab64890Smrg    UnlockDisplay(dpy);
8411ab64890Smrg    SyncHandle();
8421ab64890Smrg    return status;
8431ab64890Smrg}
8441ab64890Smrg
8451ab64890SmrgStatus
846818534a1SmrgXkbGetMapChanges(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
8471ab64890Smrg{
8481ab64890Smrg    xkbGetMapReq *req;
8491ab64890Smrg
8501ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
851818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
852818534a1Smrg        return BadAccess;
8531ab64890Smrg    LockDisplay(dpy);
8541ab64890Smrg    if (changes->changed) {
855818534a1Smrg        Status status = Success;
856818534a1Smrg
857818534a1Smrg        req = _XkbGetGetMapReq(dpy, xkb);
858818534a1Smrg        req->full = 0;
859818534a1Smrg        req->partial = changes->changed;
860818534a1Smrg        req->firstType = changes->first_type;
861818534a1Smrg        req->nTypes = changes->num_types;
862818534a1Smrg        req->firstKeySym = changes->first_key_sym;
863818534a1Smrg        req->nKeySyms = changes->num_key_syms;
864818534a1Smrg        req->firstKeyAct = changes->first_key_act;
865818534a1Smrg        req->nKeyActs = changes->num_key_acts;
866818534a1Smrg        req->firstKeyBehavior = changes->first_key_behavior;
867818534a1Smrg        req->nKeyBehaviors = changes->num_key_behaviors;
868818534a1Smrg        req->virtualMods = changes->vmods;
869818534a1Smrg        req->firstKeyExplicit = changes->first_key_explicit;
870818534a1Smrg        req->nKeyExplicit = changes->num_key_explicit;
871818534a1Smrg        req->firstModMapKey = changes->first_modmap_key;
872818534a1Smrg        req->nModMapKeys = changes->num_modmap_keys;
873818534a1Smrg        req->firstVModMapKey = changes->first_vmodmap_key;
874818534a1Smrg        req->nVModMapKeys = changes->num_vmodmap_keys;
875818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
876818534a1Smrg        UnlockDisplay(dpy);
877818534a1Smrg        SyncHandle();
878818534a1Smrg        return status;
8791ab64890Smrg    }
8801ab64890Smrg    UnlockDisplay(dpy);
8811ab64890Smrg    return Success;
8821ab64890Smrg}
883