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)) {
66258a0ebeSmrg                    _XkbResizeArray(type->map, type->map_count,
67258a0ebeSmrg                                  desc->nMapEntries, XkbKTMapEntryRec);
68818534a1Smrg                    if (type->map == NULL) {
69818534a1Smrg                        return BadAlloc;
70818534a1Smrg                    }
71818534a1Smrg                }
72818534a1Smrg            }
73818534a1Smrg            else if (type->map != NULL) {
74818534a1Smrg                Xfree(type->map);
75818534a1Smrg                type->map_count = 0;
76818534a1Smrg                type->map = NULL;
77818534a1Smrg            }
78818534a1Smrg
79818534a1Smrg            if (desc->preserve && (desc->nMapEntries > 0)) {
80818534a1Smrg                if ((!type->preserve) || (desc->nMapEntries > lastMapCount)) {
81258a0ebeSmrg                    _XkbResizeArray(type->preserve, lastMapCount,
82258a0ebeSmrg                                    desc->nMapEntries, XkbModsRec);
83818534a1Smrg                    if (type->preserve == NULL) {
84818534a1Smrg                        return BadAlloc;
85818534a1Smrg                    }
86818534a1Smrg                }
87818534a1Smrg            }
88818534a1Smrg            else if (type->preserve != NULL) {
89818534a1Smrg                Xfree(type->preserve);
90818534a1Smrg                type->preserve = NULL;
91818534a1Smrg            }
92818534a1Smrg
93818534a1Smrg            type->mods.mask = desc->mask;
94818534a1Smrg            type->mods.real_mods = desc->realMods;
95818534a1Smrg            type->mods.vmods = desc->virtualMods;
96818534a1Smrg            type->num_levels = desc->numLevels;
97818534a1Smrg            type->map_count = desc->nMapEntries;
98818534a1Smrg            if (desc->nMapEntries > 0) {
99818534a1Smrg                register xkbKTMapEntryWireDesc *wire;
100818534a1Smrg                register XkbKTMapEntryPtr entry;
101818534a1Smrg                register int size;
102818534a1Smrg
103818534a1Smrg                size = type->map_count * SIZEOF(xkbKTMapEntryWireDesc);
104818534a1Smrg                wire =
105818534a1Smrg                    (xkbKTMapEntryWireDesc *) _XkbGetReadBufferPtr(buf, size);
106818534a1Smrg                if (wire == NULL)
107818534a1Smrg                    return BadLength;
108818534a1Smrg                entry = type->map;
109818534a1Smrg                for (n = 0; n < type->map_count; n++, wire++, entry++) {
110818534a1Smrg                    entry->active = wire->active;
111818534a1Smrg                    entry->level = wire->level;
112818534a1Smrg                    entry->mods.mask = wire->mask;
113818534a1Smrg                    entry->mods.real_mods = wire->realMods;
114818534a1Smrg                    entry->mods.vmods = wire->virtualMods;
115818534a1Smrg                }
116818534a1Smrg
117818534a1Smrg                if (desc->preserve) {
118818534a1Smrg                    register xkbModsWireDesc *pwire;
119818534a1Smrg                    register XkbModsPtr preserve;
120818534a1Smrg                    register int sz;
121818534a1Smrg
122818534a1Smrg                    sz = desc->nMapEntries * SIZEOF(xkbModsWireDesc);
123818534a1Smrg                    pwire = (xkbModsWireDesc *) _XkbGetReadBufferPtr(buf, sz);
124818534a1Smrg                    if (pwire == NULL)
125818534a1Smrg                        return BadLength;
126818534a1Smrg                    preserve = type->preserve;
127818534a1Smrg                    for (n = 0; n < desc->nMapEntries; n++, pwire++, preserve++) {
128818534a1Smrg                        preserve->mask = pwire->mask;
129818534a1Smrg                        preserve->vmods = pwire->virtualMods;
130818534a1Smrg                        preserve->real_mods = pwire->realMods;
131818534a1Smrg                    }
132818534a1Smrg                }
133818534a1Smrg            }
134818534a1Smrg        }
1351ab64890Smrg    }
1361ab64890Smrg    return Success;
1371ab64890Smrg}
1381ab64890Smrg
1391ab64890Smrgstatic Status
140818534a1Smrg_XkbReadKeySyms(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
1411ab64890Smrg{
142818534a1Smrg    register int i;
143818534a1Smrg    XkbClientMapPtr map;
144818534a1Smrg    int size = xkb->max_key_code + 1;
145818534a1Smrg
146818534a1Smrg    if (((unsigned short) rep->firstKeySym + rep->nKeySyms) > size)
147818534a1Smrg        return BadLength;
148818534a1Smrg
149818534a1Smrg    map = xkb->map;
150818534a1Smrg    if (map->key_sym_map == NULL) {
151818534a1Smrg        register int offset;
152818534a1Smrg        XkbSymMapPtr oldMap;
153818534a1Smrg        xkbSymMapWireDesc *newMap;
154818534a1Smrg
155818534a1Smrg        map->key_sym_map = _XkbTypedCalloc(size, XkbSymMapRec);
156818534a1Smrg        if (map->key_sym_map == NULL)
157818534a1Smrg            return BadAlloc;
158818534a1Smrg        if (map->syms == NULL) {
159818534a1Smrg            int sz;
160818534a1Smrg
161818534a1Smrg            sz = (rep->totalSyms * 12) / 10;
162818534a1Smrg            sz = ((sz + (unsigned) 128) / 128) * 128;
163818534a1Smrg            map->syms = _XkbTypedCalloc(sz, KeySym);
164818534a1Smrg            if (map->syms == NULL)
165818534a1Smrg                return BadAlloc;
166818534a1Smrg            map->size_syms = sz;
167818534a1Smrg        }
168818534a1Smrg        offset = 1;
169818534a1Smrg        oldMap = &map->key_sym_map[rep->firstKeySym];
170818534a1Smrg        for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
171818534a1Smrg            newMap = (xkbSymMapWireDesc *)
172818534a1Smrg                _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
173818534a1Smrg            if (newMap == NULL)
174818534a1Smrg                return BadLength;
175818534a1Smrg            oldMap->kt_index[0] = newMap->ktIndex[0];
176818534a1Smrg            oldMap->kt_index[1] = newMap->ktIndex[1];
177818534a1Smrg            oldMap->kt_index[2] = newMap->ktIndex[2];
178818534a1Smrg            oldMap->kt_index[3] = newMap->ktIndex[3];
179818534a1Smrg            oldMap->group_info = newMap->groupInfo;
180818534a1Smrg            oldMap->width = newMap->width;
181818534a1Smrg            oldMap->offset = offset;
182818534a1Smrg            if (offset + newMap->nSyms >= map->size_syms) {
183818534a1Smrg                register int sz;
184818534a1Smrg
185cbfda780Smrg                sz = offset + newMap->nSyms;
186cbfda780Smrg                sz = ((sz + (unsigned) 128) / 128) * 128;
187258a0ebeSmrg                _XkbResizeArray(map->syms, map->size_syms, sz, KeySym);
188818534a1Smrg                if (map->syms == NULL) {
189818534a1Smrg                    map->size_syms = 0;
190818534a1Smrg                    return BadAlloc;
191818534a1Smrg                }
192818534a1Smrg                map->size_syms = sz;
193818534a1Smrg            }
194818534a1Smrg            if (newMap->nSyms > 0) {
195cbfda780Smrg                if (_XkbReadBufferCopyKeySyms(buf, (KeySym *) &map->syms[offset],
196cbfda780Smrg                                              newMap->nSyms) == 0)
197cbfda780Smrg                    return BadLength;
198818534a1Smrg                offset += newMap->nSyms;
199818534a1Smrg            }
200818534a1Smrg            else {
201818534a1Smrg                map->syms[offset] = 0;
202818534a1Smrg            }
203818534a1Smrg        }
204818534a1Smrg        map->num_syms = offset;
2051ab64890Smrg    }
2061ab64890Smrg    else {
207818534a1Smrg        XkbSymMapPtr oldMap = &map->key_sym_map[rep->firstKeySym];
208818534a1Smrg
209818534a1Smrg        for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
210818534a1Smrg            xkbSymMapWireDesc *newMap;
211818534a1Smrg            KeySym *newSyms;
212818534a1Smrg            int tmp;
213818534a1Smrg
214818534a1Smrg            newMap = (xkbSymMapWireDesc *)
215818534a1Smrg                _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
216818534a1Smrg            if (newMap == NULL)
217818534a1Smrg                return BadLength;
218818534a1Smrg
219818534a1Smrg            if (newMap->nSyms > 0)
220818534a1Smrg                tmp = newMap->nSyms;
221818534a1Smrg            else
222818534a1Smrg                tmp = 0;
223818534a1Smrg
224818534a1Smrg            newSyms = XkbResizeKeySyms(xkb, i + rep->firstKeySym, tmp);
225818534a1Smrg            if (newSyms == NULL)
226818534a1Smrg                return BadAlloc;
227cbfda780Smrg            if (newMap->nSyms > 0) {
228cbfda780Smrg                if (_XkbReadBufferCopyKeySyms(buf, newSyms, newMap->nSyms) == 0)
229cbfda780Smrg                    return BadLength;
230cbfda780Smrg            }
231818534a1Smrg            else
232818534a1Smrg                newSyms[0] = NoSymbol;
233818534a1Smrg            oldMap->kt_index[0] = newMap->ktIndex[0];
234818534a1Smrg            oldMap->kt_index[1] = newMap->ktIndex[1];
235818534a1Smrg            oldMap->kt_index[2] = newMap->ktIndex[2];
236818534a1Smrg            oldMap->kt_index[3] = newMap->ktIndex[3];
237818534a1Smrg            oldMap->group_info = newMap->groupInfo;
238818534a1Smrg            oldMap->width = newMap->width;
239818534a1Smrg        }
2401ab64890Smrg    }
2411ab64890Smrg    return Success;
2421ab64890Smrg}
2431ab64890Smrg
2441ab64890Smrgstatic Status
245818534a1Smrg_XkbReadKeyActions(XkbReadBufferPtr buf, XkbDescPtr info, xkbGetMapReply *rep)
2461ab64890Smrg{
247818534a1Smrg    int i;
248818534a1Smrg    CARD8 numDescBuf[248];
249818534a1Smrg    CARD8 *numDesc = NULL;
250818534a1Smrg    register int nKeyActs;
251818534a1Smrg    Status ret = Success;
252818534a1Smrg
253818534a1Smrg    if ((nKeyActs = rep->nKeyActs) > 0) {
254818534a1Smrg        XkbSymMapPtr symMap;
255818534a1Smrg
256818534a1Smrg        if (nKeyActs < sizeof numDescBuf)
257818534a1Smrg            numDesc = numDescBuf;
258818534a1Smrg        else
259258a0ebeSmrg            numDesc = Xmallocarray(nKeyActs, sizeof(CARD8));
260818534a1Smrg
261818534a1Smrg        if (!_XkbCopyFromReadBuffer(buf, (char *) numDesc, nKeyActs)) {
262818534a1Smrg            ret = BadLength;
263818534a1Smrg            goto done;
264818534a1Smrg        }
265818534a1Smrg        i = XkbPaddedSize(nKeyActs) - nKeyActs;
266818534a1Smrg        if ((i > 0) && (!_XkbSkipReadBufferData(buf, i))) {
267818534a1Smrg            ret = BadLength;
268818534a1Smrg            goto done;
269818534a1Smrg        }
270818534a1Smrg        symMap = &info->map->key_sym_map[rep->firstKeyAct];
271818534a1Smrg        for (i = 0; i < (int) rep->nKeyActs; i++, symMap++) {
272818534a1Smrg            if (numDesc[i] == 0) {
273818534a1Smrg                if ((i + rep->firstKeyAct) > (info->max_key_code + 1)) {
274818534a1Smrg                    ret = BadLength;
275818534a1Smrg                    goto done;
276818534a1Smrg                }
277818534a1Smrg                info->server->key_acts[i + rep->firstKeyAct] = 0;
278818534a1Smrg            }
279818534a1Smrg            else {
280818534a1Smrg                XkbAction *newActs;
281818534a1Smrg
282818534a1Smrg                /* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
283818534a1Smrg                /*                 either zero or XkbKeyNumSyms(info,key) */
284818534a1Smrg                newActs = XkbResizeKeyActions(info, i + rep->firstKeyAct,
285818534a1Smrg                                              numDesc[i]);
286818534a1Smrg                if (newActs == NULL) {
287818534a1Smrg                    ret = BadAlloc;
288818534a1Smrg                    goto done;
289818534a1Smrg                }
290818534a1Smrg                if (!_XkbCopyFromReadBuffer(buf, (char *) newActs,
291818534a1Smrg                            (int) (numDesc[i] * sizeof(XkbAction)))) {
292818534a1Smrg                    ret = BadLength;
293818534a1Smrg                    goto done;
294818534a1Smrg                }
295818534a1Smrg            }
296818534a1Smrg        }
2971ab64890Smrg    }
298818534a1Smrg done:
299818534a1Smrg    if (numDesc != NULL && numDesc != numDescBuf)
300818534a1Smrg        Xfree(numDesc);
3011ab64890Smrg    return ret;
3021ab64890Smrg}
3031ab64890Smrg
3041ab64890Smrgstatic Status
305818534a1Smrg_XkbReadKeyBehaviors(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
3061ab64890Smrg{
307818534a1Smrg    register int i;
308818534a1Smrg
309818534a1Smrg    if (rep->totalKeyBehaviors > 0) {
310818534a1Smrg        int size = xkb->max_key_code + 1;
311818534a1Smrg
312818534a1Smrg        if (((int) rep->firstKeyBehavior + rep->nKeyBehaviors) > size)
313818534a1Smrg            return BadLength;
314818534a1Smrg        if (xkb->server->behaviors == NULL) {
315818534a1Smrg            xkb->server->behaviors = _XkbTypedCalloc(size, XkbBehavior);
316818534a1Smrg            if (xkb->server->behaviors == NULL)
317818534a1Smrg                return BadAlloc;
318818534a1Smrg        }
319818534a1Smrg        else {
320818534a1Smrg            bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
321818534a1Smrg                  (rep->nKeyBehaviors * sizeof(XkbBehavior)));
322818534a1Smrg        }
323818534a1Smrg        for (i = 0; i < rep->totalKeyBehaviors; i++) {
324818534a1Smrg            xkbBehaviorWireDesc *wire;
325818534a1Smrg
326818534a1Smrg            wire = (xkbBehaviorWireDesc *) _XkbGetReadBufferPtr(buf,
327818534a1Smrg                                               SIZEOF(xkbBehaviorWireDesc));
328818534a1Smrg            if (wire == NULL || wire->key >= size)
329818534a1Smrg                return BadLength;
330818534a1Smrg            xkb->server->behaviors[wire->key].type = wire->type;
331818534a1Smrg            xkb->server->behaviors[wire->key].data = wire->data;
332818534a1Smrg        }
3331ab64890Smrg    }
3341ab64890Smrg    return Success;
3351ab64890Smrg}
3361ab64890Smrg
3371ab64890Smrgstatic Status
338818534a1Smrg_XkbReadVirtualMods(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
3391ab64890Smrg{
340818534a1Smrg    if (rep->virtualMods) {
341818534a1Smrg        register int i, bit, nVMods;
342818534a1Smrg        register char *data;
343818534a1Smrg
344818534a1Smrg        for (i = nVMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
345818534a1Smrg            if (rep->virtualMods & bit)
346818534a1Smrg                nVMods++;
347818534a1Smrg        }
348818534a1Smrg        data = _XkbGetReadBufferPtr(buf, XkbPaddedSize(nVMods));
349818534a1Smrg        if (data == NULL)
350818534a1Smrg            return BadLength;
351818534a1Smrg        for (i = 0, bit = 1; (i < XkbNumVirtualMods) && (nVMods > 0);
352818534a1Smrg             i++, bit <<= 1) {
353818534a1Smrg            if (rep->virtualMods & bit) {
354818534a1Smrg                xkb->server->vmods[i] = *data++;
355818534a1Smrg                nVMods--;
356818534a1Smrg            }
357818534a1Smrg        }
3581ab64890Smrg    }
3591ab64890Smrg    return Success;
3601ab64890Smrg}
3611ab64890Smrg
3621ab64890Smrgstatic Status
363818534a1Smrg_XkbReadExplicitComponents(XkbReadBufferPtr buf,
364818534a1Smrg                           XkbDescPtr xkb,
365818534a1Smrg                           xkbGetMapReply *rep)
3661ab64890Smrg{
367818534a1Smrg    register int i;
368818534a1Smrg    unsigned char *wire;
369818534a1Smrg
370818534a1Smrg    if (rep->totalKeyExplicit > 0) {
371818534a1Smrg        int size = xkb->max_key_code + 1;
372818534a1Smrg
373818534a1Smrg        if (((int) rep->firstKeyExplicit + rep->nKeyExplicit) > size)
374818534a1Smrg            return BadLength;
375818534a1Smrg        if (xkb->server->explicit == NULL) {
376818534a1Smrg            xkb->server->explicit = _XkbTypedCalloc(size, unsigned char);
377818534a1Smrg
378818534a1Smrg            if (xkb->server->explicit == NULL)
379818534a1Smrg                return BadAlloc;
380818534a1Smrg        }
381818534a1Smrg        else {
382818534a1Smrg            bzero(&xkb->server->explicit[rep->firstKeyExplicit],
383818534a1Smrg                  rep->nKeyExplicit);
384818534a1Smrg        }
385818534a1Smrg        i = XkbPaddedSize(2 * rep->totalKeyExplicit);
386818534a1Smrg        wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
387818534a1Smrg        if (!wire)
388818534a1Smrg            return BadLength;
389818534a1Smrg        for (i = 0; i < rep->totalKeyExplicit; i++, wire += 2) {
390818534a1Smrg            if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
391818534a1Smrg                return BadLength;
392818534a1Smrg            xkb->server->explicit[wire[0]] = wire[1];
393818534a1Smrg        }
3941ab64890Smrg    }
3951ab64890Smrg    return Success;
3961ab64890Smrg}
3971ab64890Smrg
3981ab64890Smrgstatic Status
399818534a1Smrg_XkbReadModifierMap(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
4001ab64890Smrg{
401818534a1Smrg    register int i;
402818534a1Smrg    unsigned char *wire;
403818534a1Smrg
404818534a1Smrg    if (rep->totalModMapKeys > 0) {
405818534a1Smrg        if (((int) rep->firstModMapKey + rep->nModMapKeys) >
406818534a1Smrg            (xkb->max_key_code + 1))
407818534a1Smrg            return BadLength;
408818534a1Smrg        if ((xkb->map->modmap == NULL) &&
409818534a1Smrg            (XkbAllocClientMap(xkb, XkbModifierMapMask, 0) != Success)) {
410818534a1Smrg            return BadAlloc;
411818534a1Smrg        }
412818534a1Smrg        else {
413818534a1Smrg            bzero(&xkb->map->modmap[rep->firstModMapKey], rep->nModMapKeys);
414818534a1Smrg        }
415818534a1Smrg        i = XkbPaddedSize(2 * rep->totalModMapKeys);
416818534a1Smrg        wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
417818534a1Smrg        if (!wire)
418818534a1Smrg            return BadLength;
419818534a1Smrg        for (i = 0; i < rep->totalModMapKeys; i++, wire += 2) {
420818534a1Smrg            if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
421818534a1Smrg                return BadLength;
422818534a1Smrg            xkb->map->modmap[wire[0]] = wire[1];
423818534a1Smrg        }
4241ab64890Smrg    }
4251ab64890Smrg    return Success;
4261ab64890Smrg}
4271ab64890Smrg
4281ab64890Smrgstatic Status
429818534a1Smrg_XkbReadVirtualModMap(XkbReadBufferPtr buf,
430818534a1Smrg                      XkbDescPtr xkb,
431818534a1Smrg                      xkbGetMapReply *rep)
4321ab64890Smrg{
433818534a1Smrg    register int i;
434818534a1Smrg    xkbVModMapWireDesc *wire;
435818534a1Smrg    XkbServerMapPtr srv;
436818534a1Smrg
437818534a1Smrg    if (rep->totalVModMapKeys > 0) {
438818534a1Smrg        if (((int) rep->firstVModMapKey + rep->nVModMapKeys)
439818534a1Smrg            > xkb->max_key_code + 1)
440818534a1Smrg            return BadLength;
441818534a1Smrg        if (((xkb->server == NULL) || (xkb->server->vmodmap == NULL)) &&
442818534a1Smrg            (XkbAllocServerMap(xkb, XkbVirtualModMapMask, 0) != Success)) {
443818534a1Smrg            return BadAlloc;
444818534a1Smrg        }
445818534a1Smrg        else {
446818534a1Smrg            srv = xkb->server;
447818534a1Smrg            if (rep->nVModMapKeys > rep->firstVModMapKey)
448818534a1Smrg                bzero((char *) &srv->vmodmap[rep->firstVModMapKey],
449818534a1Smrg                      (rep->nVModMapKeys - rep->firstVModMapKey) *
450818534a1Smrg                      sizeof(unsigned short));
451818534a1Smrg        }
452818534a1Smrg        srv = xkb->server;
453818534a1Smrg        i = rep->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
454818534a1Smrg        wire = (xkbVModMapWireDesc *) _XkbGetReadBufferPtr(buf, i);
455818534a1Smrg        if (!wire)
456818534a1Smrg            return BadLength;
457818534a1Smrg        for (i = 0; i < rep->totalVModMapKeys; i++, wire++) {
458818534a1Smrg            if ((wire->key >= xkb->min_key_code) &&
459818534a1Smrg                (wire->key <= xkb->max_key_code))
460818534a1Smrg                srv->vmodmap[wire->key] = wire->vmods;
461818534a1Smrg        }
4621ab64890Smrg    }
4631ab64890Smrg    return Success;
4641ab64890Smrg}
4651ab64890Smrg
4661ab64890Smrgstatic xkbGetMapReq *
467818534a1Smrg_XkbGetGetMapReq(Display *dpy, XkbDescPtr xkb)
4681ab64890Smrg{
469818534a1Smrg    xkbGetMapReq *req;
4701ab64890Smrg
4711ab64890Smrg    GetReq(kbGetMap, req);
4721ab64890Smrg    req->reqType = dpy->xkb_info->codes->major_opcode;
4731ab64890Smrg    req->xkbReqType = X_kbGetMap;
4741ab64890Smrg    req->deviceSpec = xkb->device_spec;
4751ab64890Smrg    req->full = req->partial = 0;
4761ab64890Smrg    req->firstType = req->nTypes = 0;
4771ab64890Smrg    req->firstKeySym = req->nKeySyms = 0;
4781ab64890Smrg    req->firstKeyAct = req->nKeyActs = 0;
4791ab64890Smrg    req->firstKeyBehavior = req->nKeyBehaviors = 0;
4801ab64890Smrg    req->virtualMods = 0;
4811ab64890Smrg    req->firstKeyExplicit = req->nKeyExplicit = 0;
4821ab64890Smrg    req->firstModMapKey = req->nModMapKeys = 0;
4831ab64890Smrg    req->firstVModMapKey = req->nVModMapKeys = 0;
4841ab64890Smrg    return req;
4851ab64890Smrg}
4861ab64890Smrg
4871ab64890SmrgStatus
488818534a1Smrg_XkbReadGetMapReply(Display *dpy,
489818534a1Smrg                    xkbGetMapReply *rep,
490818534a1Smrg                    XkbDescPtr xkb,
491818534a1Smrg                    int *nread_rtrn)
4921ab64890Smrg{
493818534a1Smrg    int extraData;
494818534a1Smrg    unsigned mask;
4951ab64890Smrg
496818534a1Smrg    if (xkb->device_spec == XkbUseCoreKbd)
497818534a1Smrg        xkb->device_spec = rep->deviceID;
498818534a1Smrg    if (rep->maxKeyCode < rep->minKeyCode)
499818534a1Smrg        return BadImplementation;
5001ab64890Smrg    xkb->min_key_code = rep->minKeyCode;
5011ab64890Smrg    xkb->max_key_code = rep->maxKeyCode;
5021ab64890Smrg
5031ab64890Smrg    if (!xkb->map) {
504818534a1Smrg        mask = rep->present & XkbAllClientInfoMask;
505818534a1Smrg        if (mask && (XkbAllocClientMap(xkb, mask, rep->nTypes) != Success))
506818534a1Smrg            return BadAlloc;
5071ab64890Smrg    }
5081ab64890Smrg    if (!xkb->server) {
509818534a1Smrg        mask = rep->present & XkbAllServerInfoMask;
510818534a1Smrg        if (mask && (XkbAllocServerMap(xkb, mask, rep->totalActs) != Success))
511818534a1Smrg            return BadAlloc;
5121ab64890Smrg    }
513818534a1Smrg    extraData = (int) (rep->length * 4);
514818534a1Smrg    extraData -= (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
5151ab64890Smrg    if (rep->length) {
516818534a1Smrg        XkbReadBufferRec buf;
517818534a1Smrg        int left;
518818534a1Smrg
519818534a1Smrg        if (_XkbInitReadBuffer(dpy, &buf, extraData)) {
520818534a1Smrg            Status status = Success;
521818534a1Smrg
522818534a1Smrg            if (nread_rtrn != NULL)
523818534a1Smrg                *nread_rtrn = extraData;
524818534a1Smrg            if (status == Success)
525818534a1Smrg                status = _XkbReadKeyTypes(&buf, xkb, rep);
526818534a1Smrg            if (status == Success)
527818534a1Smrg                status = _XkbReadKeySyms(&buf, xkb, rep);
528818534a1Smrg            if (status == Success)
529818534a1Smrg                status = _XkbReadKeyActions(&buf, xkb, rep);
530818534a1Smrg            if (status == Success)
531818534a1Smrg                status = _XkbReadKeyBehaviors(&buf, xkb, rep);
532818534a1Smrg            if (status == Success)
533818534a1Smrg                status = _XkbReadVirtualMods(&buf, xkb, rep);
534818534a1Smrg            if (status == Success)
535818534a1Smrg                status = _XkbReadExplicitComponents(&buf, xkb, rep);
536818534a1Smrg            if (status == Success)
537818534a1Smrg                status = _XkbReadModifierMap(&buf, xkb, rep);
538818534a1Smrg            if (status == Success)
539818534a1Smrg                status = _XkbReadVirtualModMap(&buf, xkb, rep);
540818534a1Smrg            left = _XkbFreeReadBuffer(&buf);
541818534a1Smrg            if (status != Success)
542818534a1Smrg                return status;
543818534a1Smrg            else if (left || buf.error)
544818534a1Smrg                return BadLength;
545818534a1Smrg        }
546818534a1Smrg        else
547818534a1Smrg            return BadAlloc;
5481ab64890Smrg    }
5491ab64890Smrg    return Success;
5501ab64890Smrg}
5511ab64890Smrg
5521ab64890Smrgstatic Status
553818534a1Smrg_XkbHandleGetMapReply(Display *dpy, XkbDescPtr xkb)
5541ab64890Smrg{
555818534a1Smrg    xkbGetMapReply rep;
5561ab64890Smrg
557818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep,
558818534a1Smrg                 ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2),
559818534a1Smrg                 xFalse)) {
560818534a1Smrg        return BadImplementation;
5611ab64890Smrg    }
562818534a1Smrg    return _XkbReadGetMapReply(dpy, &rep, xkb, NULL);
5631ab64890Smrg}
5641ab64890Smrg
5651ab64890SmrgStatus
566818534a1SmrgXkbGetUpdatedMap(Display *dpy, unsigned which, XkbDescPtr xkb)
5671ab64890Smrg{
5681ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
569818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
570818534a1Smrg        return BadAccess;
5711ab64890Smrg    if (which) {
572818534a1Smrg        register xkbGetMapReq *req;
573818534a1Smrg        Status status;
5741ab64890Smrg
575818534a1Smrg        LockDisplay(dpy);
5761ab64890Smrg
577818534a1Smrg        req = _XkbGetGetMapReq(dpy, xkb);
578818534a1Smrg        req->full = which;
579818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
5801ab64890Smrg
581818534a1Smrg        UnlockDisplay(dpy);
582818534a1Smrg        SyncHandle();
583818534a1Smrg        return status;
5841ab64890Smrg    }
5851ab64890Smrg    return Success;
5861ab64890Smrg}
5871ab64890Smrg
5881ab64890SmrgXkbDescPtr
589818534a1SmrgXkbGetMap(Display *dpy, unsigned which, unsigned deviceSpec)
5901ab64890Smrg{
591818534a1Smrg    XkbDescPtr xkb;
5921ab64890Smrg
593818534a1Smrg    xkb = _XkbTypedCalloc(1, XkbDescRec);
5941ab64890Smrg    if (xkb) {
595818534a1Smrg        xkb->device_spec = deviceSpec;
596818534a1Smrg        xkb->map = _XkbTypedCalloc(1, XkbClientMapRec);
597818534a1Smrg        if ((xkb->map == NULL) ||
598818534a1Smrg            ((which) && (XkbGetUpdatedMap(dpy, which, xkb) != Success))) {
599818534a1Smrg            if (xkb->map) {
600818534a1Smrg                Xfree(xkb->map);
601818534a1Smrg                xkb->map = NULL;
602818534a1Smrg            }
603818534a1Smrg            Xfree(xkb);
604818534a1Smrg            return NULL;
605818534a1Smrg        }
606818534a1Smrg        xkb->dpy = dpy;
6071ab64890Smrg    }
6081ab64890Smrg    return xkb;
6091ab64890Smrg}
6101ab64890Smrg
6111ab64890SmrgStatus
612818534a1SmrgXkbGetKeyTypes(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6131ab64890Smrg{
6141ab64890Smrg    register xkbGetMapReq *req;
6151ab64890Smrg    Status status;
6161ab64890Smrg
6171ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
618818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
619818534a1Smrg        return BadAccess;
620818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyTypes))
621818534a1Smrg        return BadValue;
6221ab64890Smrg
6231ab64890Smrg    LockDisplay(dpy);
6241ab64890Smrg
6251ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6261ab64890Smrg    req->firstType = first;
6271ab64890Smrg    req->nTypes = num;
628818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6291ab64890Smrg
6301ab64890Smrg    UnlockDisplay(dpy);
6311ab64890Smrg    SyncHandle();
6321ab64890Smrg    return status;
6331ab64890Smrg}
6341ab64890Smrg
6351ab64890SmrgStatus
636818534a1SmrgXkbGetKeyActions(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6371ab64890Smrg{
6381ab64890Smrg    register xkbGetMapReq *req;
6391ab64890Smrg    Status status;
6401ab64890Smrg
6411ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
642818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
643818534a1Smrg        return BadAccess;
6441ab64890Smrg
645818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
646818534a1Smrg        return BadValue;
6471ab64890Smrg
6481ab64890Smrg    LockDisplay(dpy);
6491ab64890Smrg
6501ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6511ab64890Smrg    req->firstKeyAct = first;
6521ab64890Smrg    req->nKeyActs = num;
653818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6541ab64890Smrg
6551ab64890Smrg    UnlockDisplay(dpy);
6561ab64890Smrg    SyncHandle();
6571ab64890Smrg    return status;
6581ab64890Smrg}
6591ab64890Smrg
6601ab64890SmrgStatus
661818534a1SmrgXkbGetKeySyms(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6621ab64890Smrg{
6631ab64890Smrg    register xkbGetMapReq *req;
6641ab64890Smrg    Status status;
6651ab64890Smrg
6661ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
667818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
668818534a1Smrg        return BadAccess;
6691ab64890Smrg
670818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
671818534a1Smrg        return BadValue;
6721ab64890Smrg
6731ab64890Smrg    LockDisplay(dpy);
6741ab64890Smrg
6751ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
6761ab64890Smrg    req->firstKeySym = first;
6771ab64890Smrg    req->nKeySyms = num;
678818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
6791ab64890Smrg
6801ab64890Smrg    UnlockDisplay(dpy);
6811ab64890Smrg    SyncHandle();
6821ab64890Smrg
6831ab64890Smrg    return status;
6841ab64890Smrg}
6851ab64890Smrg
6861ab64890SmrgStatus
687818534a1SmrgXkbGetKeyBehaviors(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
6881ab64890Smrg{
6891ab64890Smrg    register xkbGetMapReq *req;
6901ab64890Smrg    Status status;
6911ab64890Smrg
6921ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
693818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
694818534a1Smrg        return BadAccess;
6951ab64890Smrg
696818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
697818534a1Smrg        return BadValue;
6981ab64890Smrg
6991ab64890Smrg    LockDisplay(dpy);
7001ab64890Smrg
7011ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7021ab64890Smrg    req->firstKeyBehavior = first;
7031ab64890Smrg    req->nKeyBehaviors = num;
704818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
7051ab64890Smrg
7061ab64890Smrg    UnlockDisplay(dpy);
7071ab64890Smrg    SyncHandle();
7081ab64890Smrg    return status;
7091ab64890Smrg}
7101ab64890Smrg
7111ab64890SmrgStatus
712818534a1SmrgXkbGetVirtualMods(Display *dpy, unsigned which, XkbDescPtr xkb)
7131ab64890Smrg{
7141ab64890Smrg    register xkbGetMapReq *req;
7151ab64890Smrg    Status status;
7161ab64890Smrg
7171ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
718818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
719818534a1Smrg        return BadAccess;
7201ab64890Smrg
7211ab64890Smrg    LockDisplay(dpy);
7221ab64890Smrg
7231ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7241ab64890Smrg    req->virtualMods = which;
725818534a1Smrg    status = _XkbHandleGetMapReply(dpy, xkb);
7261ab64890Smrg
7271ab64890Smrg    UnlockDisplay(dpy);
7281ab64890Smrg    SyncHandle();
7291ab64890Smrg    return status;
7301ab64890Smrg}
7311ab64890Smrg
7321ab64890SmrgStatus
733818534a1SmrgXkbGetKeyExplicitComponents(Display *dpy,
734818534a1Smrg                            unsigned first,
735818534a1Smrg                            unsigned num,
736818534a1Smrg                            XkbDescPtr xkb)
7371ab64890Smrg{
7381ab64890Smrg    register xkbGetMapReq *req;
7391ab64890Smrg    Status status;
7401ab64890Smrg
7411ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
742818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
743818534a1Smrg        return BadAccess;
7441ab64890Smrg
745818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
746818534a1Smrg        return BadValue;
7471ab64890Smrg
7481ab64890Smrg    LockDisplay(dpy);
7491ab64890Smrg
7501ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7511ab64890Smrg    req->firstKeyExplicit = first;
7521ab64890Smrg    req->nKeyExplicit = num;
753818534a1Smrg    if ((xkb != NULL) && (xkb->server != NULL) &&
754818534a1Smrg        (xkb->server->explicit != NULL)) {
755818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
756818534a1Smrg            (first + num <= xkb->max_key_code))
757818534a1Smrg            bzero(&xkb->server->explicit[first], num);
7581ab64890Smrg    }
7591ab64890Smrg    if (xkb)
760818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
7611ab64890Smrg    else
7621ab64890Smrg        status = BadMatch;
7631ab64890Smrg
7641ab64890Smrg    UnlockDisplay(dpy);
7651ab64890Smrg    SyncHandle();
7661ab64890Smrg    return status;
7671ab64890Smrg}
7681ab64890Smrg
7691ab64890SmrgStatus
770818534a1SmrgXkbGetKeyModifierMap(Display *dpy,
771818534a1Smrg                     unsigned first,
772818534a1Smrg                     unsigned num,
773818534a1Smrg                     XkbDescPtr xkb)
7741ab64890Smrg{
7751ab64890Smrg    register xkbGetMapReq *req;
7761ab64890Smrg    Status status;
7771ab64890Smrg
7781ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
779818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
780818534a1Smrg        return BadAccess;
7811ab64890Smrg
782818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
783818534a1Smrg        return BadValue;
7841ab64890Smrg
7851ab64890Smrg    LockDisplay(dpy);
7861ab64890Smrg
7871ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
7881ab64890Smrg    req->firstModMapKey = first;
7891ab64890Smrg    req->nModMapKeys = num;
790818534a1Smrg    if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
791818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
792818534a1Smrg            (first + num <= xkb->max_key_code))
793818534a1Smrg            bzero(&xkb->map->modmap[first], num);
7941ab64890Smrg    }
7951ab64890Smrg    if (xkb)
796818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
7971ab64890Smrg    else
7981ab64890Smrg        status = BadMatch;
7991ab64890Smrg
8001ab64890Smrg    UnlockDisplay(dpy);
8011ab64890Smrg    SyncHandle();
8021ab64890Smrg    return status;
8031ab64890Smrg}
8041ab64890Smrg
8051ab64890SmrgStatus
806818534a1SmrgXkbGetKeyVirtualModMap(Display *dpy, unsigned first, unsigned num,
807818534a1Smrg                       XkbDescPtr xkb)
8081ab64890Smrg{
8091ab64890Smrg    register xkbGetMapReq *req;
8101ab64890Smrg    Status status;
8111ab64890Smrg
8121ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
813818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
814818534a1Smrg        return BadAccess;
8151ab64890Smrg
816818534a1Smrg    if ((num < 1) || (num > XkbMaxKeyCount))
817818534a1Smrg        return BadValue;
8181ab64890Smrg
8191ab64890Smrg    LockDisplay(dpy);
8201ab64890Smrg
8211ab64890Smrg    req = _XkbGetGetMapReq(dpy, xkb);
8221ab64890Smrg    req->firstVModMapKey = first;
8231ab64890Smrg    req->nVModMapKeys = num;
824818534a1Smrg    if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
825818534a1Smrg        if ((num > 0) && (first >= xkb->min_key_code) &&
826818534a1Smrg            (first + num <= xkb->max_key_code))
827818534a1Smrg            bzero(&xkb->server->vmodmap[first], num * sizeof(unsigned short));
8281ab64890Smrg    }
8291ab64890Smrg
8301ab64890Smrg    if (xkb)
831818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
8321ab64890Smrg    else
8331ab64890Smrg        status = BadMatch;
8341ab64890Smrg
8351ab64890Smrg    UnlockDisplay(dpy);
8361ab64890Smrg    SyncHandle();
8371ab64890Smrg    return status;
8381ab64890Smrg}
8391ab64890Smrg
8401ab64890SmrgStatus
841818534a1SmrgXkbGetMapChanges(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
8421ab64890Smrg{
8431ab64890Smrg    xkbGetMapReq *req;
8441ab64890Smrg
8451ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
846818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
847818534a1Smrg        return BadAccess;
8481ab64890Smrg    LockDisplay(dpy);
8491ab64890Smrg    if (changes->changed) {
850818534a1Smrg        Status status = Success;
851818534a1Smrg
852818534a1Smrg        req = _XkbGetGetMapReq(dpy, xkb);
853818534a1Smrg        req->full = 0;
854818534a1Smrg        req->partial = changes->changed;
855818534a1Smrg        req->firstType = changes->first_type;
856818534a1Smrg        req->nTypes = changes->num_types;
857818534a1Smrg        req->firstKeySym = changes->first_key_sym;
858818534a1Smrg        req->nKeySyms = changes->num_key_syms;
859818534a1Smrg        req->firstKeyAct = changes->first_key_act;
860818534a1Smrg        req->nKeyActs = changes->num_key_acts;
861818534a1Smrg        req->firstKeyBehavior = changes->first_key_behavior;
862818534a1Smrg        req->nKeyBehaviors = changes->num_key_behaviors;
863818534a1Smrg        req->virtualMods = changes->vmods;
864818534a1Smrg        req->firstKeyExplicit = changes->first_key_explicit;
865818534a1Smrg        req->nKeyExplicit = changes->num_key_explicit;
866818534a1Smrg        req->firstModMapKey = changes->first_modmap_key;
867818534a1Smrg        req->nModMapKeys = changes->num_modmap_keys;
868818534a1Smrg        req->firstVModMapKey = changes->first_vmodmap_key;
869818534a1Smrg        req->nVModMapKeys = changes->num_vmodmap_keys;
870818534a1Smrg        status = _XkbHandleGetMapReply(dpy, xkb);
871818534a1Smrg        UnlockDisplay(dpy);
872818534a1Smrg        SyncHandle();
873818534a1Smrg        return status;
8741ab64890Smrg    }
8751ab64890Smrg    UnlockDisplay(dpy);
8761ab64890Smrg    return Success;
8771ab64890Smrg}
878