XKBNames.c revision 0f8248bf
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#define NEED_MAP_READERS
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "Xlibint.h"
32#include <X11/extensions/XKBproto.h>
33#include "XKBlibint.h"
34
35
36static Status
37_XkbReadAtoms(XkbReadBufferPtr buf,
38              Atom *atoms,
39              int maxAtoms,
40              CARD32 present)
41{
42    register int i, bit;
43
44    for (i = 0, bit = 1; (i < maxAtoms) && (present); i++, bit <<= 1) {
45        if (present & bit) {
46            if (!_XkbReadBufferCopy32(buf, (long *) &atoms[i], 1))
47                return BadLength;
48            present &= ~bit;
49        }
50    }
51    return Success;
52}
53
54Status
55_XkbReadGetNamesReply(Display *dpy,
56                      xkbGetNamesReply *rep,
57                      XkbDescPtr xkb,
58                      int *nread_rtrn)
59{
60    int i, len;
61    XkbReadBufferRec buf;
62    register XkbNamesPtr names;
63
64    if (xkb->device_spec == XkbUseCoreKbd)
65        xkb->device_spec = rep->deviceID;
66
67    if ((xkb->names == NULL) &&
68        (XkbAllocNames(xkb, rep->which,
69                       rep->nRadioGroups, rep->nKeyAliases) != Success)) {
70        return BadAlloc;
71    }
72    names = xkb->names;
73    if (rep->length == 0)
74        return Success;
75
76    if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4))
77        return BadAlloc;
78    if (nread_rtrn)
79        *nread_rtrn = (int) rep->length * 4;
80
81    if ((rep->which & XkbKeycodesNameMask) &&
82        (!_XkbReadBufferCopy32(&buf, (long *) &names->keycodes, 1)))
83        goto BAILOUT;
84    if ((rep->which & XkbGeometryNameMask) &&
85        (!_XkbReadBufferCopy32(&buf, (long *) &names->geometry, 1)))
86        goto BAILOUT;
87    if ((rep->which & XkbSymbolsNameMask) &&
88        (!_XkbReadBufferCopy32(&buf, (long *) &names->symbols, 1)))
89        goto BAILOUT;
90    if ((rep->which & XkbPhysSymbolsNameMask) &&
91        (!_XkbReadBufferCopy32(&buf, (long *) &names->phys_symbols, 1)))
92        goto BAILOUT;
93    if ((rep->which & XkbTypesNameMask) &&
94        (!_XkbReadBufferCopy32(&buf, (long *) &names->types, 1)))
95        goto BAILOUT;
96    if ((rep->which & XkbCompatNameMask) &&
97        (!_XkbReadBufferCopy32(&buf, (long *) &names->compat, 1)))
98        goto BAILOUT;
99
100    if (rep->which & XkbKeyTypeNamesMask) {
101        XkbClientMapPtr map = xkb->map;
102        XkbKeyTypePtr type;
103
104        len = rep->nTypes * 4;
105        if (map != NULL) {
106            type = map->types;
107            for (i = 0; (i < map->num_types) && (i < rep->nTypes); i++, type++) {
108                if (!_XkbReadBufferCopy32(&buf, (long *) &type->name, 1))
109                    goto BAILOUT;
110                len -= 4;
111            }
112        }
113        if ((len > 0) && (!_XkbSkipReadBufferData(&buf, len)))
114            goto BAILOUT;
115    }
116    if (rep->which & XkbKTLevelNamesMask) {
117        CARD8 *nLevels;
118        XkbClientMapPtr map = xkb->map;
119
120        nLevels =
121            (CARD8 *) _XkbGetReadBufferPtr(&buf, XkbPaddedSize(rep->nTypes));
122        if (nLevels == NULL)
123            goto BAILOUT;
124        if (map != NULL) {
125            XkbKeyTypePtr type = map->types;
126
127            for (i = 0; i < (int) rep->nTypes; i++, type++) {
128                if (i >= map->num_types) {
129                    if (!_XkbSkipReadBufferData(&buf, nLevels[i] * 4))
130                        goto BAILOUT;
131                    continue;
132                }
133                if ((nLevels[i] > 0) && (nLevels[i] != type->num_levels)) {
134                    goto BAILOUT;
135                }
136
137                Xfree(type->level_names);
138                if (nLevels[i] == 0) {
139                    type->level_names = NULL;
140                    continue;
141                }
142                type->level_names = _XkbTypedCalloc(nLevels[i], Atom);
143                if (type->level_names != NULL) {
144                    if (!_XkbReadBufferCopy32(&buf, (long *) type->level_names,
145                                              nLevels[i]))
146                        goto BAILOUT;
147                }
148                else {
149                    _XkbSkipReadBufferData(&buf, nLevels[i] * 4);
150                }
151            }
152        }
153        else {
154            for (i = 0; i < (int) rep->nTypes; i++) {
155                _XkbSkipReadBufferData(&buf, nLevels[i] * 4);
156            }
157        }
158    }
159    if (rep->which & XkbIndicatorNamesMask) {
160        if (_XkbReadAtoms(&buf, names->indicators, XkbNumIndicators,
161                          rep->indicators) != Success)
162            goto BAILOUT;
163    }
164    if (rep->which & XkbVirtualModNamesMask) {
165        if (_XkbReadAtoms(&buf, names->vmods, XkbNumVirtualMods,
166                          (CARD32) rep->virtualMods) != Success)
167            goto BAILOUT;
168    }
169    if (rep->which & XkbGroupNamesMask) {
170        if (_XkbReadAtoms(&buf, names->groups, XkbNumKbdGroups,
171                          (CARD32) rep->groupNames) != Success)
172            goto BAILOUT;
173    }
174    if (rep->which & XkbKeyNamesMask) {
175        if (names->keys == NULL) {
176            int nKeys;
177
178            if (xkb->max_key_code == 0) {
179                xkb->min_key_code = rep->minKeyCode;
180                xkb->max_key_code = rep->maxKeyCode;
181            }
182            nKeys = xkb->max_key_code + 1;
183            names->keys = _XkbTypedCalloc(nKeys, XkbKeyNameRec);
184        }
185        if (((int) rep->firstKey + rep->nKeys) > xkb->max_key_code + 1)
186            goto BAILOUT;
187        if (names->keys != NULL) {
188            if (!_XkbCopyFromReadBuffer(&buf,
189                                        (char *) &names->keys[rep->firstKey],
190                                        rep->nKeys * XkbKeyNameLength))
191                goto BAILOUT;
192        }
193        else
194            _XkbSkipReadBufferData(&buf, rep->nKeys * XkbKeyNameLength);
195    }
196    if (rep->which & XkbKeyAliasesMask && (rep->nKeyAliases > 0)) {
197        if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, rep->nKeyAliases) !=
198            Success)
199            goto BAILOUT;
200        if (!_XkbCopyFromReadBuffer(&buf, (char *) names->key_aliases,
201                                    rep->nKeyAliases * XkbKeyNameLength * 2))
202            goto BAILOUT;
203    }
204    if (rep->which & XkbRGNamesMask) {
205        if (rep->nRadioGroups > 0) {
206            Atom *rgNames;
207
208            if (names->radio_groups == NULL)
209                names->radio_groups = _XkbTypedCalloc(rep->nRadioGroups, Atom);
210            else if (names->num_rg < rep->nRadioGroups) {
211                names->radio_groups = _XkbTypedRealloc(names->radio_groups,
212                                                       rep->nRadioGroups, Atom);
213            }
214            rgNames = names->radio_groups;
215            if (!rgNames) {
216                goto BAILOUT;
217            }
218            if (!_XkbReadBufferCopy32
219                (&buf, (long *) rgNames, rep->nRadioGroups))
220                goto BAILOUT;
221            names->num_rg = rep->nRadioGroups;
222        }
223        else if (names->num_rg > 0) {
224            names->num_rg = 0;
225            Xfree(names->radio_groups);
226        }
227    }
228    len = _XkbFreeReadBuffer(&buf);
229    if (len != 0)
230        return BadLength;
231    else
232        return Success;
233 BAILOUT:
234    _XkbFreeReadBuffer(&buf);
235    return BadLength;
236}
237
238Status
239XkbGetNames(Display *dpy, unsigned which, XkbDescPtr xkb)
240{
241    register xkbGetNamesReq *req;
242    xkbGetNamesReply rep;
243    Status status;
244    XkbInfoPtr xkbi;
245
246    if ((dpy->flags & XlibDisplayNoXkb) ||
247        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
248        return BadAccess;
249    LockDisplay(dpy);
250    xkbi = dpy->xkb_info;
251    if (!xkb->names) {
252        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
253        if (!xkb->names) {
254            UnlockDisplay(dpy);
255            SyncHandle();
256            return BadAlloc;
257        }
258    }
259    GetReq(kbGetNames, req);
260    req->reqType = xkbi->codes->major_opcode;
261    req->xkbReqType = X_kbGetNames;
262    req->deviceSpec = xkb->device_spec;
263    req->which = which;
264    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
265        UnlockDisplay(dpy);
266        SyncHandle();
267        return BadImplementation;
268    }
269
270    status = _XkbReadGetNamesReply(dpy, &rep, xkb, NULL);
271    UnlockDisplay(dpy);
272    SyncHandle();
273    return status;
274}
275
276/***====================================================================***/
277
278static int
279_XkbCountBits(int nBitsMax, unsigned long mask)
280{
281    register unsigned long y, nBits;
282
283    y = (mask >> 1) & 033333333333;
284    y = mask - y - ((y >> 1) & 033333333333);
285    nBits = ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077));
286
287    /* nBitsMax really means max+1 */
288    return (nBits < nBitsMax) ? nBits : (nBitsMax - 1);
289}
290
291static CARD32
292_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
293{
294    register unsigned int i, bit, nAtoms;
295    register CARD32 atomsPresent;
296
297    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
298        if (atoms[i] != None) {
299            atomsPresent |= bit;
300            nAtoms++;
301        }
302    }
303    if (count)
304        *count = nAtoms;
305    return atomsPresent;
306}
307
308static void
309_XkbCopyAtoms(Display *dpy, Atom *atoms, CARD32 mask, int maxAtoms)
310{
311    register unsigned int i, bit;
312
313    for (i = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
314        if (mask & bit)
315            Data32(dpy, &atoms[i], 4);
316    }
317    return;
318}
319
320Bool
321XkbSetNames(Display *dpy,
322            unsigned int which,
323            unsigned int firstType,
324            unsigned int nTypes,
325            XkbDescPtr xkb)
326{
327    register xkbSetNamesReq *req;
328    int nLvlNames = 0;
329    XkbInfoPtr xkbi;
330    XkbNamesPtr names;
331    unsigned firstLvlType, nLvlTypes;
332    int nVMods, nLEDs, nRG, nKA, nGroups;
333    int nKeys = 0, firstKey = 0, nAtoms;
334    CARD32 leds, vmods, groups;
335
336    if ((dpy->flags & XlibDisplayNoXkb) ||
337        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
338        return False;
339    if ((!xkb) || (!xkb->names))
340        return False;
341    firstLvlType = firstType;
342    nLvlTypes = nTypes;
343    if (nTypes < 1)
344        which &= ~(XkbKTLevelNamesMask | XkbKeyTypeNamesMask);
345    else if (firstType <= XkbLastRequiredType) {
346        int adjust;
347
348        adjust = XkbLastRequiredType - firstType + 1;
349        firstType += adjust;
350        nTypes -= adjust;
351        if (nTypes < 1)
352            which &= ~XkbKeyTypeNamesMask;
353    }
354    names = xkb->names;
355    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
356        register int i;
357        XkbKeyTypePtr type;
358
359        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
360            (firstType + nTypes > xkb->map->num_types) ||
361            (firstLvlType + nLvlTypes > xkb->map->num_types))
362            return False;
363        if (which & XkbKTLevelNamesMask) {
364            type = &xkb->map->types[firstLvlType];
365            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
366                if (type->level_names != NULL)
367                    nLvlNames += type->num_levels;
368            }
369        }
370    }
371
372    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
373    LockDisplay(dpy);
374    xkbi = dpy->xkb_info;
375    GetReq(kbSetNames, req);
376    req->reqType = xkbi->codes->major_opcode;
377    req->xkbReqType = X_kbSetNames;
378    req->deviceSpec = xkb->device_spec;
379    req->firstType = firstType;
380    req->nTypes = nTypes;
381    req->firstKey = xkb->min_key_code;
382    req->nKeys = xkb->max_key_code - xkb->min_key_code + 1;
383
384    if (which & XkbKeycodesNameMask)
385        nAtoms++;
386    if (which & XkbGeometryNameMask)
387        nAtoms++;
388    if (which & XkbSymbolsNameMask)
389        nAtoms++;
390    if (which & XkbPhysSymbolsNameMask)
391        nAtoms++;
392    if (which & XkbTypesNameMask)
393        nAtoms++;
394    if (which & XkbCompatNameMask)
395        nAtoms++;
396    if (which & XkbKeyTypeNamesMask)
397        nAtoms += nTypes;
398    if (which & XkbKTLevelNamesMask) {
399        req->firstKTLevel = firstLvlType;
400        req->nKTLevels = nLvlTypes;
401        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
402        nAtoms += nLvlNames;
403    }
404    else
405        req->firstKTLevel = req->nKTLevels = 0;
406
407    if (which & XkbIndicatorNamesMask) {
408        req->indicators = leds =
409            _XkbCountAtoms(names->indicators, XkbNumIndicators, &nLEDs);
410        if (nLEDs > 0)
411            nAtoms += nLEDs;
412        else
413            which &= ~XkbIndicatorNamesMask;
414    }
415    else
416        req->indicators = leds = 0;
417
418    if (which & XkbVirtualModNamesMask) {
419        vmods = req->virtualMods = (CARD16)
420            _XkbCountAtoms(names->vmods, XkbNumVirtualMods, &nVMods);
421        if (nVMods > 0)
422            nAtoms += nVMods;
423        else
424            which &= ~XkbVirtualModNamesMask;
425    }
426    else
427        vmods = req->virtualMods = 0;
428
429    if (which & XkbGroupNamesMask) {
430        groups = req->groupNames = (CARD8)
431            _XkbCountAtoms(names->groups, XkbNumKbdGroups, &nGroups);
432        if (nGroups > 0)
433            nAtoms += nGroups;
434        else
435            which &= ~XkbGroupNamesMask;
436    }
437    else
438        groups = req->groupNames = 0;
439
440    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
441        firstKey = req->firstKey;
442        nKeys = req->nKeys;
443        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
444    }
445    else
446        which &= ~XkbKeyNamesMask;
447
448    if (which & XkbKeyAliasesMask) {
449        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
450        if (nKA > 0) {
451            req->nKeyAliases = nKA;
452            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
453        }
454        else {
455            which &= ~XkbKeyAliasesMask;
456            req->nKeyAliases = 0;
457        }
458    }
459    else
460        req->nKeyAliases = 0;
461
462    if (which & XkbRGNamesMask) {
463        nRG = names->num_rg;
464        if (nRG > 0)
465            nAtoms += nRG;
466        else
467            which &= ~XkbRGNamesMask;
468    }
469
470    req->which = which;
471    req->nRadioGroups = nRG;
472    req->length += (nAtoms * 4) / 4;
473
474    if (which & XkbKeycodesNameMask)
475        Data32(dpy, (long *) &names->keycodes, 4);
476    if (which & XkbGeometryNameMask)
477        Data32(dpy, (long *) &names->geometry, 4);
478    if (which & XkbSymbolsNameMask)
479        Data32(dpy, (long *) &names->symbols, 4);
480    if (which & XkbPhysSymbolsNameMask)
481        Data32(dpy, (long *) &names->phys_symbols, 4);
482    if (which & XkbTypesNameMask)
483        Data32(dpy, (long *) &names->types, 4);
484    if (which & XkbCompatNameMask)
485        Data32(dpy, (long *) &names->compat, 4);
486    if (which & XkbKeyTypeNamesMask) {
487        register int i;
488        register XkbKeyTypePtr type;
489
490        type = &xkb->map->types[firstType];
491        for (i = 0; i < nTypes; i++, type++) {
492            Data32(dpy, (long *) &type->name, 4);
493        }
494    }
495    if (which & XkbKTLevelNamesMask) {
496        XkbKeyTypePtr type;
497        int i;
498        char *tmp;
499
500        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
501        type = &xkb->map->types[firstLvlType];
502        for (i = 0; i < nLvlTypes; i++, type++) {
503            *tmp++ = type->num_levels;
504        }
505        type = &xkb->map->types[firstLvlType];
506        for (i = 0; i < nLvlTypes; i++, type++) {
507            if (type->level_names != NULL)
508                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
509        }
510    }
511    if (which & XkbIndicatorNamesMask)
512        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
513    if (which & XkbVirtualModNamesMask)
514        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
515    if (which & XkbGroupNamesMask)
516        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
517    if (which & XkbKeyNamesMask) {
518        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
519    }
520    if (which & XkbKeyAliasesMask) {
521        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
522    }
523    if (which & XkbRGNamesMask) {
524        Data32(dpy, (long *) names->radio_groups, nRG * 4);
525    }
526    UnlockDisplay(dpy);
527    SyncHandle();
528    return True;
529}
530
531Bool
532XkbChangeNames(Display *dpy, XkbDescPtr xkb, XkbNameChangesPtr changes)
533{
534    register xkbSetNamesReq *req;
535    int nLvlNames = 0;
536    XkbInfoPtr xkbi;
537    XkbNamesPtr names;
538    unsigned which, firstType, nTypes;
539    unsigned firstLvlType, nLvlTypes;
540    int nVMods, nLEDs, nRG, nKA, nGroups;
541    int nKeys = 0, firstKey = 0, nAtoms;
542    CARD32 leds = 0, vmods = 0, groups = 0;
543
544    if ((dpy->flags & XlibDisplayNoXkb) ||
545        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
546        return False;
547    if ((!xkb) || (!xkb->names) || (!changes))
548        return False;
549    which = changes->changed;
550    firstType = changes->first_type;
551    nTypes = changes->num_types;
552    firstLvlType = changes->first_lvl;;
553    nLvlTypes = changes->num_lvls;
554    if (which & XkbKeyTypeNamesMask) {
555        if (nTypes < 1)
556            which &= ~XkbKeyTypeNamesMask;
557        else if (firstType <= XkbLastRequiredType) {
558            int adjust;
559
560            adjust = XkbLastRequiredType - firstType + 1;
561            firstType += adjust;
562            nTypes -= adjust;
563            if (nTypes < 1)
564                which &= ~XkbKeyTypeNamesMask;
565        }
566    }
567    else
568        firstType = nTypes = 0;
569
570    if (which & XkbKTLevelNamesMask) {
571        if (nLvlTypes < 1)
572            which &= ~XkbKTLevelNamesMask;
573    }
574    else
575        firstLvlType = nLvlTypes = 0;
576
577    names = xkb->names;
578    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
579        register int i;
580
581        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
582            (firstType + nTypes > xkb->map->num_types) ||
583            (firstLvlType + nLvlTypes > xkb->map->num_types))
584            return False;
585        if (which & XkbKTLevelNamesMask) {
586            XkbKeyTypePtr type = &xkb->map->types[firstLvlType];
587
588            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
589                if (type->level_names != NULL)
590                    nLvlNames += type->num_levels;
591            }
592        }
593    }
594
595    if (changes->num_keys < 1)
596        which &= ~XkbKeyNamesMask;
597    if ((which & XkbKeyNamesMask) == 0)
598        changes->first_key = changes->num_keys = 0;
599    else if ((changes->first_key < xkb->min_key_code) ||
600             (changes->first_key + changes->num_keys > xkb->max_key_code)) {
601        return False;
602    }
603
604    if ((which & XkbVirtualModNamesMask) == 0)
605        changes->changed_vmods = 0;
606    else if (changes->changed_vmods == 0)
607        which &= ~XkbVirtualModNamesMask;
608
609    if ((which & XkbIndicatorNamesMask) == 0)
610        changes->changed_indicators = 0;
611    else if (changes->changed_indicators == 0)
612        which &= ~XkbIndicatorNamesMask;
613
614    if ((which & XkbGroupNamesMask) == 0)
615        changes->changed_groups = 0;
616    else if (changes->changed_groups == 0)
617        which &= ~XkbGroupNamesMask;
618
619    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
620    LockDisplay(dpy);
621    xkbi = dpy->xkb_info;
622    GetReq(kbSetNames, req);
623    req->reqType = xkbi->codes->major_opcode;
624    req->xkbReqType = X_kbSetNames;
625    req->deviceSpec = xkb->device_spec;
626    req->firstType = firstType;
627    req->nTypes = nTypes;
628    req->firstKey = changes->first_key;
629    req->nKeys = changes->num_keys;
630
631    if (which & XkbKeycodesNameMask)
632        nAtoms++;
633    if (which & XkbGeometryNameMask)
634        nAtoms++;
635    if (which & XkbSymbolsNameMask)
636        nAtoms++;
637    if (which & XkbPhysSymbolsNameMask)
638        nAtoms++;
639    if (which & XkbTypesNameMask)
640        nAtoms++;
641    if (which & XkbCompatNameMask)
642        nAtoms++;
643    if (which & XkbKeyTypeNamesMask)
644        nAtoms += nTypes;
645    if (which & XkbKTLevelNamesMask) {
646        req->firstKTLevel = firstLvlType;
647        req->nKTLevels = nLvlTypes;
648        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
649        nAtoms += nLvlNames;
650    }
651    else
652        req->firstKTLevel = req->nKTLevels = 0;
653
654    if (which & XkbIndicatorNamesMask) {
655        leds = req->indicators = (CARD32) changes->changed_indicators;
656        nLEDs = _XkbCountBits(XkbNumIndicators, changes->changed_indicators);
657        if (nLEDs > 0)
658            nAtoms += nLEDs;
659        else
660            which &= ~XkbIndicatorNamesMask;
661    }
662    else
663        req->indicators = 0;
664
665    if (which & XkbVirtualModNamesMask) {
666        vmods = req->virtualMods = changes->changed_vmods;
667        nVMods = _XkbCountBits(XkbNumVirtualMods,
668                               (unsigned long) changes->changed_vmods);
669        if (nVMods > 0)
670            nAtoms += nVMods;
671        else
672            which &= ~XkbVirtualModNamesMask;
673    }
674    else
675        req->virtualMods = 0;
676
677    if (which & XkbGroupNamesMask) {
678        groups = req->groupNames = changes->changed_groups;
679        nGroups = _XkbCountBits(XkbNumKbdGroups,
680                                (unsigned long) changes->changed_groups);
681        if (nGroups > 0)
682            nAtoms += nGroups;
683        else
684            which &= ~XkbGroupNamesMask;
685    }
686    else
687        req->groupNames = 0;
688
689    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
690        firstKey = req->firstKey;
691        nKeys = req->nKeys;
692        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
693    }
694    else
695        which &= ~XkbKeyNamesMask;
696
697    if (which & XkbKeyAliasesMask) {
698        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
699        if (nKA > 0)
700            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
701        else
702            which &= ~XkbKeyAliasesMask;
703    }
704
705    if (which & XkbRGNamesMask) {
706        nRG = names->num_rg;
707        if (nRG > 0)
708            nAtoms += nRG;
709        else
710            which &= ~XkbRGNamesMask;
711    }
712
713    req->which = which;
714    req->nRadioGroups = nRG;
715    req->length += (nAtoms * 4) / 4;
716
717    if (which & XkbKeycodesNameMask)
718        Data32(dpy, (long *) &names->keycodes, 4);
719    if (which & XkbGeometryNameMask)
720        Data32(dpy, (long *) &names->geometry, 4);
721    if (which & XkbSymbolsNameMask)
722        Data32(dpy, (long *) &names->symbols, 4);
723    if (which & XkbPhysSymbolsNameMask)
724        Data32(dpy, (long *) &names->phys_symbols, 4);
725    if (which & XkbTypesNameMask)
726        Data32(dpy, (long *) &names->types, 4);
727    if (which & XkbCompatNameMask)
728        Data32(dpy, (long *) &names->compat, 4);
729    if (which & XkbKeyTypeNamesMask) {
730        register int i;
731        register XkbKeyTypePtr type;
732
733        type = &xkb->map->types[firstType];
734        for (i = 0; i < nTypes; i++, type++) {
735            Data32(dpy, (long *) &type->name, 4);
736        }
737    }
738    if (which & XkbKTLevelNamesMask) {
739        XkbKeyTypePtr type;
740        int i;
741        char *tmp;
742
743        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
744        type = &xkb->map->types[firstLvlType];
745        for (i = 0; i < nLvlTypes; i++, type++) {
746            *tmp++ = type->num_levels;
747        }
748        type = &xkb->map->types[firstLvlType];
749        for (i = 0; i < nLvlTypes; i++, type++) {
750            if (type->level_names != NULL)
751                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
752        }
753    }
754    if (which & XkbIndicatorNamesMask)
755        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
756    if (which & XkbVirtualModNamesMask)
757        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
758    if (which & XkbGroupNamesMask)
759        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
760    if (which & XkbKeyNamesMask) {
761        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
762    }
763    if (which & XkbKeyAliasesMask) {
764        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
765    }
766    if (which & XkbRGNamesMask) {
767        Data32(dpy, (long *) names->radio_groups, nRG * 4);
768    }
769    UnlockDisplay(dpy);
770    SyncHandle();
771    return True;
772}
773
774void
775XkbNoteNameChanges(XkbNameChangesPtr old,
776                   XkbNamesNotifyEvent *new,
777                   unsigned int wanted)
778{
779    int first, last, old_last, new_last;
780
781    if ((old == NULL) || (new == NULL))
782        return;
783
784    wanted &= new->changed;
785
786    if (wanted == 0)
787	return;
788
789    if (wanted & XkbKeyTypeNamesMask) {
790        if (old->changed & XkbKeyTypeNamesMask) {
791            new_last = (new->first_type + new->num_types - 1);
792            old_last = (old->first_type + old->num_types - 1);
793
794            if (new->first_type < old->first_type)
795                first = new->first_type;
796            else
797                first = old->first_type;
798
799            if (old_last > new_last)
800                last = old_last;
801            else
802                last = new_last;
803
804            old->first_type = first;
805            old->num_types = (last - first) + 1;
806        }
807        else {
808            old->first_type = new->first_type;
809            old->num_types = new->num_types;
810        }
811    }
812    if (wanted & XkbKTLevelNamesMask) {
813        if (old->changed & XkbKTLevelNamesMask) {
814            new_last = (new->first_lvl + new->num_lvls - 1);
815            old_last = (old->first_lvl + old->num_lvls - 1);
816
817            if (new->first_lvl < old->first_lvl)
818                first = new->first_lvl;
819            else
820                first = old->first_lvl;
821
822            if (old_last > new_last)
823                last = old_last;
824            else
825                last = new_last;
826
827            old->first_lvl = first;
828            old->num_lvls = (last - first) + 1;
829        }
830        else {
831            old->first_lvl = new->first_lvl;
832            old->num_lvls = new->num_lvls;
833        }
834    }
835    if (wanted & XkbIndicatorNamesMask) {
836        if (old->changed & XkbIndicatorNamesMask)
837            old->changed_indicators |= new->changed_indicators;
838        else
839            old->changed_indicators = new->changed_indicators;
840    }
841    if (wanted & XkbKeyNamesMask) {
842        if (old->changed & XkbKeyNamesMask) {
843            new_last = (new->first_key + new->num_keys - 1);
844            old_last = (old->first_key + old->num_keys - 1);
845
846            first = old->first_key;
847
848            if (new->first_key < old->first_key)
849                first = new->first_key;
850            if (old_last > new_last)
851                new_last = old_last;
852
853            old->first_key = first;
854            old->num_keys = (new_last - first) + 1;
855        }
856        else {
857            old->first_key = new->first_key;
858            old->num_keys = new->num_keys;
859        }
860    }
861    if (wanted & XkbVirtualModNamesMask) {
862        if (old->changed & XkbVirtualModNamesMask)
863            old->changed_vmods |= new->changed_vmods;
864        else
865            old->changed_vmods = new->changed_vmods;
866    }
867    if (wanted & XkbGroupNamesMask) {
868        if (old->changed & XkbGroupNamesMask)
869            old->changed_groups |= new->changed_groups;
870        else
871            old->changed_groups = new->changed_groups;
872    }
873    if (wanted & XkbRGNamesMask)
874        old->num_rg = new->num_radio_groups;
875    if (wanted & XkbKeyAliasesMask)
876        old->num_aliases = new->num_aliases;
877    old->changed |= wanted;
878    return;
879}
880