XKBNames.c revision b4ee4795
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_REPLIES
28#define NEED_EVENTS
29#define NEED_MAP_READERS
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33#include "Xlibint.h"
34#include <X11/extensions/XKBproto.h>
35#include "XKBlibint.h"
36
37
38static Status
39_XkbReadAtoms(	XkbReadBufferPtr	buf,
40		Atom *			atoms,
41		int			maxAtoms,
42		CARD32		 	present)
43{
44register int i,bit;
45
46    for (i=0,bit=1;(i<maxAtoms)&&(present);i++,bit<<=1) {
47	if (present&bit) {
48	    if (!_XkbReadBufferCopy32(buf,(long *)&atoms[i],1))
49		return BadLength;
50	    present&= ~bit;
51	}
52    }
53    return Success;
54}
55
56Status
57_XkbReadGetNamesReply(	Display *		dpy,
58			xkbGetNamesReply *	rep,
59			XkbDescPtr 		xkb,
60			int *			nread_rtrn)
61{
62    int				 i,len;
63    XkbReadBufferRec		 buf;
64    register XkbNamesPtr	 names;
65
66    if ( xkb->device_spec == XkbUseCoreKbd )
67	xkb->device_spec = rep->deviceID;
68
69    if ((xkb->names==NULL)&&
70	(XkbAllocNames(xkb,rep->which,
71				rep->nRadioGroups,rep->nKeyAliases)!=Success)) {
72	return BadAlloc;
73    }
74    names= xkb->names;
75    if (rep->length==0)
76	return Success;
77
78    if (!_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4))
79	return BadAlloc;
80    if (nread_rtrn)
81	*nread_rtrn= (int)rep->length*4;
82
83    if ((rep->which&XkbKeycodesNameMask)&&
84	(!_XkbReadBufferCopy32(&buf,(long *)&names->keycodes,1)))
85	    goto BAILOUT;
86    if ((rep->which&XkbGeometryNameMask)&&
87	(!_XkbReadBufferCopy32(&buf,(long *)&names->geometry,1)))
88	    goto BAILOUT;
89    if ((rep->which&XkbSymbolsNameMask)&&
90	(!_XkbReadBufferCopy32(&buf,(long *)&names->symbols,1)))
91	    goto BAILOUT;
92    if ((rep->which&XkbPhysSymbolsNameMask)&&
93	(!_XkbReadBufferCopy32(&buf,(long *)&names->phys_symbols,1)))
94	    goto BAILOUT;
95    if ((rep->which&XkbTypesNameMask)&&
96	(!_XkbReadBufferCopy32(&buf,(long *)&names->types,1)))
97	    goto BAILOUT;
98    if ((rep->which&XkbCompatNameMask)&&
99	(!_XkbReadBufferCopy32(&buf,(long *)&names->compat,1)))
100	    goto BAILOUT;
101
102    if ( rep->which & XkbKeyTypeNamesMask ) {
103	XkbClientMapPtr	map= xkb->map;
104	XkbKeyTypePtr	type;
105
106	len= rep->nTypes*4;
107	if (map!=NULL) {
108	    type= map->types;
109	    for (i=0;(i<map->num_types)&&(i<rep->nTypes);i++,type++) {
110		if (!_XkbReadBufferCopy32(&buf,(long *)&type->name,1))
111		    goto BAILOUT;
112		len-= 4;
113	    }
114	}
115	if ((len>0)&&(!_XkbSkipReadBufferData(&buf,len)))
116	    goto BAILOUT;
117    }
118    if ( rep->which&XkbKTLevelNamesMask ) {
119	CARD8 *nLevels;
120	XkbClientMapPtr	map= xkb->map;
121	XkbKeyTypePtr	type;
122
123	nLevels=(CARD8*)_XkbGetReadBufferPtr(&buf,XkbPaddedSize(rep->nTypes));
124	if (nLevels==NULL)
125	    goto BAILOUT;
126	if (map!=NULL) {
127	    type= map->types;
128	    for (i=0;i<(int)rep->nTypes;i++,type++) {
129		if (i>=map->num_types) {
130		    if (!_XkbSkipReadBufferData(&buf,nLevels[i]*4))
131			goto BAILOUT;
132		    continue;
133		}
134		if ((nLevels[i]>0)&&(nLevels[i]!=type->num_levels)) {
135		    goto BAILOUT;
136		}
137		if (type->level_names!=NULL)
138		    Xfree(type->level_names);
139		if (nLevels[i]==0) {
140		    type->level_names= NULL;
141		    continue;
142		}
143		type->level_names= _XkbTypedCalloc(nLevels[i],Atom);
144		if (type->level_names!=NULL) {
145		    if (!_XkbReadBufferCopy32(&buf,(long *)type->level_names,
146								nLevels[i]))
147			goto BAILOUT;
148		}
149		else {
150		    _XkbSkipReadBufferData(&buf,nLevels[i]*4);
151		}
152	    }
153	}
154	else {
155	    for (i=0;i<(int)rep->nTypes;i++) {
156		_XkbSkipReadBufferData(&buf,nLevels[i]*4);
157	    }
158	}
159    }
160    if (rep->which & XkbIndicatorNamesMask) {
161	if (_XkbReadAtoms(&buf,names->indicators,XkbNumIndicators,
162						rep->indicators)!=Success)
163	    goto BAILOUT;
164    }
165    if ( rep->which&XkbVirtualModNamesMask ) {
166	if (_XkbReadAtoms(&buf,names->vmods,XkbNumVirtualMods,
167					(CARD32)rep->virtualMods)!=Success)
168	    goto BAILOUT;
169    }
170    if ( rep->which&XkbGroupNamesMask ) {
171	if (_XkbReadAtoms(&buf,names->groups,XkbNumKbdGroups,
172					(CARD32)rep->groupNames)!=Success)
173	    goto BAILOUT;
174    }
175    if ( rep->which&XkbKeyNamesMask ) {
176	if (names->keys==NULL) {
177	    int nKeys;
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 (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#ifdef WORD64
500	char *tmp;
501	register int i;
502	BufAlloc(char *,tmp,nKeys*XkbKeyNameLength);
503	for (i=0;i<nKeys;i++,tmp+= XkbKeyNameLength) {
504	    tmp[0]= names->keys[firstKey+i].name[0];
505	    tmp[1]= names->keys[firstKey+i].name[1];
506	    tmp[2]= names->keys[firstKey+i].name[2];
507	    tmp[3]= names->keys[firstKey+i].name[3];
508	}
509#else
510	Data(dpy,(char *)&names->keys[firstKey],nKeys*XkbKeyNameLength);
511#endif
512    }
513    if (which&XkbKeyAliasesMask) {
514#ifdef WORD64
515	char *tmp;
516	register int i;
517	BufAlloc(char *,tmp,nKA*XkbKeyNameLength*2);
518	for (i=0;i<nKeys;i++,tmp+= 2*XkbKeyNameLength) {
519	    tmp[0]= names->key_aliases[i].real[0];
520	    tmp[1]= names->key_aliases[i].real[1];
521	    tmp[2]= names->key_aliases[i].real[2];
522	    tmp[3]= names->key_aliases[i].real[3];
523	    tmp[4]= names->key_aliases[i].alias[0];
524	    tmp[5]= names->key_aliases[i].alias[1];
525	    tmp[6]= names->key_aliases[i].alias[2];
526	    tmp[7]= names->key_aliases[i].alias[3];
527	}
528#else
529	Data(dpy,(char *)names->key_aliases,nKA*XkbKeyNameLength*2);
530#endif
531    }
532    if (which&XkbRGNamesMask) {
533	Data32(dpy,(long *)names->radio_groups,nRG*4);
534    }
535    UnlockDisplay(dpy);
536    SyncHandle();
537    return True;
538}
539
540Bool
541XkbChangeNames(Display *dpy,XkbDescPtr xkb,XkbNameChangesPtr changes)
542{
543    register xkbSetNamesReq *req;
544    int  nLvlNames = 0;
545    XkbInfoPtr xkbi;
546    XkbNamesPtr names;
547    unsigned which,firstType,nTypes;
548    unsigned firstLvlType,nLvlTypes;
549    int	nVMods,nLEDs,nRG,nKA,nGroups;
550    int nKeys=0,firstKey=0,nAtoms;
551    CARD32 leds=0,vmods=0,groups=0;
552
553    if ((dpy->flags & XlibDisplayNoXkb) ||
554	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
555	return False;
556    if ((!xkb)||(!xkb->names)||(!changes))
557	return False;
558    which= changes->changed;
559    firstType= changes->first_type;
560    nTypes= changes->num_types;
561    firstLvlType= changes->first_lvl;;
562    nLvlTypes= changes->num_lvls;
563    if (which&XkbKeyTypeNamesMask) {
564	if (nTypes<1)
565	    which&= ~XkbKeyTypeNamesMask;
566	else if (firstType<=XkbLastRequiredType) {
567	    int	adjust;
568	    adjust= XkbLastRequiredType-firstType+1;
569	    firstType+= adjust;
570	    nTypes-= adjust;
571	    if (nTypes<1)
572		which&= ~XkbKeyTypeNamesMask;
573	}
574    }
575    else firstType= nTypes= 0;
576
577    if (which&XkbKTLevelNamesMask) {
578	if (nLvlTypes<1)
579	    which&= ~XkbKTLevelNamesMask;
580    }
581    else firstLvlType= nLvlTypes= 0;
582
583    names= xkb->names;
584    if (which&(XkbKTLevelNamesMask|XkbKeyTypeNamesMask)) {
585	register int	i;
586	XkbKeyTypePtr	type;
587	if((xkb->map==NULL)||(xkb->map->types==NULL)||(nTypes==0)||
588				(firstType+nTypes>xkb->map->num_types)||
589				(firstLvlType+nLvlTypes>xkb->map->num_types))
590	    return False;
591	if (which&XkbKTLevelNamesMask) {
592	    type= &xkb->map->types[firstLvlType];
593	    for (i=nLvlNames=0;i<nLvlTypes;i++,type++) {
594		if (type->level_names!=NULL)
595		    nLvlNames+= type->num_levels;
596	    }
597	}
598    }
599
600    if (changes->num_keys<1)
601	which&= ~XkbKeyNamesMask;
602    if ((which&XkbKeyNamesMask)==0)
603	changes->first_key= changes->num_keys= 0;
604    else if ((changes->first_key<xkb->min_key_code)||
605	     (changes->first_key+changes->num_keys>xkb->max_key_code)) {
606	return False;
607    }
608
609    if ((which&XkbVirtualModNamesMask)==0)
610	changes->changed_vmods= 0;
611    else if (changes->changed_vmods==0)
612	which&= ~XkbVirtualModNamesMask;
613
614    if ((which&XkbIndicatorNamesMask)==0)
615	changes->changed_indicators= 0;
616    else if (changes->changed_indicators==0)
617	which&= ~XkbIndicatorNamesMask;
618
619    if ((which&XkbGroupNamesMask)==0)
620	changes->changed_groups= 0;
621    else if (changes->changed_groups==0)
622	which&= ~XkbGroupNamesMask;
623
624    nVMods= nLEDs= nRG= nKA= nAtoms= nGroups= 0;
625    LockDisplay(dpy);
626    xkbi = dpy->xkb_info;
627    GetReq(kbSetNames, req);
628    req->reqType = xkbi->codes->major_opcode;
629    req->xkbReqType = X_kbSetNames;
630    req->deviceSpec = xkb->device_spec;
631    req->firstType = firstType;
632    req->nTypes = nTypes;
633    req->firstKey = changes->first_key;
634    req->nKeys = changes->num_keys;
635
636    if (which&XkbKeycodesNameMask)
637	nAtoms++;
638    if (which&XkbGeometryNameMask)
639	nAtoms++;
640    if (which&XkbSymbolsNameMask)
641	nAtoms++;
642    if (which&XkbPhysSymbolsNameMask)
643	nAtoms++;
644    if (which&XkbTypesNameMask)
645	nAtoms++;
646    if (which&XkbCompatNameMask)
647	nAtoms++;
648    if (which&XkbKeyTypeNamesMask)
649	nAtoms+= nTypes;
650    if (which&XkbKTLevelNamesMask) {
651	req->firstKTLevel= firstLvlType;
652	req->nKTLevels= nLvlTypes;
653	req->length+= XkbPaddedSize(nLvlTypes)/4; /* room for group widths */
654	nAtoms+= nLvlNames;
655    }
656    else req->firstKTLevel= req->nKTLevels= 0;
657
658    if (which&XkbIndicatorNamesMask) {
659	leds= req->indicators= (CARD32)changes->changed_indicators;
660	nLEDs= _XkbCountBits(XkbNumIndicators,changes->changed_indicators);
661	if (nLEDs>0)
662	     nAtoms+= nLEDs;
663	else which&= ~XkbIndicatorNamesMask;
664    }
665    else req->indicators= 0;
666
667    if (which&XkbVirtualModNamesMask) {
668	vmods= req->virtualMods= changes->changed_vmods;
669	nVMods= _XkbCountBits(XkbNumVirtualMods,
670					(unsigned long)changes->changed_vmods);
671	if (nVMods>0)
672	     nAtoms+= nVMods;
673	else which&= ~XkbVirtualModNamesMask;
674    }
675    else 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 which&= ~XkbGroupNamesMask;
684    }
685    else req->groupNames= 0;
686
687    if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) {
688	firstKey= req->firstKey;
689	nKeys= req->nKeys;
690	nAtoms+= nKeys;	/* technically not atoms, but 4 bytes wide */
691    }
692    else which&= ~XkbKeyNamesMask;
693
694    if (which&XkbKeyAliasesMask) {
695	nKA= ((names->key_aliases!=NULL)?names->num_key_aliases:0);
696	if (nKA>0)
697	    nAtoms+= nKA*2; /* not atoms, but 8 bytes on the wire */
698	else which&= ~XkbKeyAliasesMask;
699    }
700
701    if (which&XkbRGNamesMask) {
702	nRG= names->num_rg;
703	if (nRG>0)
704	     nAtoms+= nRG;
705	else which&= ~XkbRGNamesMask;
706    }
707
708    req->which= which;
709    req->nRadioGroups= nRG;
710    req->length+= (nAtoms*4)/4;
711
712    if (which&XkbKeycodesNameMask)
713	Data32(dpy,(long *)&names->keycodes,4);
714    if (which&XkbGeometryNameMask)
715	Data32(dpy,(long *)&names->geometry,4);
716    if (which&XkbSymbolsNameMask)
717	Data32(dpy,(long *)&names->symbols,4);
718    if (which&XkbPhysSymbolsNameMask)
719	Data32(dpy,(long *)&names->phys_symbols,4);
720    if (which&XkbTypesNameMask)
721	Data32(dpy,(long *)&names->types,4);
722    if (which&XkbCompatNameMask)
723	Data32(dpy,(long *)&names->compat,4);
724    if (which&XkbKeyTypeNamesMask) {
725	register int 		i;
726	register XkbKeyTypePtr	type;
727	type= &xkb->map->types[firstType];
728	for (i=0;i<nTypes;i++,type++) {
729	    Data32(dpy,(long *)&type->name,4);
730	}
731    }
732    if (which&XkbKTLevelNamesMask) {
733	XkbKeyTypePtr type;
734	int i;
735	char *tmp;
736
737	BufAlloc(char *,tmp,XkbPaddedSize(nLvlTypes));
738	type = &xkb->map->types[firstLvlType];
739	for (i=0;i<nLvlTypes;i++,type++) {
740	    *tmp++ = type->num_levels;
741	}
742	type = &xkb->map->types[firstLvlType];
743	for (i=0;i<nLvlTypes;i++,type++) {
744	    if (type->level_names!=NULL)
745		Data32(dpy,(long *)type->level_names,type->num_levels*4);
746	}
747    }
748    if (which&XkbIndicatorNamesMask)
749	_XkbCopyAtoms(dpy,names->indicators,leds,XkbNumIndicators);
750    if (which&XkbVirtualModNamesMask)
751	_XkbCopyAtoms(dpy,names->vmods,vmods,XkbNumVirtualMods);
752    if (which&XkbGroupNamesMask)
753	_XkbCopyAtoms(dpy,names->groups,groups,XkbNumKbdGroups);
754    if (which&XkbKeyNamesMask) {
755#ifdef WORD64
756	char *tmp;
757	register int i;
758	BufAlloc(char *,tmp,nKeys*4);
759	for (i=0;i<nKeys;i++,tmp+= 4) {
760	    tmp[0]= names->keys[firstKey+i].name[0];
761	    tmp[1]= names->keys[firstKey+i].name[1];
762	    tmp[2]= names->keys[firstKey+i].name[2];
763	    tmp[3]= names->keys[firstKey+i].name[3];
764	}
765#else
766	Data(dpy,(char *)&names->keys[firstKey],nKeys*XkbKeyNameLength);
767#endif
768    }
769    if (which&XkbKeyAliasesMask) {
770#ifdef WORD64
771	char *tmp;
772	register int i;
773	BufAlloc(char *,tmp,nKA*XkbKeyNameLength*2);
774	for (i=0;i<nKeys;i++,tmp+= 2*XkbKeyNameLength) {
775	    tmp[0]= names->key_aliases[i].real[0];
776	    tmp[1]= names->key_aliases[i].real[1];
777	    tmp[2]= names->key_aliases[i].real[2];
778	    tmp[3]= names->key_aliases[i].real[3];
779	    tmp[4]= names->key_aliases[i].alias[0];
780	    tmp[5]= names->key_aliases[i].alias[1];
781	    tmp[6]= names->key_aliases[i].alias[2];
782	    tmp[7]= names->key_aliases[i].alias[3];
783	}
784#else
785	Data(dpy,(char *)names->key_aliases,nKA*XkbKeyNameLength*2);
786#endif
787    }
788    if (which&XkbRGNamesMask) {
789	Data32(dpy,(long *)names->radio_groups,nRG*4);
790    }
791    UnlockDisplay(dpy);
792    SyncHandle();
793    return True;
794}
795
796void
797XkbNoteNameChanges(	XkbNameChangesPtr	old,
798			XkbNamesNotifyEvent *	new,
799			unsigned int	 	wanted)
800{
801int	first,last,old_last,new_last;
802
803    wanted&= new->changed;
804    if ((old==NULL)||(new==NULL)||(wanted==0))
805	return;
806    if (wanted&XkbKeyTypeNamesMask) {
807	if (old->changed&XkbKeyTypeNamesMask) {
808	    new_last= (new->first_type+new->num_types-1);
809	    old_last= (old->first_type+old->num_types-1);
810
811	    if (new->first_type<old->first_type)
812		 first= new->first_type;
813	    else first= old->first_type;
814
815	    if (old_last>new_last)
816		 last= old_last;
817	    else last= new_last;
818
819	    old->first_type= first;
820	    old->num_types= (last-first)+1;
821	}
822	else {
823	    old->first_type= new->first_type;
824	    old->num_types= new->num_types;
825	}
826    }
827    if (wanted&XkbKTLevelNamesMask) {
828	if (old->changed&XkbKTLevelNamesMask) {
829	    new_last= (new->first_lvl+new->num_lvls-1);
830	    old_last= (old->first_lvl+old->num_lvls-1);
831
832	    if (new->first_lvl<old->first_lvl)
833		 first= new->first_lvl;
834	    else first= old->first_lvl;
835
836	    if (old_last>new_last)
837		 last= old_last;
838	    else last= new_last;
839
840	    old->first_lvl= first;
841	    old->num_lvls= (last-first)+1;
842	}
843	else {
844	    old->first_lvl= new->first_lvl;
845	    old->num_lvls= new->num_lvls;
846	}
847    }
848    if (wanted&XkbIndicatorNamesMask) {
849	if (old->changed&XkbIndicatorNamesMask)
850	     old->changed_indicators|= new->changed_indicators;
851	else old->changed_indicators=  new->changed_indicators;
852    }
853    if (wanted&XkbKeyNamesMask) {
854	if (old->changed&XkbKeyNamesMask) {
855	    new_last= (new->first_key+new->num_keys-1);
856	    old_last= (old->first_key+old->num_keys-1);
857
858	    first= old->first_key;
859
860	    if (new->first_key<old->first_key)
861		first= new->first_key;
862	    if (old_last>new_last)
863		new_last= old_last;
864
865	    old->first_key= first;
866	    old->num_keys= (new_last-first)+1;
867	}
868	else {
869	    old->first_key= new->first_key;
870	    old->num_keys= new->num_keys;
871	}
872    }
873    if (wanted&XkbVirtualModNamesMask) {
874	if (old->changed&XkbVirtualModNamesMask)
875	     old->changed_vmods|= new->changed_vmods;
876	else old->changed_vmods=  new->changed_vmods;
877    }
878    if (wanted&XkbGroupNamesMask) {
879	if (old->changed&XkbGroupNamesMask)
880	     old->changed_groups|= new->changed_groups;
881	else old->changed_groups=  new->changed_groups;
882    }
883    if (wanted&XkbRGNamesMask)
884	old->num_rg= new->num_radio_groups;
885    if (wanted&XkbKeyAliasesMask)
886	old->num_aliases= new->num_aliases;
887    old->changed|= wanted;
888    return;
889}
890