1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3 
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15 
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE 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 
36 static Status
_XkbReadAtoms(XkbReadBufferPtr buf,Atom * atoms,int maxAtoms,CARD32 present)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 
54 Status
_XkbReadGetNamesReply(Display * dpy,xkbGetNamesReply * rep,XkbDescPtr xkb,int * nread_rtrn)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->num_rg < rep->nRadioGroups)) {
210                 _XkbResizeArray(names->radio_groups, names->num_rg,
211                                 rep->nRadioGroups, Atom);
212             }
213             rgNames = names->radio_groups;
214             if (!rgNames) {
215                 names->num_rg = 0;
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 
238 Status
XkbGetNames(Display * dpy,unsigned which,XkbDescPtr xkb)239 XkbGetNames(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 
278 static int
_XkbCountBits(int nBitsMax,unsigned long mask)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 
291 static CARD32
_XkbCountAtoms(Atom * atoms,int maxAtoms,int * count)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 
308 static void
_XkbCopyAtoms(Display * dpy,Atom * atoms,CARD32 mask,int maxAtoms)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 
320 Bool
XkbSetNames(Display * dpy,unsigned int which,unsigned int firstType,unsigned int nTypes,XkbDescPtr xkb)321 XkbSetNames(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 
531 Bool
XkbChangeNames(Display * dpy,XkbDescPtr xkb,XkbNameChangesPtr changes)532 XkbChangeNames(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 
774 void
XkbNoteNameChanges(XkbNameChangesPtr old,XkbNamesNotifyEvent * new,unsigned int wanted)775 XkbNoteNameChanges(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