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
351ab64890Smrg
361ab64890Smrgstatic Status
37818534a1Smrg_XkbReadAtoms(XkbReadBufferPtr buf,
38818534a1Smrg              Atom *atoms,
39818534a1Smrg              int maxAtoms,
40818534a1Smrg              CARD32 present)
411ab64890Smrg{
42818534a1Smrg    register int i, bit;
431ab64890Smrg
44818534a1Smrg    for (i = 0, bit = 1; (i < maxAtoms) && (present); i++, bit <<= 1) {
45818534a1Smrg        if (present & bit) {
46818534a1Smrg            if (!_XkbReadBufferCopy32(buf, (long *) &atoms[i], 1))
47818534a1Smrg                return BadLength;
48818534a1Smrg            present &= ~bit;
49818534a1Smrg        }
501ab64890Smrg    }
511ab64890Smrg    return Success;
521ab64890Smrg}
531ab64890Smrg
541ab64890SmrgStatus
55818534a1Smrg_XkbReadGetNamesReply(Display *dpy,
56818534a1Smrg                      xkbGetNamesReply *rep,
57818534a1Smrg                      XkbDescPtr xkb,
58818534a1Smrg                      int *nread_rtrn)
591ab64890Smrg{
60818534a1Smrg    int i, len;
61818534a1Smrg    XkbReadBufferRec buf;
62818534a1Smrg    register XkbNamesPtr names;
631ab64890Smrg
64818534a1Smrg    if (xkb->device_spec == XkbUseCoreKbd)
65818534a1Smrg        xkb->device_spec = rep->deviceID;
661ab64890Smrg
67818534a1Smrg    if ((xkb->names == NULL) &&
68818534a1Smrg        (XkbAllocNames(xkb, rep->which,
69818534a1Smrg                       rep->nRadioGroups, rep->nKeyAliases) != Success)) {
70818534a1Smrg        return BadAlloc;
711ab64890Smrg    }
72818534a1Smrg    names = xkb->names;
73818534a1Smrg    if (rep->length == 0)
74818534a1Smrg        return Success;
751ab64890Smrg
76818534a1Smrg    if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4))
77818534a1Smrg        return BadAlloc;
781ab64890Smrg    if (nread_rtrn)
79818534a1Smrg        *nread_rtrn = (int) rep->length * 4;
80818534a1Smrg
81818534a1Smrg    if ((rep->which & XkbKeycodesNameMask) &&
82818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->keycodes, 1)))
83818534a1Smrg        goto BAILOUT;
84818534a1Smrg    if ((rep->which & XkbGeometryNameMask) &&
85818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->geometry, 1)))
86818534a1Smrg        goto BAILOUT;
87818534a1Smrg    if ((rep->which & XkbSymbolsNameMask) &&
88818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->symbols, 1)))
89818534a1Smrg        goto BAILOUT;
90818534a1Smrg    if ((rep->which & XkbPhysSymbolsNameMask) &&
91818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->phys_symbols, 1)))
92818534a1Smrg        goto BAILOUT;
93818534a1Smrg    if ((rep->which & XkbTypesNameMask) &&
94818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->types, 1)))
95818534a1Smrg        goto BAILOUT;
96818534a1Smrg    if ((rep->which & XkbCompatNameMask) &&
97818534a1Smrg        (!_XkbReadBufferCopy32(&buf, (long *) &names->compat, 1)))
98818534a1Smrg        goto BAILOUT;
99818534a1Smrg
100818534a1Smrg    if (rep->which & XkbKeyTypeNamesMask) {
101818534a1Smrg        XkbClientMapPtr map = xkb->map;
102818534a1Smrg        XkbKeyTypePtr type;
103818534a1Smrg
104818534a1Smrg        len = rep->nTypes * 4;
105818534a1Smrg        if (map != NULL) {
106818534a1Smrg            type = map->types;
107818534a1Smrg            for (i = 0; (i < map->num_types) && (i < rep->nTypes); i++, type++) {
108818534a1Smrg                if (!_XkbReadBufferCopy32(&buf, (long *) &type->name, 1))
109818534a1Smrg                    goto BAILOUT;
110818534a1Smrg                len -= 4;
111818534a1Smrg            }
112818534a1Smrg        }
113818534a1Smrg        if ((len > 0) && (!_XkbSkipReadBufferData(&buf, len)))
114818534a1Smrg            goto BAILOUT;
115818534a1Smrg    }
116818534a1Smrg    if (rep->which & XkbKTLevelNamesMask) {
117818534a1Smrg        CARD8 *nLevels;
118818534a1Smrg        XkbClientMapPtr map = xkb->map;
119818534a1Smrg
120818534a1Smrg        nLevels =
121818534a1Smrg            (CARD8 *) _XkbGetReadBufferPtr(&buf, XkbPaddedSize(rep->nTypes));
122818534a1Smrg        if (nLevels == NULL)
123818534a1Smrg            goto BAILOUT;
124818534a1Smrg        if (map != NULL) {
125818534a1Smrg            XkbKeyTypePtr type = map->types;
126818534a1Smrg
127818534a1Smrg            for (i = 0; i < (int) rep->nTypes; i++, type++) {
128818534a1Smrg                if (i >= map->num_types) {
129818534a1Smrg                    if (!_XkbSkipReadBufferData(&buf, nLevels[i] * 4))
130818534a1Smrg                        goto BAILOUT;
131818534a1Smrg                    continue;
132818534a1Smrg                }
133818534a1Smrg                if ((nLevels[i] > 0) && (nLevels[i] != type->num_levels)) {
134818534a1Smrg                    goto BAILOUT;
135818534a1Smrg                }
1360f8248bfSmrg
1370f8248bfSmrg                Xfree(type->level_names);
138818534a1Smrg                if (nLevels[i] == 0) {
139818534a1Smrg                    type->level_names = NULL;
140818534a1Smrg                    continue;
141818534a1Smrg                }
142818534a1Smrg                type->level_names = _XkbTypedCalloc(nLevels[i], Atom);
143818534a1Smrg                if (type->level_names != NULL) {
144818534a1Smrg                    if (!_XkbReadBufferCopy32(&buf, (long *) type->level_names,
145818534a1Smrg                                              nLevels[i]))
146818534a1Smrg                        goto BAILOUT;
147818534a1Smrg                }
148818534a1Smrg                else {
149818534a1Smrg                    _XkbSkipReadBufferData(&buf, nLevels[i] * 4);
150818534a1Smrg                }
151818534a1Smrg            }
152818534a1Smrg        }
153818534a1Smrg        else {
154818534a1Smrg            for (i = 0; i < (int) rep->nTypes; i++) {
155818534a1Smrg                _XkbSkipReadBufferData(&buf, nLevels[i] * 4);
156818534a1Smrg            }
157818534a1Smrg        }
1581ab64890Smrg    }
1591ab64890Smrg    if (rep->which & XkbIndicatorNamesMask) {
160818534a1Smrg        if (_XkbReadAtoms(&buf, names->indicators, XkbNumIndicators,
161818534a1Smrg                          rep->indicators) != Success)
162818534a1Smrg            goto BAILOUT;
163818534a1Smrg    }
164818534a1Smrg    if (rep->which & XkbVirtualModNamesMask) {
165818534a1Smrg        if (_XkbReadAtoms(&buf, names->vmods, XkbNumVirtualMods,
166818534a1Smrg                          (CARD32) rep->virtualMods) != Success)
167818534a1Smrg            goto BAILOUT;
168818534a1Smrg    }
169818534a1Smrg    if (rep->which & XkbGroupNamesMask) {
170818534a1Smrg        if (_XkbReadAtoms(&buf, names->groups, XkbNumKbdGroups,
171818534a1Smrg                          (CARD32) rep->groupNames) != Success)
172818534a1Smrg            goto BAILOUT;
173818534a1Smrg    }
174818534a1Smrg    if (rep->which & XkbKeyNamesMask) {
175818534a1Smrg        if (names->keys == NULL) {
176818534a1Smrg            int nKeys;
177818534a1Smrg
178818534a1Smrg            if (xkb->max_key_code == 0) {
179818534a1Smrg                xkb->min_key_code = rep->minKeyCode;
180818534a1Smrg                xkb->max_key_code = rep->maxKeyCode;
181818534a1Smrg            }
182818534a1Smrg            nKeys = xkb->max_key_code + 1;
183818534a1Smrg            names->keys = _XkbTypedCalloc(nKeys, XkbKeyNameRec);
184818534a1Smrg        }
185818534a1Smrg        if (((int) rep->firstKey + rep->nKeys) > xkb->max_key_code + 1)
186818534a1Smrg            goto BAILOUT;
187818534a1Smrg        if (names->keys != NULL) {
188818534a1Smrg            if (!_XkbCopyFromReadBuffer(&buf,
189818534a1Smrg                                        (char *) &names->keys[rep->firstKey],
190818534a1Smrg                                        rep->nKeys * XkbKeyNameLength))
191818534a1Smrg                goto BAILOUT;
1925efbdfc3Smrg            names->num_keys = rep->nKeys;
193818534a1Smrg        }
194818534a1Smrg        else
195818534a1Smrg            _XkbSkipReadBufferData(&buf, rep->nKeys * XkbKeyNameLength);
196818534a1Smrg    }
197818534a1Smrg    if (rep->which & XkbKeyAliasesMask && (rep->nKeyAliases > 0)) {
198818534a1Smrg        if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, rep->nKeyAliases) !=
199818534a1Smrg            Success)
200818534a1Smrg            goto BAILOUT;
201818534a1Smrg        if (!_XkbCopyFromReadBuffer(&buf, (char *) names->key_aliases,
202818534a1Smrg                                    rep->nKeyAliases * XkbKeyNameLength * 2))
203818534a1Smrg            goto BAILOUT;
204818534a1Smrg    }
205818534a1Smrg    if (rep->which & XkbRGNamesMask) {
206818534a1Smrg        if (rep->nRadioGroups > 0) {
207818534a1Smrg            Atom *rgNames;
208818534a1Smrg
209258a0ebeSmrg            if ((names->radio_groups == NULL) ||
210258a0ebeSmrg                (names->num_rg < rep->nRadioGroups)) {
211258a0ebeSmrg                _XkbResizeArray(names->radio_groups, names->num_rg,
212258a0ebeSmrg                                rep->nRadioGroups, Atom);
213818534a1Smrg            }
214818534a1Smrg            rgNames = names->radio_groups;
215818534a1Smrg            if (!rgNames) {
216258a0ebeSmrg                names->num_rg = 0;
217818534a1Smrg                goto BAILOUT;
218818534a1Smrg            }
219818534a1Smrg            if (!_XkbReadBufferCopy32
220818534a1Smrg                (&buf, (long *) rgNames, rep->nRadioGroups))
221818534a1Smrg                goto BAILOUT;
222818534a1Smrg            names->num_rg = rep->nRadioGroups;
223818534a1Smrg        }
224818534a1Smrg        else if (names->num_rg > 0) {
225818534a1Smrg            names->num_rg = 0;
226818534a1Smrg            Xfree(names->radio_groups);
227818534a1Smrg        }
228818534a1Smrg    }
229818534a1Smrg    len = _XkbFreeReadBuffer(&buf);
230818534a1Smrg    if (len != 0)
231818534a1Smrg        return BadLength;
232818534a1Smrg    else
233818534a1Smrg        return Success;
234818534a1Smrg BAILOUT:
2351ab64890Smrg    _XkbFreeReadBuffer(&buf);
2361ab64890Smrg    return BadLength;
2371ab64890Smrg}
2381ab64890Smrg
2391ab64890SmrgStatus
240818534a1SmrgXkbGetNames(Display *dpy, unsigned which, XkbDescPtr xkb)
2411ab64890Smrg{
2421ab64890Smrg    register xkbGetNamesReq *req;
243818534a1Smrg    xkbGetNamesReply rep;
244818534a1Smrg    Status status;
2451ab64890Smrg    XkbInfoPtr xkbi;
2461ab64890Smrg
2471ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
248818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
249818534a1Smrg        return BadAccess;
2501ab64890Smrg    LockDisplay(dpy);
2511ab64890Smrg    xkbi = dpy->xkb_info;
2521ab64890Smrg    if (!xkb->names) {
253818534a1Smrg        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
254818534a1Smrg        if (!xkb->names) {
255818534a1Smrg            UnlockDisplay(dpy);
256818534a1Smrg            SyncHandle();
257818534a1Smrg            return BadAlloc;
258818534a1Smrg        }
2591ab64890Smrg    }
2601ab64890Smrg    GetReq(kbGetNames, req);
2611ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
2621ab64890Smrg    req->xkbReqType = X_kbGetNames;
2631ab64890Smrg    req->deviceSpec = xkb->device_spec;
2641ab64890Smrg    req->which = which;
265818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
266818534a1Smrg        UnlockDisplay(dpy);
267818534a1Smrg        SyncHandle();
268818534a1Smrg        return BadImplementation;
2691ab64890Smrg    }
2701ab64890Smrg
271818534a1Smrg    status = _XkbReadGetNamesReply(dpy, &rep, xkb, NULL);
2721ab64890Smrg    UnlockDisplay(dpy);
2731ab64890Smrg    SyncHandle();
2741ab64890Smrg    return status;
2751ab64890Smrg}
2761ab64890Smrg
2771ab64890Smrg/***====================================================================***/
2781ab64890Smrg
2791ab64890Smrgstatic int
280818534a1Smrg_XkbCountBits(int nBitsMax, unsigned long mask)
2811ab64890Smrg{
282818534a1Smrg    register unsigned long y, nBits;
2831ab64890Smrg
284818534a1Smrg    y = (mask >> 1) & 033333333333;
285818534a1Smrg    y = mask - y - ((y >> 1) & 033333333333);
2861ab64890Smrg    nBits = ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077));
2871ab64890Smrg
2881ab64890Smrg    /* nBitsMax really means max+1 */
2891ab64890Smrg    return (nBits < nBitsMax) ? nBits : (nBitsMax - 1);
2901ab64890Smrg}
2911ab64890Smrg
2921ab64890Smrgstatic CARD32
293818534a1Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
2941ab64890Smrg{
295818534a1Smrg    register unsigned int i, bit, nAtoms;
296818534a1Smrg    register CARD32 atomsPresent;
2971ab64890Smrg
298818534a1Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
299818534a1Smrg        if (atoms[i] != None) {
300818534a1Smrg            atomsPresent |= bit;
3011ab64890Smrg            nAtoms++;
3021ab64890Smrg        }
3031ab64890Smrg    }
3041ab64890Smrg    if (count)
305818534a1Smrg        *count = nAtoms;
3061ab64890Smrg    return atomsPresent;
3071ab64890Smrg}
3081ab64890Smrg
3091ab64890Smrgstatic void
310818534a1Smrg_XkbCopyAtoms(Display *dpy, Atom *atoms, CARD32 mask, int maxAtoms)
3111ab64890Smrg{
312818534a1Smrg    register unsigned int i, bit;
3131ab64890Smrg
314818534a1Smrg    for (i = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
315818534a1Smrg        if (mask & bit)
316818534a1Smrg            Data32(dpy, &atoms[i], 4);
3171ab64890Smrg    }
3181ab64890Smrg    return;
3191ab64890Smrg}
3201ab64890Smrg
3211ab64890SmrgBool
322818534a1SmrgXkbSetNames(Display *dpy,
323818534a1Smrg            unsigned int which,
324818534a1Smrg            unsigned int firstType,
325818534a1Smrg            unsigned int nTypes,
326818534a1Smrg            XkbDescPtr xkb)
3271ab64890Smrg{
3281ab64890Smrg    register xkbSetNamesReq *req;
329818534a1Smrg    int nLvlNames = 0;
3301ab64890Smrg    XkbInfoPtr xkbi;
3311ab64890Smrg    XkbNamesPtr names;
332818534a1Smrg    unsigned firstLvlType, nLvlTypes;
333818534a1Smrg    int nVMods, nLEDs, nRG, nKA, nGroups;
334818534a1Smrg    int nKeys = 0, firstKey = 0, nAtoms;
335818534a1Smrg    CARD32 leds, vmods, groups;
3361ab64890Smrg
3371ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
338818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
339818534a1Smrg        return False;
340818534a1Smrg    if ((!xkb) || (!xkb->names))
341818534a1Smrg        return False;
342818534a1Smrg    firstLvlType = firstType;
343818534a1Smrg    nLvlTypes = nTypes;
344818534a1Smrg    if (nTypes < 1)
345818534a1Smrg        which &= ~(XkbKTLevelNamesMask | XkbKeyTypeNamesMask);
346818534a1Smrg    else if (firstType <= XkbLastRequiredType) {
347818534a1Smrg        int adjust;
348818534a1Smrg
349818534a1Smrg        adjust = XkbLastRequiredType - firstType + 1;
350818534a1Smrg        firstType += adjust;
351818534a1Smrg        nTypes -= adjust;
352818534a1Smrg        if (nTypes < 1)
353818534a1Smrg            which &= ~XkbKeyTypeNamesMask;
354818534a1Smrg    }
355818534a1Smrg    names = xkb->names;
356818534a1Smrg    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
357818534a1Smrg        register int i;
358818534a1Smrg        XkbKeyTypePtr type;
359818534a1Smrg
360818534a1Smrg        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
361818534a1Smrg            (firstType + nTypes > xkb->map->num_types) ||
362818534a1Smrg            (firstLvlType + nLvlTypes > xkb->map->num_types))
363818534a1Smrg            return False;
364818534a1Smrg        if (which & XkbKTLevelNamesMask) {
365818534a1Smrg            type = &xkb->map->types[firstLvlType];
366818534a1Smrg            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
367818534a1Smrg                if (type->level_names != NULL)
368818534a1Smrg                    nLvlNames += type->num_levels;
369818534a1Smrg            }
370818534a1Smrg        }
371818534a1Smrg    }
372818534a1Smrg
373818534a1Smrg    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
3741ab64890Smrg    LockDisplay(dpy);
3751ab64890Smrg    xkbi = dpy->xkb_info;
3761ab64890Smrg    GetReq(kbSetNames, req);
3771ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
3781ab64890Smrg    req->xkbReqType = X_kbSetNames;
3791ab64890Smrg    req->deviceSpec = xkb->device_spec;
3801ab64890Smrg    req->firstType = firstType;
3811ab64890Smrg    req->nTypes = nTypes;
3821ab64890Smrg    req->firstKey = xkb->min_key_code;
383818534a1Smrg    req->nKeys = xkb->max_key_code - xkb->min_key_code + 1;
384818534a1Smrg
385818534a1Smrg    if (which & XkbKeycodesNameMask)
386818534a1Smrg        nAtoms++;
387818534a1Smrg    if (which & XkbGeometryNameMask)
388818534a1Smrg        nAtoms++;
389818534a1Smrg    if (which & XkbSymbolsNameMask)
390818534a1Smrg        nAtoms++;
391818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
392818534a1Smrg        nAtoms++;
393818534a1Smrg    if (which & XkbTypesNameMask)
394818534a1Smrg        nAtoms++;
395818534a1Smrg    if (which & XkbCompatNameMask)
396818534a1Smrg        nAtoms++;
397818534a1Smrg    if (which & XkbKeyTypeNamesMask)
398818534a1Smrg        nAtoms += nTypes;
399818534a1Smrg    if (which & XkbKTLevelNamesMask) {
400818534a1Smrg        req->firstKTLevel = firstLvlType;
401818534a1Smrg        req->nKTLevels = nLvlTypes;
402818534a1Smrg        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
403818534a1Smrg        nAtoms += nLvlNames;
404818534a1Smrg    }
405818534a1Smrg    else
406818534a1Smrg        req->firstKTLevel = req->nKTLevels = 0;
407818534a1Smrg
408818534a1Smrg    if (which & XkbIndicatorNamesMask) {
409818534a1Smrg        req->indicators = leds =
410818534a1Smrg            _XkbCountAtoms(names->indicators, XkbNumIndicators, &nLEDs);
411818534a1Smrg        if (nLEDs > 0)
412818534a1Smrg            nAtoms += nLEDs;
413818534a1Smrg        else
414818534a1Smrg            which &= ~XkbIndicatorNamesMask;
415818534a1Smrg    }
416818534a1Smrg    else
417818534a1Smrg        req->indicators = leds = 0;
418818534a1Smrg
419818534a1Smrg    if (which & XkbVirtualModNamesMask) {
420818534a1Smrg        vmods = req->virtualMods = (CARD16)
421818534a1Smrg            _XkbCountAtoms(names->vmods, XkbNumVirtualMods, &nVMods);
422818534a1Smrg        if (nVMods > 0)
423818534a1Smrg            nAtoms += nVMods;
424818534a1Smrg        else
425818534a1Smrg            which &= ~XkbVirtualModNamesMask;
426818534a1Smrg    }
427818534a1Smrg    else
428818534a1Smrg        vmods = req->virtualMods = 0;
429818534a1Smrg
430818534a1Smrg    if (which & XkbGroupNamesMask) {
431818534a1Smrg        groups = req->groupNames = (CARD8)
432818534a1Smrg            _XkbCountAtoms(names->groups, XkbNumKbdGroups, &nGroups);
433818534a1Smrg        if (nGroups > 0)
434818534a1Smrg            nAtoms += nGroups;
435818534a1Smrg        else
436818534a1Smrg            which &= ~XkbGroupNamesMask;
437818534a1Smrg    }
438818534a1Smrg    else
439818534a1Smrg        groups = req->groupNames = 0;
440818534a1Smrg
441818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
442818534a1Smrg        firstKey = req->firstKey;
443818534a1Smrg        nKeys = req->nKeys;
444818534a1Smrg        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
445818534a1Smrg    }
446818534a1Smrg    else
447818534a1Smrg        which &= ~XkbKeyNamesMask;
448818534a1Smrg
449818534a1Smrg    if (which & XkbKeyAliasesMask) {
450818534a1Smrg        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
451818534a1Smrg        if (nKA > 0) {
452818534a1Smrg            req->nKeyAliases = nKA;
453818534a1Smrg            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
454818534a1Smrg        }
455818534a1Smrg        else {
456818534a1Smrg            which &= ~XkbKeyAliasesMask;
457818534a1Smrg            req->nKeyAliases = 0;
458818534a1Smrg        }
459818534a1Smrg    }
460818534a1Smrg    else
461818534a1Smrg        req->nKeyAliases = 0;
462818534a1Smrg
463818534a1Smrg    if (which & XkbRGNamesMask) {
464818534a1Smrg        nRG = names->num_rg;
465818534a1Smrg        if (nRG > 0)
466818534a1Smrg            nAtoms += nRG;
467818534a1Smrg        else
468818534a1Smrg            which &= ~XkbRGNamesMask;
469818534a1Smrg    }
470818534a1Smrg
471818534a1Smrg    req->which = which;
472818534a1Smrg    req->nRadioGroups = nRG;
473818534a1Smrg    req->length += (nAtoms * 4) / 4;
474818534a1Smrg
475818534a1Smrg    if (which & XkbKeycodesNameMask)
476818534a1Smrg        Data32(dpy, (long *) &names->keycodes, 4);
477818534a1Smrg    if (which & XkbGeometryNameMask)
478818534a1Smrg        Data32(dpy, (long *) &names->geometry, 4);
479818534a1Smrg    if (which & XkbSymbolsNameMask)
480818534a1Smrg        Data32(dpy, (long *) &names->symbols, 4);
481818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
482818534a1Smrg        Data32(dpy, (long *) &names->phys_symbols, 4);
483818534a1Smrg    if (which & XkbTypesNameMask)
484818534a1Smrg        Data32(dpy, (long *) &names->types, 4);
485818534a1Smrg    if (which & XkbCompatNameMask)
486818534a1Smrg        Data32(dpy, (long *) &names->compat, 4);
487818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
488818534a1Smrg        register int i;
489818534a1Smrg        register XkbKeyTypePtr type;
490818534a1Smrg
491818534a1Smrg        type = &xkb->map->types[firstType];
492818534a1Smrg        for (i = 0; i < nTypes; i++, type++) {
493818534a1Smrg            Data32(dpy, (long *) &type->name, 4);
494818534a1Smrg        }
495818534a1Smrg    }
496818534a1Smrg    if (which & XkbKTLevelNamesMask) {
497818534a1Smrg        XkbKeyTypePtr type;
498818534a1Smrg        int i;
499818534a1Smrg        char *tmp;
500818534a1Smrg
501818534a1Smrg        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
502818534a1Smrg        type = &xkb->map->types[firstLvlType];
503818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
504818534a1Smrg            *tmp++ = type->num_levels;
505818534a1Smrg        }
506818534a1Smrg        type = &xkb->map->types[firstLvlType];
507818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
508818534a1Smrg            if (type->level_names != NULL)
509818534a1Smrg                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
510818534a1Smrg        }
511818534a1Smrg    }
512818534a1Smrg    if (which & XkbIndicatorNamesMask)
513818534a1Smrg        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
514818534a1Smrg    if (which & XkbVirtualModNamesMask)
515818534a1Smrg        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
516818534a1Smrg    if (which & XkbGroupNamesMask)
517818534a1Smrg        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
518818534a1Smrg    if (which & XkbKeyNamesMask) {
519818534a1Smrg        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
520818534a1Smrg    }
521818534a1Smrg    if (which & XkbKeyAliasesMask) {
522818534a1Smrg        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
523818534a1Smrg    }
524818534a1Smrg    if (which & XkbRGNamesMask) {
525818534a1Smrg        Data32(dpy, (long *) names->radio_groups, nRG * 4);
5261ab64890Smrg    }
5271ab64890Smrg    UnlockDisplay(dpy);
5281ab64890Smrg    SyncHandle();
5291ab64890Smrg    return True;
5301ab64890Smrg}
5311ab64890Smrg
5321ab64890SmrgBool
533818534a1SmrgXkbChangeNames(Display *dpy, XkbDescPtr xkb, XkbNameChangesPtr changes)
5341ab64890Smrg{
5351ab64890Smrg    register xkbSetNamesReq *req;
536818534a1Smrg    int nLvlNames = 0;
5371ab64890Smrg    XkbInfoPtr xkbi;
5381ab64890Smrg    XkbNamesPtr names;
539818534a1Smrg    unsigned which, firstType, nTypes;
540818534a1Smrg    unsigned firstLvlType, nLvlTypes;
541818534a1Smrg    int nVMods, nLEDs, nRG, nKA, nGroups;
542818534a1Smrg    int nKeys = 0, firstKey = 0, nAtoms;
543818534a1Smrg    CARD32 leds = 0, vmods = 0, groups = 0;
5441ab64890Smrg
5451ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
546818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
547818534a1Smrg        return False;
548818534a1Smrg    if ((!xkb) || (!xkb->names) || (!changes))
549818534a1Smrg        return False;
550818534a1Smrg    which = changes->changed;
551818534a1Smrg    firstType = changes->first_type;
552818534a1Smrg    nTypes = changes->num_types;
5532d67cb4fSmrg    firstLvlType = changes->first_lvl;
554818534a1Smrg    nLvlTypes = changes->num_lvls;
555818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
556818534a1Smrg        if (nTypes < 1)
557818534a1Smrg            which &= ~XkbKeyTypeNamesMask;
558818534a1Smrg        else if (firstType <= XkbLastRequiredType) {
559818534a1Smrg            int adjust;
560818534a1Smrg
561818534a1Smrg            adjust = XkbLastRequiredType - firstType + 1;
562818534a1Smrg            firstType += adjust;
563818534a1Smrg            nTypes -= adjust;
564818534a1Smrg            if (nTypes < 1)
565818534a1Smrg                which &= ~XkbKeyTypeNamesMask;
566818534a1Smrg        }
567818534a1Smrg    }
568818534a1Smrg    else
569818534a1Smrg        firstType = nTypes = 0;
570818534a1Smrg
571818534a1Smrg    if (which & XkbKTLevelNamesMask) {
572818534a1Smrg        if (nLvlTypes < 1)
573818534a1Smrg            which &= ~XkbKTLevelNamesMask;
574818534a1Smrg    }
575818534a1Smrg    else
576818534a1Smrg        firstLvlType = nLvlTypes = 0;
577818534a1Smrg
578818534a1Smrg    names = xkb->names;
579818534a1Smrg    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
580818534a1Smrg        register int i;
581818534a1Smrg
582818534a1Smrg        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
583818534a1Smrg            (firstType + nTypes > xkb->map->num_types) ||
584818534a1Smrg            (firstLvlType + nLvlTypes > xkb->map->num_types))
585818534a1Smrg            return False;
586818534a1Smrg        if (which & XkbKTLevelNamesMask) {
587818534a1Smrg            XkbKeyTypePtr type = &xkb->map->types[firstLvlType];
588818534a1Smrg
589818534a1Smrg            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
590818534a1Smrg                if (type->level_names != NULL)
591818534a1Smrg                    nLvlNames += type->num_levels;
592818534a1Smrg            }
593818534a1Smrg        }
594818534a1Smrg    }
595818534a1Smrg
596818534a1Smrg    if (changes->num_keys < 1)
597818534a1Smrg        which &= ~XkbKeyNamesMask;
598818534a1Smrg    if ((which & XkbKeyNamesMask) == 0)
599818534a1Smrg        changes->first_key = changes->num_keys = 0;
600818534a1Smrg    else if ((changes->first_key < xkb->min_key_code) ||
601818534a1Smrg             (changes->first_key + changes->num_keys > xkb->max_key_code)) {
602818534a1Smrg        return False;
603818534a1Smrg    }
604818534a1Smrg
605818534a1Smrg    if ((which & XkbVirtualModNamesMask) == 0)
606818534a1Smrg        changes->changed_vmods = 0;
607818534a1Smrg    else if (changes->changed_vmods == 0)
608818534a1Smrg        which &= ~XkbVirtualModNamesMask;
609818534a1Smrg
610818534a1Smrg    if ((which & XkbIndicatorNamesMask) == 0)
611818534a1Smrg        changes->changed_indicators = 0;
612818534a1Smrg    else if (changes->changed_indicators == 0)
613818534a1Smrg        which &= ~XkbIndicatorNamesMask;
614818534a1Smrg
615818534a1Smrg    if ((which & XkbGroupNamesMask) == 0)
616818534a1Smrg        changes->changed_groups = 0;
617818534a1Smrg    else if (changes->changed_groups == 0)
618818534a1Smrg        which &= ~XkbGroupNamesMask;
619818534a1Smrg
620818534a1Smrg    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
6211ab64890Smrg    LockDisplay(dpy);
6221ab64890Smrg    xkbi = dpy->xkb_info;
6231ab64890Smrg    GetReq(kbSetNames, req);
6241ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
6251ab64890Smrg    req->xkbReqType = X_kbSetNames;
6261ab64890Smrg    req->deviceSpec = xkb->device_spec;
6271ab64890Smrg    req->firstType = firstType;
6281ab64890Smrg    req->nTypes = nTypes;
6291ab64890Smrg    req->firstKey = changes->first_key;
6301ab64890Smrg    req->nKeys = changes->num_keys;
6311ab64890Smrg
632818534a1Smrg    if (which & XkbKeycodesNameMask)
633818534a1Smrg        nAtoms++;
634818534a1Smrg    if (which & XkbGeometryNameMask)
635818534a1Smrg        nAtoms++;
636818534a1Smrg    if (which & XkbSymbolsNameMask)
637818534a1Smrg        nAtoms++;
638818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
639818534a1Smrg        nAtoms++;
640818534a1Smrg    if (which & XkbTypesNameMask)
641818534a1Smrg        nAtoms++;
642818534a1Smrg    if (which & XkbCompatNameMask)
643818534a1Smrg        nAtoms++;
644818534a1Smrg    if (which & XkbKeyTypeNamesMask)
645818534a1Smrg        nAtoms += nTypes;
646818534a1Smrg    if (which & XkbKTLevelNamesMask) {
647818534a1Smrg        req->firstKTLevel = firstLvlType;
648818534a1Smrg        req->nKTLevels = nLvlTypes;
649818534a1Smrg        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
650818534a1Smrg        nAtoms += nLvlNames;
651818534a1Smrg    }
652818534a1Smrg    else
653818534a1Smrg        req->firstKTLevel = req->nKTLevels = 0;
654818534a1Smrg
655818534a1Smrg    if (which & XkbIndicatorNamesMask) {
656818534a1Smrg        leds = req->indicators = (CARD32) changes->changed_indicators;
657818534a1Smrg        nLEDs = _XkbCountBits(XkbNumIndicators, changes->changed_indicators);
658818534a1Smrg        if (nLEDs > 0)
659818534a1Smrg            nAtoms += nLEDs;
660818534a1Smrg        else
661818534a1Smrg            which &= ~XkbIndicatorNamesMask;
662818534a1Smrg    }
663818534a1Smrg    else
664818534a1Smrg        req->indicators = 0;
665818534a1Smrg
666818534a1Smrg    if (which & XkbVirtualModNamesMask) {
667818534a1Smrg        vmods = req->virtualMods = changes->changed_vmods;
668818534a1Smrg        nVMods = _XkbCountBits(XkbNumVirtualMods,
669818534a1Smrg                               (unsigned long) changes->changed_vmods);
670818534a1Smrg        if (nVMods > 0)
671818534a1Smrg            nAtoms += nVMods;
672818534a1Smrg        else
673818534a1Smrg            which &= ~XkbVirtualModNamesMask;
674818534a1Smrg    }
675818534a1Smrg    else
676818534a1Smrg        req->virtualMods = 0;
677818534a1Smrg
678818534a1Smrg    if (which & XkbGroupNamesMask) {
679818534a1Smrg        groups = req->groupNames = changes->changed_groups;
680818534a1Smrg        nGroups = _XkbCountBits(XkbNumKbdGroups,
681818534a1Smrg                                (unsigned long) changes->changed_groups);
682818534a1Smrg        if (nGroups > 0)
683818534a1Smrg            nAtoms += nGroups;
684818534a1Smrg        else
685818534a1Smrg            which &= ~XkbGroupNamesMask;
686818534a1Smrg    }
687818534a1Smrg    else
688818534a1Smrg        req->groupNames = 0;
689818534a1Smrg
690818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
691818534a1Smrg        firstKey = req->firstKey;
692818534a1Smrg        nKeys = req->nKeys;
693818534a1Smrg        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
694818534a1Smrg    }
695818534a1Smrg    else
696818534a1Smrg        which &= ~XkbKeyNamesMask;
697818534a1Smrg
698818534a1Smrg    if (which & XkbKeyAliasesMask) {
699818534a1Smrg        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
700818534a1Smrg        if (nKA > 0)
701818534a1Smrg            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
702818534a1Smrg        else
703818534a1Smrg            which &= ~XkbKeyAliasesMask;
704818534a1Smrg    }
705818534a1Smrg
706818534a1Smrg    if (which & XkbRGNamesMask) {
707818534a1Smrg        nRG = names->num_rg;
708818534a1Smrg        if (nRG > 0)
709818534a1Smrg            nAtoms += nRG;
710818534a1Smrg        else
711818534a1Smrg            which &= ~XkbRGNamesMask;
712818534a1Smrg    }
713818534a1Smrg
714818534a1Smrg    req->which = which;
715818534a1Smrg    req->nRadioGroups = nRG;
716818534a1Smrg    req->length += (nAtoms * 4) / 4;
717818534a1Smrg
718818534a1Smrg    if (which & XkbKeycodesNameMask)
719818534a1Smrg        Data32(dpy, (long *) &names->keycodes, 4);
720818534a1Smrg    if (which & XkbGeometryNameMask)
721818534a1Smrg        Data32(dpy, (long *) &names->geometry, 4);
722818534a1Smrg    if (which & XkbSymbolsNameMask)
723818534a1Smrg        Data32(dpy, (long *) &names->symbols, 4);
724818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
725818534a1Smrg        Data32(dpy, (long *) &names->phys_symbols, 4);
726818534a1Smrg    if (which & XkbTypesNameMask)
727818534a1Smrg        Data32(dpy, (long *) &names->types, 4);
728818534a1Smrg    if (which & XkbCompatNameMask)
729818534a1Smrg        Data32(dpy, (long *) &names->compat, 4);
730818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
731818534a1Smrg        register int i;
732818534a1Smrg        register XkbKeyTypePtr type;
733818534a1Smrg
734818534a1Smrg        type = &xkb->map->types[firstType];
735818534a1Smrg        for (i = 0; i < nTypes; i++, type++) {
736818534a1Smrg            Data32(dpy, (long *) &type->name, 4);
737818534a1Smrg        }
738818534a1Smrg    }
739818534a1Smrg    if (which & XkbKTLevelNamesMask) {
740818534a1Smrg        XkbKeyTypePtr type;
741818534a1Smrg        int i;
742818534a1Smrg        char *tmp;
743818534a1Smrg
744818534a1Smrg        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
745818534a1Smrg        type = &xkb->map->types[firstLvlType];
746818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
747818534a1Smrg            *tmp++ = type->num_levels;
748818534a1Smrg        }
749818534a1Smrg        type = &xkb->map->types[firstLvlType];
750818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
751818534a1Smrg            if (type->level_names != NULL)
752818534a1Smrg                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
753818534a1Smrg        }
754818534a1Smrg    }
755818534a1Smrg    if (which & XkbIndicatorNamesMask)
756818534a1Smrg        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
757818534a1Smrg    if (which & XkbVirtualModNamesMask)
758818534a1Smrg        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
759818534a1Smrg    if (which & XkbGroupNamesMask)
760818534a1Smrg        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
761818534a1Smrg    if (which & XkbKeyNamesMask) {
762818534a1Smrg        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
763818534a1Smrg    }
764818534a1Smrg    if (which & XkbKeyAliasesMask) {
765818534a1Smrg        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
766818534a1Smrg    }
767818534a1Smrg    if (which & XkbRGNamesMask) {
768818534a1Smrg        Data32(dpy, (long *) names->radio_groups, nRG * 4);
7691ab64890Smrg    }
7701ab64890Smrg    UnlockDisplay(dpy);
7711ab64890Smrg    SyncHandle();
7721ab64890Smrg    return True;
7731ab64890Smrg}
7741ab64890Smrg
7751ab64890Smrgvoid
776818534a1SmrgXkbNoteNameChanges(XkbNameChangesPtr old,
777818534a1Smrg                   XkbNamesNotifyEvent *new,
778818534a1Smrg                   unsigned int wanted)
7791ab64890Smrg{
780818534a1Smrg    int first, last, old_last, new_last;
781818534a1Smrg
7820f8248bfSmrg    if ((old == NULL) || (new == NULL))
783818534a1Smrg        return;
7840f8248bfSmrg
7850f8248bfSmrg    wanted &= new->changed;
7860f8248bfSmrg
7870f8248bfSmrg    if (wanted == 0)
7880f8248bfSmrg	return;
7890f8248bfSmrg
790818534a1Smrg    if (wanted & XkbKeyTypeNamesMask) {
791818534a1Smrg        if (old->changed & XkbKeyTypeNamesMask) {
792818534a1Smrg            new_last = (new->first_type + new->num_types - 1);
793818534a1Smrg            old_last = (old->first_type + old->num_types - 1);
794818534a1Smrg
795818534a1Smrg            if (new->first_type < old->first_type)
796818534a1Smrg                first = new->first_type;
797818534a1Smrg            else
798818534a1Smrg                first = old->first_type;
799818534a1Smrg
800818534a1Smrg            if (old_last > new_last)
801818534a1Smrg                last = old_last;
802818534a1Smrg            else
803818534a1Smrg                last = new_last;
804818534a1Smrg
805818534a1Smrg            old->first_type = first;
806818534a1Smrg            old->num_types = (last - first) + 1;
807818534a1Smrg        }
808818534a1Smrg        else {
809818534a1Smrg            old->first_type = new->first_type;
810818534a1Smrg            old->num_types = new->num_types;
811818534a1Smrg        }
812818534a1Smrg    }
813818534a1Smrg    if (wanted & XkbKTLevelNamesMask) {
814818534a1Smrg        if (old->changed & XkbKTLevelNamesMask) {
815818534a1Smrg            new_last = (new->first_lvl + new->num_lvls - 1);
816818534a1Smrg            old_last = (old->first_lvl + old->num_lvls - 1);
817818534a1Smrg
818818534a1Smrg            if (new->first_lvl < old->first_lvl)
819818534a1Smrg                first = new->first_lvl;
820818534a1Smrg            else
821818534a1Smrg                first = old->first_lvl;
822818534a1Smrg
823818534a1Smrg            if (old_last > new_last)
824818534a1Smrg                last = old_last;
825818534a1Smrg            else
826818534a1Smrg                last = new_last;
827818534a1Smrg
828818534a1Smrg            old->first_lvl = first;
829818534a1Smrg            old->num_lvls = (last - first) + 1;
830818534a1Smrg        }
831818534a1Smrg        else {
832818534a1Smrg            old->first_lvl = new->first_lvl;
833818534a1Smrg            old->num_lvls = new->num_lvls;
834818534a1Smrg        }
835818534a1Smrg    }
836818534a1Smrg    if (wanted & XkbIndicatorNamesMask) {
837818534a1Smrg        if (old->changed & XkbIndicatorNamesMask)
838818534a1Smrg            old->changed_indicators |= new->changed_indicators;
839818534a1Smrg        else
840818534a1Smrg            old->changed_indicators = new->changed_indicators;
841818534a1Smrg    }
842818534a1Smrg    if (wanted & XkbKeyNamesMask) {
843818534a1Smrg        if (old->changed & XkbKeyNamesMask) {
844818534a1Smrg            new_last = (new->first_key + new->num_keys - 1);
845818534a1Smrg            old_last = (old->first_key + old->num_keys - 1);
846818534a1Smrg
847818534a1Smrg            first = old->first_key;
848818534a1Smrg
849818534a1Smrg            if (new->first_key < old->first_key)
850818534a1Smrg                first = new->first_key;
851818534a1Smrg            if (old_last > new_last)
852818534a1Smrg                new_last = old_last;
853818534a1Smrg
854818534a1Smrg            old->first_key = first;
855818534a1Smrg            old->num_keys = (new_last - first) + 1;
856818534a1Smrg        }
857818534a1Smrg        else {
858818534a1Smrg            old->first_key = new->first_key;
859818534a1Smrg            old->num_keys = new->num_keys;
860818534a1Smrg        }
861818534a1Smrg    }
862818534a1Smrg    if (wanted & XkbVirtualModNamesMask) {
863818534a1Smrg        if (old->changed & XkbVirtualModNamesMask)
864818534a1Smrg            old->changed_vmods |= new->changed_vmods;
865818534a1Smrg        else
866818534a1Smrg            old->changed_vmods = new->changed_vmods;
867818534a1Smrg    }
868818534a1Smrg    if (wanted & XkbGroupNamesMask) {
869818534a1Smrg        if (old->changed & XkbGroupNamesMask)
870818534a1Smrg            old->changed_groups |= new->changed_groups;
871818534a1Smrg        else
872818534a1Smrg            old->changed_groups = new->changed_groups;
873818534a1Smrg    }
874818534a1Smrg    if (wanted & XkbRGNamesMask)
875818534a1Smrg        old->num_rg = new->num_radio_groups;
876818534a1Smrg    if (wanted & XkbKeyAliasesMask)
877818534a1Smrg        old->num_aliases = new->num_aliases;
878818534a1Smrg    old->changed |= wanted;
8791ab64890Smrg    return;
8801ab64890Smrg}
881