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