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            names->num_keys = rep->nKeys;
193        }
194        else
195            _XkbSkipReadBufferData(&buf, rep->nKeys * XkbKeyNameLength);
196    }
197    if (rep->which & XkbKeyAliasesMask && (rep->nKeyAliases > 0)) {
198        if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, rep->nKeyAliases) !=
199            Success)
200            goto BAILOUT;
201        if (!_XkbCopyFromReadBuffer(&buf, (char *) names->key_aliases,
202                                    rep->nKeyAliases * XkbKeyNameLength * 2))
203            goto BAILOUT;
204    }
205    if (rep->which & XkbRGNamesMask) {
206        if (rep->nRadioGroups > 0) {
207            Atom *rgNames;
208
209            if ((names->radio_groups == NULL) ||
210                (names->num_rg < rep->nRadioGroups)) {
211                _XkbResizeArray(names->radio_groups, names->num_rg,
212                                rep->nRadioGroups, Atom);
213            }
214            rgNames = names->radio_groups;
215            if (!rgNames) {
216                names->num_rg = 0;
217                goto BAILOUT;
218            }
219            if (!_XkbReadBufferCopy32
220                (&buf, (long *) rgNames, rep->nRadioGroups))
221                goto BAILOUT;
222            names->num_rg = rep->nRadioGroups;
223        }
224        else if (names->num_rg > 0) {
225            names->num_rg = 0;
226            Xfree(names->radio_groups);
227        }
228    }
229    len = _XkbFreeReadBuffer(&buf);
230    if (len != 0)
231        return BadLength;
232    else
233        return Success;
234 BAILOUT:
235    _XkbFreeReadBuffer(&buf);
236    return BadLength;
237}
238
239Status
240XkbGetNames(Display *dpy, unsigned which, XkbDescPtr xkb)
241{
242    register xkbGetNamesReq *req;
243    xkbGetNamesReply rep;
244    Status status;
245    XkbInfoPtr xkbi;
246
247    if ((dpy->flags & XlibDisplayNoXkb) ||
248        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
249        return BadAccess;
250    LockDisplay(dpy);
251    xkbi = dpy->xkb_info;
252    if (!xkb->names) {
253        xkb->names = _XkbTypedCalloc(1, XkbNamesRec);
254        if (!xkb->names) {
255            UnlockDisplay(dpy);
256            SyncHandle();
257            return BadAlloc;
258        }
259    }
260    GetReq(kbGetNames, req);
261    req->reqType = xkbi->codes->major_opcode;
262    req->xkbReqType = X_kbGetNames;
263    req->deviceSpec = xkb->device_spec;
264    req->which = which;
265    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
266        UnlockDisplay(dpy);
267        SyncHandle();
268        return BadImplementation;
269    }
270
271    status = _XkbReadGetNamesReply(dpy, &rep, xkb, NULL);
272    UnlockDisplay(dpy);
273    SyncHandle();
274    return status;
275}
276
277/***====================================================================***/
278
279static int
280_XkbCountBits(int nBitsMax, unsigned long mask)
281{
282    register unsigned long y, nBits;
283
284    y = (mask >> 1) & 033333333333;
285    y = mask - y - ((y >> 1) & 033333333333);
286    nBits = ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077));
287
288    /* nBitsMax really means max+1 */
289    return (nBits < nBitsMax) ? nBits : (nBitsMax - 1);
290}
291
292static CARD32
293_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
294{
295    register unsigned int i, bit, nAtoms;
296    register CARD32 atomsPresent;
297
298    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
299        if (atoms[i] != None) {
300            atomsPresent |= bit;
301            nAtoms++;
302        }
303    }
304    if (count)
305        *count = nAtoms;
306    return atomsPresent;
307}
308
309static void
310_XkbCopyAtoms(Display *dpy, Atom *atoms, CARD32 mask, int maxAtoms)
311{
312    register unsigned int i, bit;
313
314    for (i = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
315        if (mask & bit)
316            Data32(dpy, &atoms[i], 4);
317    }
318    return;
319}
320
321Bool
322XkbSetNames(Display *dpy,
323            unsigned int which,
324            unsigned int firstType,
325            unsigned int nTypes,
326            XkbDescPtr xkb)
327{
328    register xkbSetNamesReq *req;
329    int nLvlNames = 0;
330    XkbInfoPtr xkbi;
331    XkbNamesPtr names;
332    unsigned firstLvlType, nLvlTypes;
333    int nVMods, nLEDs, nRG, nKA, nGroups;
334    int nKeys = 0, firstKey = 0, nAtoms;
335    CARD32 leds, vmods, groups;
336
337    if ((dpy->flags & XlibDisplayNoXkb) ||
338        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
339        return False;
340    if ((!xkb) || (!xkb->names))
341        return False;
342    firstLvlType = firstType;
343    nLvlTypes = nTypes;
344    if (nTypes < 1)
345        which &= ~(XkbKTLevelNamesMask | XkbKeyTypeNamesMask);
346    else if (firstType <= XkbLastRequiredType) {
347        int adjust;
348
349        adjust = XkbLastRequiredType - firstType + 1;
350        firstType += adjust;
351        nTypes -= adjust;
352        if (nTypes < 1)
353            which &= ~XkbKeyTypeNamesMask;
354    }
355    names = xkb->names;
356    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
357        register int i;
358        XkbKeyTypePtr type;
359
360        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
361            (firstType + nTypes > xkb->map->num_types) ||
362            (firstLvlType + nLvlTypes > xkb->map->num_types))
363            return False;
364        if (which & XkbKTLevelNamesMask) {
365            type = &xkb->map->types[firstLvlType];
366            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
367                if (type->level_names != NULL)
368                    nLvlNames += type->num_levels;
369            }
370        }
371    }
372
373    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
374    LockDisplay(dpy);
375    xkbi = dpy->xkb_info;
376    GetReq(kbSetNames, req);
377    req->reqType = xkbi->codes->major_opcode;
378    req->xkbReqType = X_kbSetNames;
379    req->deviceSpec = xkb->device_spec;
380    req->firstType = firstType;
381    req->nTypes = nTypes;
382    req->firstKey = xkb->min_key_code;
383    req->nKeys = xkb->max_key_code - xkb->min_key_code + 1;
384
385    if (which & XkbKeycodesNameMask)
386        nAtoms++;
387    if (which & XkbGeometryNameMask)
388        nAtoms++;
389    if (which & XkbSymbolsNameMask)
390        nAtoms++;
391    if (which & XkbPhysSymbolsNameMask)
392        nAtoms++;
393    if (which & XkbTypesNameMask)
394        nAtoms++;
395    if (which & XkbCompatNameMask)
396        nAtoms++;
397    if (which & XkbKeyTypeNamesMask)
398        nAtoms += nTypes;
399    if (which & XkbKTLevelNamesMask) {
400        req->firstKTLevel = firstLvlType;
401        req->nKTLevels = nLvlTypes;
402        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
403        nAtoms += nLvlNames;
404    }
405    else
406        req->firstKTLevel = req->nKTLevels = 0;
407
408    if (which & XkbIndicatorNamesMask) {
409        req->indicators = leds =
410            _XkbCountAtoms(names->indicators, XkbNumIndicators, &nLEDs);
411        if (nLEDs > 0)
412            nAtoms += nLEDs;
413        else
414            which &= ~XkbIndicatorNamesMask;
415    }
416    else
417        req->indicators = leds = 0;
418
419    if (which & XkbVirtualModNamesMask) {
420        vmods = req->virtualMods = (CARD16)
421            _XkbCountAtoms(names->vmods, XkbNumVirtualMods, &nVMods);
422        if (nVMods > 0)
423            nAtoms += nVMods;
424        else
425            which &= ~XkbVirtualModNamesMask;
426    }
427    else
428        vmods = req->virtualMods = 0;
429
430    if (which & XkbGroupNamesMask) {
431        groups = req->groupNames = (CARD8)
432            _XkbCountAtoms(names->groups, XkbNumKbdGroups, &nGroups);
433        if (nGroups > 0)
434            nAtoms += nGroups;
435        else
436            which &= ~XkbGroupNamesMask;
437    }
438    else
439        groups = req->groupNames = 0;
440
441    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
442        firstKey = req->firstKey;
443        nKeys = req->nKeys;
444        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
445    }
446    else
447        which &= ~XkbKeyNamesMask;
448
449    if (which & XkbKeyAliasesMask) {
450        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
451        if (nKA > 0) {
452            req->nKeyAliases = nKA;
453            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
454        }
455        else {
456            which &= ~XkbKeyAliasesMask;
457            req->nKeyAliases = 0;
458        }
459    }
460    else
461        req->nKeyAliases = 0;
462
463    if (which & XkbRGNamesMask) {
464        nRG = names->num_rg;
465        if (nRG > 0)
466            nAtoms += nRG;
467        else
468            which &= ~XkbRGNamesMask;
469    }
470
471    req->which = which;
472    req->nRadioGroups = nRG;
473    req->length += (nAtoms * 4) / 4;
474
475    if (which & XkbKeycodesNameMask)
476        Data32(dpy, (long *) &names->keycodes, 4);
477    if (which & XkbGeometryNameMask)
478        Data32(dpy, (long *) &names->geometry, 4);
479    if (which & XkbSymbolsNameMask)
480        Data32(dpy, (long *) &names->symbols, 4);
481    if (which & XkbPhysSymbolsNameMask)
482        Data32(dpy, (long *) &names->phys_symbols, 4);
483    if (which & XkbTypesNameMask)
484        Data32(dpy, (long *) &names->types, 4);
485    if (which & XkbCompatNameMask)
486        Data32(dpy, (long *) &names->compat, 4);
487    if (which & XkbKeyTypeNamesMask) {
488        register int i;
489        register XkbKeyTypePtr type;
490
491        type = &xkb->map->types[firstType];
492        for (i = 0; i < nTypes; i++, type++) {
493            Data32(dpy, (long *) &type->name, 4);
494        }
495    }
496    if (which & XkbKTLevelNamesMask) {
497        XkbKeyTypePtr type;
498        int i;
499        char *tmp;
500
501        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
502        type = &xkb->map->types[firstLvlType];
503        for (i = 0; i < nLvlTypes; i++, type++) {
504            *tmp++ = type->num_levels;
505        }
506        type = &xkb->map->types[firstLvlType];
507        for (i = 0; i < nLvlTypes; i++, type++) {
508            if (type->level_names != NULL)
509                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
510        }
511    }
512    if (which & XkbIndicatorNamesMask)
513        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
514    if (which & XkbVirtualModNamesMask)
515        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
516    if (which & XkbGroupNamesMask)
517        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
518    if (which & XkbKeyNamesMask) {
519        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
520    }
521    if (which & XkbKeyAliasesMask) {
522        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
523    }
524    if (which & XkbRGNamesMask) {
525        Data32(dpy, (long *) names->radio_groups, nRG * 4);
526    }
527    UnlockDisplay(dpy);
528    SyncHandle();
529    return True;
530}
531
532Bool
533XkbChangeNames(Display *dpy, XkbDescPtr xkb, XkbNameChangesPtr changes)
534{
535    register xkbSetNamesReq *req;
536    int nLvlNames = 0;
537    XkbInfoPtr xkbi;
538    XkbNamesPtr names;
539    unsigned which, firstType, nTypes;
540    unsigned firstLvlType, nLvlTypes;
541    int nVMods, nLEDs, nRG, nKA, nGroups;
542    int nKeys = 0, firstKey = 0, nAtoms;
543    CARD32 leds = 0, vmods = 0, groups = 0;
544
545    if ((dpy->flags & XlibDisplayNoXkb) ||
546        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
547        return False;
548    if ((!xkb) || (!xkb->names) || (!changes))
549        return False;
550    which = changes->changed;
551    firstType = changes->first_type;
552    nTypes = changes->num_types;
553    firstLvlType = changes->first_lvl;
554    nLvlTypes = changes->num_lvls;
555    if (which & XkbKeyTypeNamesMask) {
556        if (nTypes < 1)
557            which &= ~XkbKeyTypeNamesMask;
558        else if (firstType <= XkbLastRequiredType) {
559            int adjust;
560
561            adjust = XkbLastRequiredType - firstType + 1;
562            firstType += adjust;
563            nTypes -= adjust;
564            if (nTypes < 1)
565                which &= ~XkbKeyTypeNamesMask;
566        }
567    }
568    else
569        firstType = nTypes = 0;
570
571    if (which & XkbKTLevelNamesMask) {
572        if (nLvlTypes < 1)
573            which &= ~XkbKTLevelNamesMask;
574    }
575    else
576        firstLvlType = nLvlTypes = 0;
577
578    names = xkb->names;
579    if (which & (XkbKTLevelNamesMask | XkbKeyTypeNamesMask)) {
580        register int i;
581
582        if ((xkb->map == NULL) || (xkb->map->types == NULL) || (nTypes == 0) ||
583            (firstType + nTypes > xkb->map->num_types) ||
584            (firstLvlType + nLvlTypes > xkb->map->num_types))
585            return False;
586        if (which & XkbKTLevelNamesMask) {
587            XkbKeyTypePtr type = &xkb->map->types[firstLvlType];
588
589            for (i = nLvlNames = 0; i < nLvlTypes; i++, type++) {
590                if (type->level_names != NULL)
591                    nLvlNames += type->num_levels;
592            }
593        }
594    }
595
596    if (changes->num_keys < 1)
597        which &= ~XkbKeyNamesMask;
598    if ((which & XkbKeyNamesMask) == 0)
599        changes->first_key = changes->num_keys = 0;
600    else if ((changes->first_key < xkb->min_key_code) ||
601             (changes->first_key + changes->num_keys > xkb->max_key_code)) {
602        return False;
603    }
604
605    if ((which & XkbVirtualModNamesMask) == 0)
606        changes->changed_vmods = 0;
607    else if (changes->changed_vmods == 0)
608        which &= ~XkbVirtualModNamesMask;
609
610    if ((which & XkbIndicatorNamesMask) == 0)
611        changes->changed_indicators = 0;
612    else if (changes->changed_indicators == 0)
613        which &= ~XkbIndicatorNamesMask;
614
615    if ((which & XkbGroupNamesMask) == 0)
616        changes->changed_groups = 0;
617    else if (changes->changed_groups == 0)
618        which &= ~XkbGroupNamesMask;
619
620    nVMods = nLEDs = nRG = nKA = nAtoms = nGroups = 0;
621    LockDisplay(dpy);
622    xkbi = dpy->xkb_info;
623    GetReq(kbSetNames, req);
624    req->reqType = xkbi->codes->major_opcode;
625    req->xkbReqType = X_kbSetNames;
626    req->deviceSpec = xkb->device_spec;
627    req->firstType = firstType;
628    req->nTypes = nTypes;
629    req->firstKey = changes->first_key;
630    req->nKeys = changes->num_keys;
631
632    if (which & XkbKeycodesNameMask)
633        nAtoms++;
634    if (which & XkbGeometryNameMask)
635        nAtoms++;
636    if (which & XkbSymbolsNameMask)
637        nAtoms++;
638    if (which & XkbPhysSymbolsNameMask)
639        nAtoms++;
640    if (which & XkbTypesNameMask)
641        nAtoms++;
642    if (which & XkbCompatNameMask)
643        nAtoms++;
644    if (which & XkbKeyTypeNamesMask)
645        nAtoms += nTypes;
646    if (which & XkbKTLevelNamesMask) {
647        req->firstKTLevel = firstLvlType;
648        req->nKTLevels = nLvlTypes;
649        req->length += XkbPaddedSize(nLvlTypes) / 4;    /* room for group widths */
650        nAtoms += nLvlNames;
651    }
652    else
653        req->firstKTLevel = req->nKTLevels = 0;
654
655    if (which & XkbIndicatorNamesMask) {
656        leds = req->indicators = (CARD32) changes->changed_indicators;
657        nLEDs = _XkbCountBits(XkbNumIndicators, changes->changed_indicators);
658        if (nLEDs > 0)
659            nAtoms += nLEDs;
660        else
661            which &= ~XkbIndicatorNamesMask;
662    }
663    else
664        req->indicators = 0;
665
666    if (which & XkbVirtualModNamesMask) {
667        vmods = req->virtualMods = changes->changed_vmods;
668        nVMods = _XkbCountBits(XkbNumVirtualMods,
669                               (unsigned long) changes->changed_vmods);
670        if (nVMods > 0)
671            nAtoms += nVMods;
672        else
673            which &= ~XkbVirtualModNamesMask;
674    }
675    else
676        req->virtualMods = 0;
677
678    if (which & XkbGroupNamesMask) {
679        groups = req->groupNames = changes->changed_groups;
680        nGroups = _XkbCountBits(XkbNumKbdGroups,
681                                (unsigned long) changes->changed_groups);
682        if (nGroups > 0)
683            nAtoms += nGroups;
684        else
685            which &= ~XkbGroupNamesMask;
686    }
687    else
688        req->groupNames = 0;
689
690    if ((which & XkbKeyNamesMask) && (names->keys != NULL)) {
691        firstKey = req->firstKey;
692        nKeys = req->nKeys;
693        nAtoms += nKeys;        /* technically not atoms, but 4 bytes wide */
694    }
695    else
696        which &= ~XkbKeyNamesMask;
697
698    if (which & XkbKeyAliasesMask) {
699        nKA = ((names->key_aliases != NULL) ? names->num_key_aliases : 0);
700        if (nKA > 0)
701            nAtoms += nKA * 2;  /* not atoms, but 8 bytes on the wire */
702        else
703            which &= ~XkbKeyAliasesMask;
704    }
705
706    if (which & XkbRGNamesMask) {
707        nRG = names->num_rg;
708        if (nRG > 0)
709            nAtoms += nRG;
710        else
711            which &= ~XkbRGNamesMask;
712    }
713
714    req->which = which;
715    req->nRadioGroups = nRG;
716    req->length += (nAtoms * 4) / 4;
717
718    if (which & XkbKeycodesNameMask)
719        Data32(dpy, (long *) &names->keycodes, 4);
720    if (which & XkbGeometryNameMask)
721        Data32(dpy, (long *) &names->geometry, 4);
722    if (which & XkbSymbolsNameMask)
723        Data32(dpy, (long *) &names->symbols, 4);
724    if (which & XkbPhysSymbolsNameMask)
725        Data32(dpy, (long *) &names->phys_symbols, 4);
726    if (which & XkbTypesNameMask)
727        Data32(dpy, (long *) &names->types, 4);
728    if (which & XkbCompatNameMask)
729        Data32(dpy, (long *) &names->compat, 4);
730    if (which & XkbKeyTypeNamesMask) {
731        register int i;
732        register XkbKeyTypePtr type;
733
734        type = &xkb->map->types[firstType];
735        for (i = 0; i < nTypes; i++, type++) {
736            Data32(dpy, (long *) &type->name, 4);
737        }
738    }
739    if (which & XkbKTLevelNamesMask) {
740        XkbKeyTypePtr type;
741        int i;
742        char *tmp;
743
744        BufAlloc(char *, tmp, XkbPaddedSize(nLvlTypes));
745        type = &xkb->map->types[firstLvlType];
746        for (i = 0; i < nLvlTypes; i++, type++) {
747            *tmp++ = type->num_levels;
748        }
749        type = &xkb->map->types[firstLvlType];
750        for (i = 0; i < nLvlTypes; i++, type++) {
751            if (type->level_names != NULL)
752                Data32(dpy, (long *) type->level_names, type->num_levels * 4);
753        }
754    }
755    if (which & XkbIndicatorNamesMask)
756        _XkbCopyAtoms(dpy, names->indicators, leds, XkbNumIndicators);
757    if (which & XkbVirtualModNamesMask)
758        _XkbCopyAtoms(dpy, names->vmods, vmods, XkbNumVirtualMods);
759    if (which & XkbGroupNamesMask)
760        _XkbCopyAtoms(dpy, names->groups, groups, XkbNumKbdGroups);
761    if (which & XkbKeyNamesMask) {
762        Data(dpy, (char *) &names->keys[firstKey], nKeys * XkbKeyNameLength);
763    }
764    if (which & XkbKeyAliasesMask) {
765        Data(dpy, (char *) names->key_aliases, nKA * XkbKeyNameLength * 2);
766    }
767    if (which & XkbRGNamesMask) {
768        Data32(dpy, (long *) names->radio_groups, nRG * 4);
769    }
770    UnlockDisplay(dpy);
771    SyncHandle();
772    return True;
773}
774
775void
776XkbNoteNameChanges(XkbNameChangesPtr old,
777                   XkbNamesNotifyEvent *new,
778                   unsigned int wanted)
779{
780    int first, last, old_last, new_last;
781
782    if ((old == NULL) || (new == NULL))
783        return;
784
785    wanted &= new->changed;
786
787    if (wanted == 0)
788	return;
789
790    if (wanted & XkbKeyTypeNamesMask) {
791        if (old->changed & XkbKeyTypeNamesMask) {
792            new_last = (new->first_type + new->num_types - 1);
793            old_last = (old->first_type + old->num_types - 1);
794
795            if (new->first_type < old->first_type)
796                first = new->first_type;
797            else
798                first = old->first_type;
799
800            if (old_last > new_last)
801                last = old_last;
802            else
803                last = new_last;
804
805            old->first_type = first;
806            old->num_types = (last - first) + 1;
807        }
808        else {
809            old->first_type = new->first_type;
810            old->num_types = new->num_types;
811        }
812    }
813    if (wanted & XkbKTLevelNamesMask) {
814        if (old->changed & XkbKTLevelNamesMask) {
815            new_last = (new->first_lvl + new->num_lvls - 1);
816            old_last = (old->first_lvl + old->num_lvls - 1);
817
818            if (new->first_lvl < old->first_lvl)
819                first = new->first_lvl;
820            else
821                first = old->first_lvl;
822
823            if (old_last > new_last)
824                last = old_last;
825            else
826                last = new_last;
827
828            old->first_lvl = first;
829            old->num_lvls = (last - first) + 1;
830        }
831        else {
832            old->first_lvl = new->first_lvl;
833            old->num_lvls = new->num_lvls;
834        }
835    }
836    if (wanted & XkbIndicatorNamesMask) {
837        if (old->changed & XkbIndicatorNamesMask)
838            old->changed_indicators |= new->changed_indicators;
839        else
840            old->changed_indicators = new->changed_indicators;
841    }
842    if (wanted & XkbKeyNamesMask) {
843        if (old->changed & XkbKeyNamesMask) {
844            new_last = (new->first_key + new->num_keys - 1);
845            old_last = (old->first_key + old->num_keys - 1);
846
847            first = old->first_key;
848
849            if (new->first_key < old->first_key)
850                first = new->first_key;
851            if (old_last > new_last)
852                new_last = old_last;
853
854            old->first_key = first;
855            old->num_keys = (new_last - first) + 1;
856        }
857        else {
858            old->first_key = new->first_key;
859            old->num_keys = new->num_keys;
860        }
861    }
862    if (wanted & XkbVirtualModNamesMask) {
863        if (old->changed & XkbVirtualModNamesMask)
864            old->changed_vmods |= new->changed_vmods;
865        else
866            old->changed_vmods = new->changed_vmods;
867    }
868    if (wanted & XkbGroupNamesMask) {
869        if (old->changed & XkbGroupNamesMask)
870            old->changed_groups |= new->changed_groups;
871        else
872            old->changed_groups = new->changed_groups;
873    }
874    if (wanted & XkbRGNamesMask)
875        old->num_rg = new->num_radio_groups;
876    if (wanted & XkbKeyAliasesMask)
877        old->num_aliases = new->num_aliases;
878    old->changed |= wanted;
879    return;
880}
881