XKBNames.c revision 258a0ebe
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;
192818534a1Smrg        }
193818534a1Smrg        else
194818534a1Smrg            _XkbSkipReadBufferData(&buf, rep->nKeys * XkbKeyNameLength);
195818534a1Smrg    }
196818534a1Smrg    if (rep->which & XkbKeyAliasesMask && (rep->nKeyAliases > 0)) {
197818534a1Smrg        if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, rep->nKeyAliases) !=
198818534a1Smrg            Success)
199818534a1Smrg            goto BAILOUT;
200818534a1Smrg        if (!_XkbCopyFromReadBuffer(&buf, (char *) names->key_aliases,
201818534a1Smrg                                    rep->nKeyAliases * XkbKeyNameLength * 2))
202818534a1Smrg            goto BAILOUT;
203818534a1Smrg    }
204818534a1Smrg    if (rep->which & XkbRGNamesMask) {
205818534a1Smrg        if (rep->nRadioGroups > 0) {
206818534a1Smrg            Atom *rgNames;
207818534a1Smrg
208258a0ebeSmrg            if ((names->radio_groups == NULL) ||
209258a0ebeSmrg                (names->num_rg < rep->nRadioGroups)) {
210258a0ebeSmrg                _XkbResizeArray(names->radio_groups, names->num_rg,
211258a0ebeSmrg                                rep->nRadioGroups, Atom);
212818534a1Smrg            }
213818534a1Smrg            rgNames = names->radio_groups;
214818534a1Smrg            if (!rgNames) {
215258a0ebeSmrg                names->num_rg = 0;
216818534a1Smrg                goto BAILOUT;
217818534a1Smrg            }
218818534a1Smrg            if (!_XkbReadBufferCopy32
219818534a1Smrg                (&buf, (long *) rgNames, rep->nRadioGroups))
220818534a1Smrg                goto BAILOUT;
221818534a1Smrg            names->num_rg = rep->nRadioGroups;
222818534a1Smrg        }
223818534a1Smrg        else if (names->num_rg > 0) {
224818534a1Smrg            names->num_rg = 0;
225818534a1Smrg            Xfree(names->radio_groups);
226818534a1Smrg        }
227818534a1Smrg    }
228818534a1Smrg    len = _XkbFreeReadBuffer(&buf);
229818534a1Smrg    if (len != 0)
230818534a1Smrg        return BadLength;
231818534a1Smrg    else
232818534a1Smrg        return Success;
233818534a1Smrg BAILOUT:
2341ab64890Smrg    _XkbFreeReadBuffer(&buf);
2351ab64890Smrg    return BadLength;
2361ab64890Smrg}
2371ab64890Smrg
2381ab64890SmrgStatus
239818534a1SmrgXkbGetNames(Display *dpy, unsigned which, XkbDescPtr xkb)
2401ab64890Smrg{
2411ab64890Smrg    register xkbGetNamesReq *req;
242818534a1Smrg    xkbGetNamesReply rep;
243818534a1Smrg    Status status;
2441ab64890Smrg    XkbInfoPtr xkbi;
2451ab64890Smrg
2461ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
247818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
248818534a1Smrg        return BadAccess;
2491ab64890Smrg    LockDisplay(dpy);
2501ab64890Smrg    xkbi = dpy->xkb_info;
2511ab64890Smrg    if (!xkb->names) {
252818534a1Smrg        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
253818534a1Smrg        if (!xkb->names) {
254818534a1Smrg            UnlockDisplay(dpy);
255818534a1Smrg            SyncHandle();
256818534a1Smrg            return BadAlloc;
257818534a1Smrg        }
2581ab64890Smrg    }
2591ab64890Smrg    GetReq(kbGetNames, req);
2601ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
2611ab64890Smrg    req->xkbReqType = X_kbGetNames;
2621ab64890Smrg    req->deviceSpec = xkb->device_spec;
2631ab64890Smrg    req->which = which;
264818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
265818534a1Smrg        UnlockDisplay(dpy);
266818534a1Smrg        SyncHandle();
267818534a1Smrg        return BadImplementation;
2681ab64890Smrg    }
2691ab64890Smrg
270818534a1Smrg    status = _XkbReadGetNamesReply(dpy, &rep, xkb, NULL);
2711ab64890Smrg    UnlockDisplay(dpy);
2721ab64890Smrg    SyncHandle();
2731ab64890Smrg    return status;
2741ab64890Smrg}
2751ab64890Smrg
2761ab64890Smrg/***====================================================================***/
2771ab64890Smrg
2781ab64890Smrgstatic int
279818534a1Smrg_XkbCountBits(int nBitsMax, unsigned long mask)
2801ab64890Smrg{
281818534a1Smrg    register unsigned long y, nBits;
2821ab64890Smrg
283818534a1Smrg    y = (mask >> 1) & 033333333333;
284818534a1Smrg    y = mask - y - ((y >> 1) & 033333333333);
2851ab64890Smrg    nBits = ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077));
2861ab64890Smrg
2871ab64890Smrg    /* nBitsMax really means max+1 */
2881ab64890Smrg    return (nBits < nBitsMax) ? nBits : (nBitsMax - 1);
2891ab64890Smrg}
2901ab64890Smrg
2911ab64890Smrgstatic CARD32
292818534a1Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
2931ab64890Smrg{
294818534a1Smrg    register unsigned int i, bit, nAtoms;
295818534a1Smrg    register CARD32 atomsPresent;
2961ab64890Smrg
297818534a1Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
298818534a1Smrg        if (atoms[i] != None) {
299818534a1Smrg            atomsPresent |= bit;
3001ab64890Smrg            nAtoms++;
3011ab64890Smrg        }
3021ab64890Smrg    }
3031ab64890Smrg    if (count)
304818534a1Smrg        *count = nAtoms;
3051ab64890Smrg    return atomsPresent;
3061ab64890Smrg}
3071ab64890Smrg
3081ab64890Smrgstatic void
309818534a1Smrg_XkbCopyAtoms(Display *dpy, Atom *atoms, CARD32 mask, int maxAtoms)
3101ab64890Smrg{
311818534a1Smrg    register unsigned int i, bit;
3121ab64890Smrg
313818534a1Smrg    for (i = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
314818534a1Smrg        if (mask & bit)
315818534a1Smrg            Data32(dpy, &atoms[i], 4);
3161ab64890Smrg    }
3171ab64890Smrg    return;
3181ab64890Smrg}
3191ab64890Smrg
3201ab64890SmrgBool
321818534a1SmrgXkbSetNames(Display *dpy,
322818534a1Smrg            unsigned int which,
323818534a1Smrg            unsigned int firstType,
324818534a1Smrg            unsigned int nTypes,
325818534a1Smrg            XkbDescPtr xkb)
3261ab64890Smrg{
3271ab64890Smrg    register xkbSetNamesReq *req;
328818534a1Smrg    int nLvlNames = 0;
3291ab64890Smrg    XkbInfoPtr xkbi;
3301ab64890Smrg    XkbNamesPtr names;
331818534a1Smrg    unsigned firstLvlType, nLvlTypes;
332818534a1Smrg    int nVMods, nLEDs, nRG, nKA, nGroups;
333818534a1Smrg    int nKeys = 0, firstKey = 0, nAtoms;
334818534a1Smrg    CARD32 leds, vmods, groups;
3351ab64890Smrg
3361ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
337818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
338818534a1Smrg        return False;
339818534a1Smrg    if ((!xkb) || (!xkb->names))
340818534a1Smrg        return False;
341818534a1Smrg    firstLvlType = firstType;
342818534a1Smrg    nLvlTypes = nTypes;
343818534a1Smrg    if (nTypes < 1)
344818534a1Smrg        which &= ~(XkbKTLevelNamesMask | XkbKeyTypeNamesMask);
345818534a1Smrg    else if (firstType <= XkbLastRequiredType) {
346818534a1Smrg        int adjust;
347818534a1Smrg
348818534a1Smrg        adjust = XkbLastRequiredType - firstType + 1;
349818534a1Smrg        firstType += adjust;
350818534a1Smrg        nTypes -= adjust;
351818534a1Smrg        if (nTypes < 1)
352818534a1Smrg            which &= ~XkbKeyTypeNamesMask;
353818534a1Smrg    }
354818534a1Smrg    names = xkb->names;
355818534a1Smrg    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
356818534a1Smrg        register int i;
357818534a1Smrg        XkbKeyTypePtr type;
358818534a1Smrg
359818534a1Smrg        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
360818534a1Smrg            (firstType + nTypes > xkb->map->num_types) ||
361818534a1Smrg            (firstLvlType + nLvlTypes > xkb->map->num_types))
362818534a1Smrg            return False;
363818534a1Smrg        if (which & XkbKTLevelNamesMask) {
364818534a1Smrg            type = &xkb->map->types[firstLvlType];
365818534a1Smrg            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
366818534a1Smrg                if (type->level_names != NULL)
367818534a1Smrg                    nLvlNames += type->num_levels;
368818534a1Smrg            }
369818534a1Smrg        }
370818534a1Smrg    }
371818534a1Smrg
372818534a1Smrg    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
3731ab64890Smrg    LockDisplay(dpy);
3741ab64890Smrg    xkbi = dpy->xkb_info;
3751ab64890Smrg    GetReq(kbSetNames, req);
3761ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
3771ab64890Smrg    req->xkbReqType = X_kbSetNames;
3781ab64890Smrg    req->deviceSpec = xkb->device_spec;
3791ab64890Smrg    req->firstType = firstType;
3801ab64890Smrg    req->nTypes = nTypes;
3811ab64890Smrg    req->firstKey = xkb->min_key_code;
382818534a1Smrg    req->nKeys = xkb->max_key_code - xkb->min_key_code + 1;
383818534a1Smrg
384818534a1Smrg    if (which & XkbKeycodesNameMask)
385818534a1Smrg        nAtoms++;
386818534a1Smrg    if (which & XkbGeometryNameMask)
387818534a1Smrg        nAtoms++;
388818534a1Smrg    if (which & XkbSymbolsNameMask)
389818534a1Smrg        nAtoms++;
390818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
391818534a1Smrg        nAtoms++;
392818534a1Smrg    if (which & XkbTypesNameMask)
393818534a1Smrg        nAtoms++;
394818534a1Smrg    if (which & XkbCompatNameMask)
395818534a1Smrg        nAtoms++;
396818534a1Smrg    if (which & XkbKeyTypeNamesMask)
397818534a1Smrg        nAtoms += nTypes;
398818534a1Smrg    if (which & XkbKTLevelNamesMask) {
399818534a1Smrg        req->firstKTLevel = firstLvlType;
400818534a1Smrg        req->nKTLevels = nLvlTypes;
401818534a1Smrg        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
402818534a1Smrg        nAtoms += nLvlNames;
403818534a1Smrg    }
404818534a1Smrg    else
405818534a1Smrg        req->firstKTLevel = req->nKTLevels = 0;
406818534a1Smrg
407818534a1Smrg    if (which & XkbIndicatorNamesMask) {
408818534a1Smrg        req->indicators = leds =
409818534a1Smrg            _XkbCountAtoms(names->indicators, XkbNumIndicators, &nLEDs);
410818534a1Smrg        if (nLEDs > 0)
411818534a1Smrg            nAtoms += nLEDs;
412818534a1Smrg        else
413818534a1Smrg            which &= ~XkbIndicatorNamesMask;
414818534a1Smrg    }
415818534a1Smrg    else
416818534a1Smrg        req->indicators = leds = 0;
417818534a1Smrg
418818534a1Smrg    if (which & XkbVirtualModNamesMask) {
419818534a1Smrg        vmods = req->virtualMods = (CARD16)
420818534a1Smrg            _XkbCountAtoms(names->vmods, XkbNumVirtualMods, &nVMods);
421818534a1Smrg        if (nVMods > 0)
422818534a1Smrg            nAtoms += nVMods;
423818534a1Smrg        else
424818534a1Smrg            which &= ~XkbVirtualModNamesMask;
425818534a1Smrg    }
426818534a1Smrg    else
427818534a1Smrg        vmods = req->virtualMods = 0;
428818534a1Smrg
429818534a1Smrg    if (which & XkbGroupNamesMask) {
430818534a1Smrg        groups = req->groupNames = (CARD8)
431818534a1Smrg            _XkbCountAtoms(names->groups, XkbNumKbdGroups, &nGroups);
432818534a1Smrg        if (nGroups > 0)
433818534a1Smrg            nAtoms += nGroups;
434818534a1Smrg        else
435818534a1Smrg            which &= ~XkbGroupNamesMask;
436818534a1Smrg    }
437818534a1Smrg    else
438818534a1Smrg        groups = req->groupNames = 0;
439818534a1Smrg
440818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
441818534a1Smrg        firstKey = req->firstKey;
442818534a1Smrg        nKeys = req->nKeys;
443818534a1Smrg        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
444818534a1Smrg    }
445818534a1Smrg    else
446818534a1Smrg        which &= ~XkbKeyNamesMask;
447818534a1Smrg
448818534a1Smrg    if (which & XkbKeyAliasesMask) {
449818534a1Smrg        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
450818534a1Smrg        if (nKA > 0) {
451818534a1Smrg            req->nKeyAliases = nKA;
452818534a1Smrg            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
453818534a1Smrg        }
454818534a1Smrg        else {
455818534a1Smrg            which &= ~XkbKeyAliasesMask;
456818534a1Smrg            req->nKeyAliases = 0;
457818534a1Smrg        }
458818534a1Smrg    }
459818534a1Smrg    else
460818534a1Smrg        req->nKeyAliases = 0;
461818534a1Smrg
462818534a1Smrg    if (which & XkbRGNamesMask) {
463818534a1Smrg        nRG = names->num_rg;
464818534a1Smrg        if (nRG > 0)
465818534a1Smrg            nAtoms += nRG;
466818534a1Smrg        else
467818534a1Smrg            which &= ~XkbRGNamesMask;
468818534a1Smrg    }
469818534a1Smrg
470818534a1Smrg    req->which = which;
471818534a1Smrg    req->nRadioGroups = nRG;
472818534a1Smrg    req->length += (nAtoms * 4) / 4;
473818534a1Smrg
474818534a1Smrg    if (which & XkbKeycodesNameMask)
475818534a1Smrg        Data32(dpy, (long *) &names->keycodes, 4);
476818534a1Smrg    if (which & XkbGeometryNameMask)
477818534a1Smrg        Data32(dpy, (long *) &names->geometry, 4);
478818534a1Smrg    if (which & XkbSymbolsNameMask)
479818534a1Smrg        Data32(dpy, (long *) &names->symbols, 4);
480818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
481818534a1Smrg        Data32(dpy, (long *) &names->phys_symbols, 4);
482818534a1Smrg    if (which & XkbTypesNameMask)
483818534a1Smrg        Data32(dpy, (long *) &names->types, 4);
484818534a1Smrg    if (which & XkbCompatNameMask)
485818534a1Smrg        Data32(dpy, (long *) &names->compat, 4);
486818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
487818534a1Smrg        register int i;
488818534a1Smrg        register XkbKeyTypePtr type;
489818534a1Smrg
490818534a1Smrg        type = &xkb->map->types[firstType];
491818534a1Smrg        for (i = 0; i < nTypes; i++, type++) {
492818534a1Smrg            Data32(dpy, (long *) &type->name, 4);
493818534a1Smrg        }
494818534a1Smrg    }
495818534a1Smrg    if (which & XkbKTLevelNamesMask) {
496818534a1Smrg        XkbKeyTypePtr type;
497818534a1Smrg        int i;
498818534a1Smrg        char *tmp;
499818534a1Smrg
500818534a1Smrg        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
501818534a1Smrg        type = &xkb->map->types[firstLvlType];
502818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
503818534a1Smrg            *tmp++ = type->num_levels;
504818534a1Smrg        }
505818534a1Smrg        type = &xkb->map->types[firstLvlType];
506818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
507818534a1Smrg            if (type->level_names != NULL)
508818534a1Smrg                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
509818534a1Smrg        }
510818534a1Smrg    }
511818534a1Smrg    if (which & XkbIndicatorNamesMask)
512818534a1Smrg        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
513818534a1Smrg    if (which & XkbVirtualModNamesMask)
514818534a1Smrg        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
515818534a1Smrg    if (which & XkbGroupNamesMask)
516818534a1Smrg        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
517818534a1Smrg    if (which & XkbKeyNamesMask) {
518818534a1Smrg        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
519818534a1Smrg    }
520818534a1Smrg    if (which & XkbKeyAliasesMask) {
521818534a1Smrg        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
522818534a1Smrg    }
523818534a1Smrg    if (which & XkbRGNamesMask) {
524818534a1Smrg        Data32(dpy, (long *) names->radio_groups, nRG * 4);
5251ab64890Smrg    }
5261ab64890Smrg    UnlockDisplay(dpy);
5271ab64890Smrg    SyncHandle();
5281ab64890Smrg    return True;
5291ab64890Smrg}
5301ab64890Smrg
5311ab64890SmrgBool
532818534a1SmrgXkbChangeNames(Display *dpy, XkbDescPtr xkb, XkbNameChangesPtr changes)
5331ab64890Smrg{
5341ab64890Smrg    register xkbSetNamesReq *req;
535818534a1Smrg    int nLvlNames = 0;
5361ab64890Smrg    XkbInfoPtr xkbi;
5371ab64890Smrg    XkbNamesPtr names;
538818534a1Smrg    unsigned which, firstType, nTypes;
539818534a1Smrg    unsigned firstLvlType, nLvlTypes;
540818534a1Smrg    int nVMods, nLEDs, nRG, nKA, nGroups;
541818534a1Smrg    int nKeys = 0, firstKey = 0, nAtoms;
542818534a1Smrg    CARD32 leds = 0, vmods = 0, groups = 0;
5431ab64890Smrg
5441ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
545818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
546818534a1Smrg        return False;
547818534a1Smrg    if ((!xkb) || (!xkb->names) || (!changes))
548818534a1Smrg        return False;
549818534a1Smrg    which = changes->changed;
550818534a1Smrg    firstType = changes->first_type;
551818534a1Smrg    nTypes = changes->num_types;
5522d67cb4fSmrg    firstLvlType = changes->first_lvl;
553818534a1Smrg    nLvlTypes = changes->num_lvls;
554818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
555818534a1Smrg        if (nTypes < 1)
556818534a1Smrg            which &= ~XkbKeyTypeNamesMask;
557818534a1Smrg        else if (firstType <= XkbLastRequiredType) {
558818534a1Smrg            int adjust;
559818534a1Smrg
560818534a1Smrg            adjust = XkbLastRequiredType - firstType + 1;
561818534a1Smrg            firstType += adjust;
562818534a1Smrg            nTypes -= adjust;
563818534a1Smrg            if (nTypes < 1)
564818534a1Smrg                which &= ~XkbKeyTypeNamesMask;
565818534a1Smrg        }
566818534a1Smrg    }
567818534a1Smrg    else
568818534a1Smrg        firstType = nTypes = 0;
569818534a1Smrg
570818534a1Smrg    if (which & XkbKTLevelNamesMask) {
571818534a1Smrg        if (nLvlTypes < 1)
572818534a1Smrg            which &= ~XkbKTLevelNamesMask;
573818534a1Smrg    }
574818534a1Smrg    else
575818534a1Smrg        firstLvlType = nLvlTypes = 0;
576818534a1Smrg
577818534a1Smrg    names = xkb->names;
578818534a1Smrg    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
579818534a1Smrg        register int i;
580818534a1Smrg
581818534a1Smrg        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
582818534a1Smrg            (firstType + nTypes > xkb->map->num_types) ||
583818534a1Smrg            (firstLvlType + nLvlTypes > xkb->map->num_types))
584818534a1Smrg            return False;
585818534a1Smrg        if (which & XkbKTLevelNamesMask) {
586818534a1Smrg            XkbKeyTypePtr type = &xkb->map->types[firstLvlType];
587818534a1Smrg
588818534a1Smrg            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
589818534a1Smrg                if (type->level_names != NULL)
590818534a1Smrg                    nLvlNames += type->num_levels;
591818534a1Smrg            }
592818534a1Smrg        }
593818534a1Smrg    }
594818534a1Smrg
595818534a1Smrg    if (changes->num_keys < 1)
596818534a1Smrg        which &= ~XkbKeyNamesMask;
597818534a1Smrg    if ((which & XkbKeyNamesMask) == 0)
598818534a1Smrg        changes->first_key = changes->num_keys = 0;
599818534a1Smrg    else if ((changes->first_key < xkb->min_key_code) ||
600818534a1Smrg             (changes->first_key + changes->num_keys > xkb->max_key_code)) {
601818534a1Smrg        return False;
602818534a1Smrg    }
603818534a1Smrg
604818534a1Smrg    if ((which & XkbVirtualModNamesMask) == 0)
605818534a1Smrg        changes->changed_vmods = 0;
606818534a1Smrg    else if (changes->changed_vmods == 0)
607818534a1Smrg        which &= ~XkbVirtualModNamesMask;
608818534a1Smrg
609818534a1Smrg    if ((which & XkbIndicatorNamesMask) == 0)
610818534a1Smrg        changes->changed_indicators = 0;
611818534a1Smrg    else if (changes->changed_indicators == 0)
612818534a1Smrg        which &= ~XkbIndicatorNamesMask;
613818534a1Smrg
614818534a1Smrg    if ((which & XkbGroupNamesMask) == 0)
615818534a1Smrg        changes->changed_groups = 0;
616818534a1Smrg    else if (changes->changed_groups == 0)
617818534a1Smrg        which &= ~XkbGroupNamesMask;
618818534a1Smrg
619818534a1Smrg    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
6201ab64890Smrg    LockDisplay(dpy);
6211ab64890Smrg    xkbi = dpy->xkb_info;
6221ab64890Smrg    GetReq(kbSetNames, req);
6231ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
6241ab64890Smrg    req->xkbReqType = X_kbSetNames;
6251ab64890Smrg    req->deviceSpec = xkb->device_spec;
6261ab64890Smrg    req->firstType = firstType;
6271ab64890Smrg    req->nTypes = nTypes;
6281ab64890Smrg    req->firstKey = changes->first_key;
6291ab64890Smrg    req->nKeys = changes->num_keys;
6301ab64890Smrg
631818534a1Smrg    if (which & XkbKeycodesNameMask)
632818534a1Smrg        nAtoms++;
633818534a1Smrg    if (which & XkbGeometryNameMask)
634818534a1Smrg        nAtoms++;
635818534a1Smrg    if (which & XkbSymbolsNameMask)
636818534a1Smrg        nAtoms++;
637818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
638818534a1Smrg        nAtoms++;
639818534a1Smrg    if (which & XkbTypesNameMask)
640818534a1Smrg        nAtoms++;
641818534a1Smrg    if (which & XkbCompatNameMask)
642818534a1Smrg        nAtoms++;
643818534a1Smrg    if (which & XkbKeyTypeNamesMask)
644818534a1Smrg        nAtoms += nTypes;
645818534a1Smrg    if (which & XkbKTLevelNamesMask) {
646818534a1Smrg        req->firstKTLevel = firstLvlType;
647818534a1Smrg        req->nKTLevels = nLvlTypes;
648818534a1Smrg        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
649818534a1Smrg        nAtoms += nLvlNames;
650818534a1Smrg    }
651818534a1Smrg    else
652818534a1Smrg        req->firstKTLevel = req->nKTLevels = 0;
653818534a1Smrg
654818534a1Smrg    if (which & XkbIndicatorNamesMask) {
655818534a1Smrg        leds = req->indicators = (CARD32) changes->changed_indicators;
656818534a1Smrg        nLEDs = _XkbCountBits(XkbNumIndicators, changes->changed_indicators);
657818534a1Smrg        if (nLEDs > 0)
658818534a1Smrg            nAtoms += nLEDs;
659818534a1Smrg        else
660818534a1Smrg            which &= ~XkbIndicatorNamesMask;
661818534a1Smrg    }
662818534a1Smrg    else
663818534a1Smrg        req->indicators = 0;
664818534a1Smrg
665818534a1Smrg    if (which & XkbVirtualModNamesMask) {
666818534a1Smrg        vmods = req->virtualMods = changes->changed_vmods;
667818534a1Smrg        nVMods = _XkbCountBits(XkbNumVirtualMods,
668818534a1Smrg                               (unsigned long) changes->changed_vmods);
669818534a1Smrg        if (nVMods > 0)
670818534a1Smrg            nAtoms += nVMods;
671818534a1Smrg        else
672818534a1Smrg            which &= ~XkbVirtualModNamesMask;
673818534a1Smrg    }
674818534a1Smrg    else
675818534a1Smrg        req->virtualMods = 0;
676818534a1Smrg
677818534a1Smrg    if (which & XkbGroupNamesMask) {
678818534a1Smrg        groups = req->groupNames = changes->changed_groups;
679818534a1Smrg        nGroups = _XkbCountBits(XkbNumKbdGroups,
680818534a1Smrg                                (unsigned long) changes->changed_groups);
681818534a1Smrg        if (nGroups > 0)
682818534a1Smrg            nAtoms += nGroups;
683818534a1Smrg        else
684818534a1Smrg            which &= ~XkbGroupNamesMask;
685818534a1Smrg    }
686818534a1Smrg    else
687818534a1Smrg        req->groupNames = 0;
688818534a1Smrg
689818534a1Smrg    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
690818534a1Smrg        firstKey = req->firstKey;
691818534a1Smrg        nKeys = req->nKeys;
692818534a1Smrg        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
693818534a1Smrg    }
694818534a1Smrg    else
695818534a1Smrg        which &= ~XkbKeyNamesMask;
696818534a1Smrg
697818534a1Smrg    if (which & XkbKeyAliasesMask) {
698818534a1Smrg        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
699818534a1Smrg        if (nKA > 0)
700818534a1Smrg            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
701818534a1Smrg        else
702818534a1Smrg            which &= ~XkbKeyAliasesMask;
703818534a1Smrg    }
704818534a1Smrg
705818534a1Smrg    if (which & XkbRGNamesMask) {
706818534a1Smrg        nRG = names->num_rg;
707818534a1Smrg        if (nRG > 0)
708818534a1Smrg            nAtoms += nRG;
709818534a1Smrg        else
710818534a1Smrg            which &= ~XkbRGNamesMask;
711818534a1Smrg    }
712818534a1Smrg
713818534a1Smrg    req->which = which;
714818534a1Smrg    req->nRadioGroups = nRG;
715818534a1Smrg    req->length += (nAtoms * 4) / 4;
716818534a1Smrg
717818534a1Smrg    if (which & XkbKeycodesNameMask)
718818534a1Smrg        Data32(dpy, (long *) &names->keycodes, 4);
719818534a1Smrg    if (which & XkbGeometryNameMask)
720818534a1Smrg        Data32(dpy, (long *) &names->geometry, 4);
721818534a1Smrg    if (which & XkbSymbolsNameMask)
722818534a1Smrg        Data32(dpy, (long *) &names->symbols, 4);
723818534a1Smrg    if (which & XkbPhysSymbolsNameMask)
724818534a1Smrg        Data32(dpy, (long *) &names->phys_symbols, 4);
725818534a1Smrg    if (which & XkbTypesNameMask)
726818534a1Smrg        Data32(dpy, (long *) &names->types, 4);
727818534a1Smrg    if (which & XkbCompatNameMask)
728818534a1Smrg        Data32(dpy, (long *) &names->compat, 4);
729818534a1Smrg    if (which & XkbKeyTypeNamesMask) {
730818534a1Smrg        register int i;
731818534a1Smrg        register XkbKeyTypePtr type;
732818534a1Smrg
733818534a1Smrg        type = &xkb->map->types[firstType];
734818534a1Smrg        for (i = 0; i < nTypes; i++, type++) {
735818534a1Smrg            Data32(dpy, (long *) &type->name, 4);
736818534a1Smrg        }
737818534a1Smrg    }
738818534a1Smrg    if (which & XkbKTLevelNamesMask) {
739818534a1Smrg        XkbKeyTypePtr type;
740818534a1Smrg        int i;
741818534a1Smrg        char *tmp;
742818534a1Smrg
743818534a1Smrg        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
744818534a1Smrg        type = &xkb->map->types[firstLvlType];
745818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
746818534a1Smrg            *tmp++ = type->num_levels;
747818534a1Smrg        }
748818534a1Smrg        type = &xkb->map->types[firstLvlType];
749818534a1Smrg        for (i = 0; i < nLvlTypes; i++, type++) {
750818534a1Smrg            if (type->level_names != NULL)
751818534a1Smrg                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
752818534a1Smrg        }
753818534a1Smrg    }
754818534a1Smrg    if (which & XkbIndicatorNamesMask)
755818534a1Smrg        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
756818534a1Smrg    if (which & XkbVirtualModNamesMask)
757818534a1Smrg        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
758818534a1Smrg    if (which & XkbGroupNamesMask)
759818534a1Smrg        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
760818534a1Smrg    if (which & XkbKeyNamesMask) {
761818534a1Smrg        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
762818534a1Smrg    }
763818534a1Smrg    if (which & XkbKeyAliasesMask) {
764818534a1Smrg        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
765818534a1Smrg    }
766818534a1Smrg    if (which & XkbRGNamesMask) {
767818534a1Smrg        Data32(dpy, (long *) names->radio_groups, nRG * 4);
7681ab64890Smrg    }
7691ab64890Smrg    UnlockDisplay(dpy);
7701ab64890Smrg    SyncHandle();
7711ab64890Smrg    return True;
7721ab64890Smrg}
7731ab64890Smrg
7741ab64890Smrgvoid
775818534a1SmrgXkbNoteNameChanges(XkbNameChangesPtr old,
776818534a1Smrg                   XkbNamesNotifyEvent *new,
777818534a1Smrg                   unsigned int wanted)
7781ab64890Smrg{
779818534a1Smrg    int first, last, old_last, new_last;
780818534a1Smrg
7810f8248bfSmrg    if ((old == NULL) || (new == NULL))
782818534a1Smrg        return;
7830f8248bfSmrg
7840f8248bfSmrg    wanted &= new->changed;
7850f8248bfSmrg
7860f8248bfSmrg    if (wanted == 0)
7870f8248bfSmrg	return;
7880f8248bfSmrg
789818534a1Smrg    if (wanted & XkbKeyTypeNamesMask) {
790818534a1Smrg        if (old->changed & XkbKeyTypeNamesMask) {
791818534a1Smrg            new_last = (new->first_type + new->num_types - 1);
792818534a1Smrg            old_last = (old->first_type + old->num_types - 1);
793818534a1Smrg
794818534a1Smrg            if (new->first_type < old->first_type)
795818534a1Smrg                first = new->first_type;
796818534a1Smrg            else
797818534a1Smrg                first = old->first_type;
798818534a1Smrg
799818534a1Smrg            if (old_last > new_last)
800818534a1Smrg                last = old_last;
801818534a1Smrg            else
802818534a1Smrg                last = new_last;
803818534a1Smrg
804818534a1Smrg            old->first_type = first;
805818534a1Smrg            old->num_types = (last - first) + 1;
806818534a1Smrg        }
807818534a1Smrg        else {
808818534a1Smrg            old->first_type = new->first_type;
809818534a1Smrg            old->num_types = new->num_types;
810818534a1Smrg        }
811818534a1Smrg    }
812818534a1Smrg    if (wanted & XkbKTLevelNamesMask) {
813818534a1Smrg        if (old->changed & XkbKTLevelNamesMask) {
814818534a1Smrg            new_last = (new->first_lvl + new->num_lvls - 1);
815818534a1Smrg            old_last = (old->first_lvl + old->num_lvls - 1);
816818534a1Smrg
817818534a1Smrg            if (new->first_lvl < old->first_lvl)
818818534a1Smrg                first = new->first_lvl;
819818534a1Smrg            else
820818534a1Smrg                first = old->first_lvl;
821818534a1Smrg
822818534a1Smrg            if (old_last > new_last)
823818534a1Smrg                last = old_last;
824818534a1Smrg            else
825818534a1Smrg                last = new_last;
826818534a1Smrg
827818534a1Smrg            old->first_lvl = first;
828818534a1Smrg            old->num_lvls = (last - first) + 1;
829818534a1Smrg        }
830818534a1Smrg        else {
831818534a1Smrg            old->first_lvl = new->first_lvl;
832818534a1Smrg            old->num_lvls = new->num_lvls;
833818534a1Smrg        }
834818534a1Smrg    }
835818534a1Smrg    if (wanted & XkbIndicatorNamesMask) {
836818534a1Smrg        if (old->changed & XkbIndicatorNamesMask)
837818534a1Smrg            old->changed_indicators |= new->changed_indicators;
838818534a1Smrg        else
839818534a1Smrg            old->changed_indicators = new->changed_indicators;
840818534a1Smrg    }
841818534a1Smrg    if (wanted & XkbKeyNamesMask) {
842818534a1Smrg        if (old->changed & XkbKeyNamesMask) {
843818534a1Smrg            new_last = (new->first_key + new->num_keys - 1);
844818534a1Smrg            old_last = (old->first_key + old->num_keys - 1);
845818534a1Smrg
846818534a1Smrg            first = old->first_key;
847818534a1Smrg
848818534a1Smrg            if (new->first_key < old->first_key)
849818534a1Smrg                first = new->first_key;
850818534a1Smrg            if (old_last > new_last)
851818534a1Smrg                new_last = old_last;
852818534a1Smrg
853818534a1Smrg            old->first_key = first;
854818534a1Smrg            old->num_keys = (new_last - first) + 1;
855818534a1Smrg        }
856818534a1Smrg        else {
857818534a1Smrg            old->first_key = new->first_key;
858818534a1Smrg            old->num_keys = new->num_keys;
859818534a1Smrg        }
860818534a1Smrg    }
861818534a1Smrg    if (wanted & XkbVirtualModNamesMask) {
862818534a1Smrg        if (old->changed & XkbVirtualModNamesMask)
863818534a1Smrg            old->changed_vmods |= new->changed_vmods;
864818534a1Smrg        else
865818534a1Smrg            old->changed_vmods = new->changed_vmods;
866818534a1Smrg    }
867818534a1Smrg    if (wanted & XkbGroupNamesMask) {
868818534a1Smrg        if (old->changed & XkbGroupNamesMask)
869818534a1Smrg            old->changed_groups |= new->changed_groups;
870818534a1Smrg        else
871818534a1Smrg            old->changed_groups = new->changed_groups;
872818534a1Smrg    }
873818534a1Smrg    if (wanted & XkbRGNamesMask)
874818534a1Smrg        old->num_rg = new->num_radio_groups;
875818534a1Smrg    if (wanted & XkbKeyAliasesMask)
876818534a1Smrg        old->num_aliases = new->num_aliases;
877818534a1Smrg    old->changed |= wanted;
8781ab64890Smrg    return;
8791ab64890Smrg}
880