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