XKBGetMap.c revision 1ab64890
1/* $Xorg: XKBGetMap.c,v 1.4 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
28/* $XFree86: xc/lib/X11/XKBGetMap.c,v 1.9 2003/04/17 02:06:31 dawes Exp $ */
29
30#define NEED_REPLIES
31#define NEED_EVENTS
32#define	NEED_MAP_READERS
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36#include "Xlibint.h"
37#include <X11/extensions/XKBproto.h>
38#include "XKBlibint.h"
39
40static Status
41_XkbReadKeyTypes(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
42{
43int		 i,n,lastMapCount;
44XkbKeyTypePtr	type;
45
46    if ( rep->nTypes>0 ) {
47	n = rep->firstType+rep->nTypes;
48	if (xkb->map->num_types>=n)
49	    n= xkb->map->num_types;
50	else if (XkbAllocClientMap(xkb,XkbKeyTypesMask,n)!=Success)
51	    return BadAlloc;
52
53	type = &xkb->map->types[rep->firstType];
54	for (i=0;i<(int)rep->nTypes;i++,type++) {
55	    xkbKeyTypeWireDesc	*desc;
56	    register int ndx;
57
58	    ndx= i+rep->firstType;
59	    if (ndx>=xkb->map->num_types)
60		xkb->map->num_types= ndx+1;
61
62	    desc= (xkbKeyTypeWireDesc *)_XkbGetReadBufferPtr(buf,
63						SIZEOF(xkbKeyTypeWireDesc));
64	    if (desc==NULL)
65		return BadLength;
66
67	    lastMapCount= type->map_count;
68	    if ( desc->nMapEntries>0 ) {
69		if ((type->map==NULL)||(desc->nMapEntries>type->map_count)) {
70		    XkbKTMapEntryRec *prev_map = type->map;
71
72		    type->map= _XkbTypedRealloc(type->map,desc->nMapEntries,
73							      XkbKTMapEntryRec);
74		    if (type->map==NULL) {
75			_XkbFree(prev_map);
76			return BadAlloc;
77		    }
78		}
79	    }
80	    else if (type->map!=NULL) {
81		Xfree(type->map);
82		type->map_count= 0;
83		type->map= NULL;
84	    }
85
86	    if ( desc->preserve && (desc->nMapEntries>0) ) {
87		if ((!type->preserve)||
88		    (desc->nMapEntries>lastMapCount)) {
89		    XkbModsRec *prev_preserve = type->preserve;
90
91		    type->preserve= _XkbTypedRealloc(type->preserve,
92							desc->nMapEntries,
93							XkbModsRec);
94		    if (type->preserve==NULL) {
95			_XkbFree(prev_preserve);
96			return BadAlloc;
97		    }
98		}
99	    }
100	    else if (type->preserve!=NULL) {
101		Xfree(type->preserve);
102		type->preserve= NULL;
103	    }
104
105	    type->mods.mask = desc->mask;
106	    type->mods.real_mods = desc->realMods;
107	    type->mods.vmods = desc->virtualMods;
108	    type->num_levels = desc->numLevels;
109	    type->map_count = desc->nMapEntries;
110	    if (desc->nMapEntries>0) {
111		register xkbKTMapEntryWireDesc *wire;
112		register XkbKTMapEntryPtr	entry;
113		register int size;
114
115		size= type->map_count*SIZEOF(xkbKTMapEntryWireDesc);
116		wire= (xkbKTMapEntryWireDesc *)_XkbGetReadBufferPtr(buf,size);
117		if (wire==NULL)
118		    return BadLength;
119		entry= type->map;
120		for (n=0;n<type->map_count;n++,wire++,entry++) {
121		    entry->active= wire->active;
122		    entry->level= wire->level;
123		    entry->mods.mask= wire->mask;
124		    entry->mods.real_mods= wire->realMods;
125		    entry->mods.vmods= wire->virtualMods;
126		}
127
128	 	if (desc->preserve) {
129		    register xkbModsWireDesc *	pwire;
130		    register XkbModsPtr		preserve;
131		    register int sz;
132
133		    sz= desc->nMapEntries*SIZEOF(xkbModsWireDesc);
134		    pwire=(xkbModsWireDesc *)_XkbGetReadBufferPtr(buf,sz);
135		    if (pwire==NULL)
136			return BadLength;
137		    preserve= type->preserve;
138		    for (n=0;n<desc->nMapEntries;n++,pwire++,preserve++) {
139			preserve->mask=  pwire->mask;
140			preserve->vmods=  pwire->virtualMods;
141			preserve->real_mods= pwire->realMods;
142		    }
143		}
144	    }
145	}
146    }
147    return Success;
148}
149
150static Status
151_XkbReadKeySyms(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
152{
153register int i;
154XkbClientMapPtr	map;
155
156    map= xkb->map;
157    if (map->key_sym_map==NULL) {
158	register int offset;
159	XkbSymMapPtr	oldMap;
160	xkbSymMapWireDesc *newMap;
161	map->key_sym_map= _XkbTypedCalloc((xkb->max_key_code+1),XkbSymMapRec);
162	if (map->key_sym_map==NULL)
163	    return BadAlloc;
164	if (map->syms==NULL) {
165	    int sz;
166	    sz= (rep->totalSyms*12)/10;
167	    sz= ((sz+(unsigned)128)/128)*128;
168	    map->syms = _XkbTypedCalloc(sz,KeySym);
169	    if (map->syms==NULL)
170		return BadAlloc;
171	    map->size_syms = sz;
172	}
173	offset = 1;
174	oldMap = &map->key_sym_map[rep->firstKeySym];
175	for (i=0;i<(int)rep->nKeySyms;i++,oldMap++) {
176	    newMap= (xkbSymMapWireDesc *)
177			_XkbGetReadBufferPtr(buf,SIZEOF(xkbSymMapWireDesc));
178	    if (newMap==NULL)
179		return BadLength;
180	    oldMap->kt_index[0]= newMap->ktIndex[0];
181	    oldMap->kt_index[1]= newMap->ktIndex[1];
182	    oldMap->kt_index[2]= newMap->ktIndex[2];
183	    oldMap->kt_index[3]= newMap->ktIndex[3];
184	    oldMap->group_info= newMap->groupInfo;
185	    oldMap->width= newMap->width;
186	    oldMap->offset= offset;
187	    if (offset+newMap->nSyms>=map->size_syms) {
188		register int sz;
189		KeySym *prev_syms = map->syms;
190
191		sz= map->size_syms+128;
192		map->syms= _XkbTypedRealloc(map->syms,sz,KeySym);
193		if (map->syms==NULL) {
194		    _XkbFree(prev_syms);
195		    map->size_syms= 0;
196		    return BadAlloc;
197		}
198		map->size_syms= sz;
199	    }
200	    if (newMap->nSyms>0) {
201		_XkbReadBufferCopyKeySyms(buf,(KeySym *)&map->syms[offset],
202							newMap->nSyms);
203		offset+= newMap->nSyms;
204	    }
205	    else {
206		map->syms[offset]= 0;
207	    }
208	}
209	map->num_syms= offset;
210    }
211    else {
212	xkbSymMapWireDesc *	newMap;
213	XkbSymMapPtr		oldMap;
214	KeySym *		newSyms;
215	int			tmp;
216
217	oldMap = &map->key_sym_map[rep->firstKeySym];
218	for (i=0;i<(int)rep->nKeySyms;i++,oldMap++) {
219	    newMap= (xkbSymMapWireDesc *)
220			_XkbGetReadBufferPtr(buf,SIZEOF(xkbSymMapWireDesc));
221	    if (newMap==NULL)
222		return BadLength;
223
224	    if (newMap->nSyms>0)
225		 tmp= newMap->nSyms;
226	    else tmp= 0;
227
228	    newSyms = XkbResizeKeySyms(xkb,i+rep->firstKeySym,tmp);
229	    if (newSyms==NULL)
230		return BadAlloc;
231	    if (newMap->nSyms>0)
232		_XkbReadBufferCopyKeySyms(buf,newSyms,newMap->nSyms);
233	    else newSyms[0]= NoSymbol;
234	    oldMap->kt_index[0] = newMap->ktIndex[0];
235	    oldMap->kt_index[1] = newMap->ktIndex[1];
236	    oldMap->kt_index[2] = newMap->ktIndex[2];
237	    oldMap->kt_index[3] = newMap->ktIndex[3];
238	    oldMap->group_info = newMap->groupInfo;
239	    oldMap->width = newMap->width;
240	}
241    }
242    return Success;
243}
244
245static Status
246_XkbReadKeyActions(XkbReadBufferPtr buf,XkbDescPtr info,xkbGetMapReply *rep)
247{
248int		i;
249CARD8		numDescBuf[248];
250CARD8*		numDesc = NULL;
251register int	nKeyActs;
252Status		ret = Success;
253
254    if ( (nKeyActs=rep->nKeyActs)>0 ) {
255	XkbSymMapPtr	symMap;
256
257	if (nKeyActs < sizeof numDescBuf) numDesc = numDescBuf;
258	else numDesc = Xmalloc (nKeyActs * sizeof(CARD8));
259
260	if (!_XkbCopyFromReadBuffer(buf, (char *)numDesc, nKeyActs)) {
261	    ret = BadLength;
262	    goto done;
263	}
264	i= XkbPaddedSize(nKeyActs)-nKeyActs;
265	if ((i>0)&&(!_XkbSkipReadBufferData(buf,i))) {
266	    ret = BadLength;
267	    goto done;
268	}
269	symMap = &info->map->key_sym_map[rep->firstKeyAct];
270	for (i=0;i<(int)rep->nKeyActs;i++,symMap++) {
271	    if (numDesc[i]==0) {
272		info->server->key_acts[i+rep->firstKeyAct]= 0;
273	    }
274	    else {
275		XkbAction *newActs;
276		/* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
277		/*                 either zero or XkbKeyNumSyms(info,key) */
278		newActs=XkbResizeKeyActions(info,i+rep->firstKeyAct,
279								numDesc[i]);
280		if (newActs==NULL) {
281		    ret = BadAlloc;
282		    goto done;
283		}
284		if (!_XkbCopyFromReadBuffer(buf,(char *)newActs,
285					(int)(numDesc[i]*sizeof(XkbAction)))) {
286		    ret = BadLength;
287		    goto done;
288		}
289	    }
290	}
291    }
292done:
293    if (numDesc != NULL && numDesc != numDescBuf) Xfree (numDesc);
294    return ret;
295}
296
297static Status
298_XkbReadKeyBehaviors(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
299{
300register int i;
301xkbBehaviorWireDesc	*wire;
302
303    if ( rep->totalKeyBehaviors>0 ) {
304	if ( xkb->server->behaviors == NULL ) {
305	    int size = xkb->max_key_code+1;
306	    xkb->server->behaviors = _XkbTypedCalloc(size,XkbBehavior);
307	    if (xkb->server->behaviors==NULL)
308		return BadAlloc;
309	}
310	else {
311	    bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
312	    		(rep->nKeyBehaviors*sizeof(XkbBehavior)));
313	}
314	for (i=0;i<rep->totalKeyBehaviors;i++) {
315	    wire= (xkbBehaviorWireDesc *)_XkbGetReadBufferPtr(buf,
316						SIZEOF(xkbBehaviorWireDesc));
317	    if (wire==NULL)
318		return BadLength;
319	    xkb->server->behaviors[wire->key].type= wire->type;
320	    xkb->server->behaviors[wire->key].data= wire->data;
321	}
322    }
323    return Success;
324}
325
326static Status
327_XkbReadVirtualMods(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
328{
329    if ( rep->virtualMods ) {
330	register int i,bit,nVMods;
331	register char *data;
332
333	for (i=nVMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
334	    if (rep->virtualMods&bit)
335		nVMods++;
336	}
337	data= _XkbGetReadBufferPtr(buf,XkbPaddedSize(nVMods));
338	if (data==NULL)
339	    return BadLength;
340	for (i=0,bit=1;(i<XkbNumVirtualMods)&&(nVMods>0);i++,bit<<=1) {
341	    if (rep->virtualMods&bit) {
342		xkb->server->vmods[i]= *data++;
343		nVMods--;
344	    }
345	}
346    }
347    return Success;
348}
349
350static Status
351_XkbReadExplicitComponents(	XkbReadBufferPtr	buf,
352				XkbDescPtr 		xkb,
353				xkbGetMapReply *	rep)
354{
355register int i;
356unsigned char *wire;
357
358    if ( rep->totalKeyExplicit>0 ) {
359	if ( xkb->server->explicit == NULL ) {
360	    int size = xkb->max_key_code+1;
361	    xkb->server->explicit = _XkbTypedCalloc(size,unsigned char);
362	    if (xkb->server->explicit==NULL)
363		return BadAlloc;
364	}
365	else {
366	    bzero(&xkb->server->explicit[rep->firstKeyExplicit],
367	    						rep->nKeyExplicit);
368	}
369	i= XkbPaddedSize(2*rep->totalKeyExplicit);
370	wire=(unsigned char *)_XkbGetReadBufferPtr(buf,i);
371	if (!wire)
372	    return BadLength;
373	for (i=0;i<rep->totalKeyExplicit;i++,wire+=2) {
374	    xkb->server->explicit[wire[0]]= wire[1];
375	}
376    }
377    return Success;
378}
379
380static Status
381_XkbReadModifierMap(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
382{
383register int i;
384unsigned char *wire;
385
386    if ( rep->totalModMapKeys>0 ) {
387	if ((xkb->map->modmap==NULL)&&
388	    (XkbAllocClientMap(xkb,XkbModifierMapMask,0)!=Success)) {
389	    return BadAlloc;
390	}
391	else {
392	    bzero(&xkb->map->modmap[rep->firstModMapKey],rep->nModMapKeys);
393	}
394	i= XkbPaddedSize(2*rep->totalModMapKeys);
395	wire=(unsigned char *)_XkbGetReadBufferPtr(buf,i);
396	if (!wire)
397	    return BadLength;
398	for (i=0;i<rep->totalModMapKeys;i++,wire+=2) {
399	    xkb->map->modmap[wire[0]]= wire[1];
400	}
401    }
402    return Success;
403}
404
405static Status
406_XkbReadVirtualModMap(XkbReadBufferPtr buf,XkbDescPtr xkb,xkbGetMapReply *rep)
407{
408register int 		i;
409xkbVModMapWireDesc *	wire;
410XkbServerMapPtr		srv;
411
412    if ( rep->totalVModMapKeys>0 ) {
413	if (((xkb->server==NULL)||(xkb->server->vmodmap==NULL))&&
414	    (XkbAllocServerMap(xkb,XkbVirtualModMapMask,0)!=Success)) {
415	    return BadAlloc;
416	}
417	else {
418	    srv= xkb->server;
419	    if (rep->nVModMapKeys > rep->firstVModMapKey)
420		bzero((char *)&srv->vmodmap[rep->firstVModMapKey],
421		      (rep->nVModMapKeys - rep->firstVModMapKey) *
422		      sizeof(unsigned short));
423	}
424	srv= xkb->server;
425	i= rep->totalVModMapKeys*SIZEOF(xkbVModMapWireDesc);
426	wire=(xkbVModMapWireDesc *)_XkbGetReadBufferPtr(buf,i);
427	if (!wire)
428	    return BadLength;
429	for (i=0;i<rep->totalVModMapKeys;i++,wire++) {
430	    if ((wire->key>=xkb->min_key_code)&&(wire->key<=xkb->max_key_code))
431		srv->vmodmap[wire->key]= wire->vmods;
432	}
433    }
434    return Success;
435}
436
437static xkbGetMapReq *
438_XkbGetGetMapReq(Display *dpy,XkbDescPtr xkb)
439{
440xkbGetMapReq *req;
441
442    GetReq(kbGetMap, req);
443    req->reqType = dpy->xkb_info->codes->major_opcode;
444    req->xkbReqType = X_kbGetMap;
445    req->deviceSpec = xkb->device_spec;
446    req->full = req->partial = 0;
447    req->firstType = req->nTypes = 0;
448    req->firstKeySym = req->nKeySyms = 0;
449    req->firstKeyAct = req->nKeyActs = 0;
450    req->firstKeyBehavior = req->nKeyBehaviors = 0;
451    req->virtualMods = 0;
452    req->firstKeyExplicit = req->nKeyExplicit = 0;
453    req->firstModMapKey = req->nModMapKeys = 0;
454    req->firstVModMapKey = req->nVModMapKeys = 0;
455    return req;
456}
457
458Status
459_XkbReadGetMapReply(	Display *	dpy,
460			xkbGetMapReply *rep,
461			XkbDescPtr	xkb,
462			int *		nread_rtrn)
463{
464int		extraData;
465unsigned	mask;
466
467    if ( xkb->device_spec == XkbUseCoreKbd )
468	xkb->device_spec= rep->deviceID;
469    xkb->min_key_code = rep->minKeyCode;
470    xkb->max_key_code = rep->maxKeyCode;
471
472    if (!xkb->map) {
473	mask= rep->present&XkbAllClientInfoMask;
474	if (mask&&(XkbAllocClientMap(xkb,mask,rep->nTypes)!=Success))
475	    return BadAlloc;
476    }
477    if (!xkb->server) {
478	mask= rep->present&XkbAllServerInfoMask;
479	if (mask&&(XkbAllocServerMap(xkb,mask,rep->totalActs)!=Success))
480	    return BadAlloc;
481    }
482    extraData= (int)(rep->length*4);
483    extraData-= (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
484    if (rep->length) {
485	XkbReadBufferRec	buf;
486	int			left;
487	if (_XkbInitReadBuffer(dpy,&buf,extraData)) {
488	    Status status= Success;
489	    if (nread_rtrn!=NULL)
490		*nread_rtrn= extraData;
491	    if (status==Success)
492		status= _XkbReadKeyTypes(&buf,xkb,rep);
493	    if (status==Success)
494		status= _XkbReadKeySyms(&buf,xkb,rep);
495	    if (status==Success)
496		status= _XkbReadKeyActions(&buf,xkb,rep);
497	    if (status==Success)
498		status= _XkbReadKeyBehaviors(&buf,xkb,rep);
499	    if (status==Success)
500		status= _XkbReadVirtualMods(&buf,xkb,rep);
501	    if (status==Success)
502		status= _XkbReadExplicitComponents(&buf,xkb,rep);
503	    if (status==Success)
504		status= _XkbReadModifierMap(&buf,xkb,rep);
505	    if (status==Success)
506		status= _XkbReadVirtualModMap(&buf,xkb,rep);
507	    left= _XkbFreeReadBuffer(&buf);
508	    if (status!=Success)		return status;
509	    else if ( left || buf.error )	return BadLength;
510	}
511	else return BadAlloc;
512    }
513    return Success;
514}
515
516static Status
517_XkbHandleGetMapReply(Display *dpy,XkbDescPtr xkb)
518{
519xkbGetMapReply	rep;
520
521    if (!_XReply(dpy, (xReply *)&rep,
522    		 ( (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)) >> 2 ),
523		 xFalse)) {
524	return BadImplementation;
525    }
526    return _XkbReadGetMapReply(dpy,&rep,xkb,NULL);
527}
528
529Status
530XkbGetUpdatedMap(Display *dpy,unsigned which,XkbDescPtr xkb)
531{
532    if ((dpy->flags & XlibDisplayNoXkb) ||
533	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
534	return BadAccess;
535    if (which) {
536	register xkbGetMapReq *req;
537	Status status;
538
539	LockDisplay(dpy);
540
541	req = _XkbGetGetMapReq(dpy, xkb);
542	req->full = which;
543	status= _XkbHandleGetMapReply(dpy, xkb);
544
545	UnlockDisplay(dpy);
546	SyncHandle();
547	return status;
548    }
549    return Success;
550}
551
552XkbDescPtr
553XkbGetMap(Display *dpy,unsigned which,unsigned deviceSpec)
554{
555XkbDescPtr xkb;
556
557    xkb = _XkbTypedCalloc(1,XkbDescRec);
558    if (xkb) {
559	xkb->device_spec = deviceSpec;
560	xkb->map = _XkbTypedCalloc(1,XkbClientMapRec);
561	if ((xkb->map==NULL)||
562	    ((which)&&(XkbGetUpdatedMap(dpy,which,xkb)!=Success))) {
563	    if (xkb->map) {
564		Xfree(xkb->map);
565		xkb->map= NULL;
566	    }
567	    Xfree(xkb);
568	    return NULL;
569	}
570	xkb->dpy= dpy;
571    }
572    return xkb;
573}
574
575Status
576XkbGetKeyTypes(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
577{
578    register xkbGetMapReq *req;
579    Status status;
580
581    if ((dpy->flags & XlibDisplayNoXkb) ||
582	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
583	return BadAccess;
584    if ((num<1)||(num>XkbMaxKeyTypes))
585	return BadValue;
586
587    LockDisplay(dpy);
588
589    req = _XkbGetGetMapReq(dpy, xkb);
590    req->firstType = first;
591    req->nTypes = num;
592    status= _XkbHandleGetMapReply(dpy, xkb);
593
594    UnlockDisplay(dpy);
595    SyncHandle();
596    return status;
597}
598
599Status
600XkbGetKeyActions(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
601{
602    register xkbGetMapReq *req;
603    Status status;
604
605    if ((dpy->flags & XlibDisplayNoXkb) ||
606	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
607	return BadAccess;
608
609    if ((num<1)||(num>XkbMaxKeyCount))
610	return BadValue;
611
612    LockDisplay(dpy);
613
614    req = _XkbGetGetMapReq(dpy, xkb);
615    req->firstKeyAct = first;
616    req->nKeyActs = num;
617    status= _XkbHandleGetMapReply(dpy, xkb);
618
619    UnlockDisplay(dpy);
620    SyncHandle();
621    return status;
622}
623
624Status
625XkbGetKeySyms(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
626{
627    register xkbGetMapReq *req;
628    Status status;
629
630    if ((dpy->flags & XlibDisplayNoXkb) ||
631	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
632	return BadAccess;
633
634    if ((num<1)||(num>XkbMaxKeyCount))
635	return BadValue;
636
637    LockDisplay(dpy);
638
639    req = _XkbGetGetMapReq(dpy, xkb);
640    req->firstKeySym = first;
641    req->nKeySyms = num;
642    status= _XkbHandleGetMapReply(dpy, xkb);
643
644    UnlockDisplay(dpy);
645    SyncHandle();
646
647    return status;
648}
649
650Status
651XkbGetKeyBehaviors(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
652{
653    register xkbGetMapReq *req;
654    Status status;
655
656    if ((dpy->flags & XlibDisplayNoXkb) ||
657	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
658	return BadAccess;
659
660    if ((num<1)||(num>XkbMaxKeyCount))
661	return BadValue;
662
663    LockDisplay(dpy);
664
665    req = _XkbGetGetMapReq(dpy, xkb);
666    req->firstKeyBehavior = first;
667    req->nKeyBehaviors = num;
668    status= _XkbHandleGetMapReply(dpy, xkb);
669
670    UnlockDisplay(dpy);
671    SyncHandle();
672    return status;
673}
674
675Status
676XkbGetVirtualMods(Display *dpy,unsigned which,XkbDescPtr xkb)
677{
678    register xkbGetMapReq *req;
679    Status status;
680
681    if ((dpy->flags & XlibDisplayNoXkb) ||
682	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
683	return BadAccess;
684
685    LockDisplay(dpy);
686
687    req = _XkbGetGetMapReq(dpy, xkb);
688    req->virtualMods = which;
689    status= _XkbHandleGetMapReply(dpy, xkb);
690
691    UnlockDisplay(dpy);
692    SyncHandle();
693    return status;
694}
695
696Status
697XkbGetKeyExplicitComponents(	Display *	dpy,
698				unsigned	first,
699				unsigned 	num,
700				XkbDescPtr	xkb)
701{
702    register xkbGetMapReq *req;
703    Status status;
704
705    if ((dpy->flags & XlibDisplayNoXkb) ||
706	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
707	return BadAccess;
708
709    if ((num<1)||(num>XkbMaxKeyCount))
710	return BadValue;
711
712    LockDisplay(dpy);
713
714    req = _XkbGetGetMapReq(dpy, xkb);
715    req->firstKeyExplicit = first;
716    req->nKeyExplicit = num;
717    if ((xkb!=NULL) && (xkb->server!=NULL) && (xkb->server->explicit!=NULL)) {
718	if ((num>0)&&(first>=xkb->min_key_code)&&(first+num<=xkb->max_key_code))
719	    bzero(&xkb->server->explicit[first],num);
720    }
721    if (xkb)
722        status= _XkbHandleGetMapReply(dpy, xkb);
723    else
724        status = BadMatch;
725
726    UnlockDisplay(dpy);
727    SyncHandle();
728    return status;
729}
730
731Status
732XkbGetKeyModifierMap(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
733{
734    register xkbGetMapReq *req;
735    Status status;
736
737    if ((dpy->flags & XlibDisplayNoXkb) ||
738	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
739	return BadAccess;
740
741    if ((num<1)||(num>XkbMaxKeyCount))
742	return BadValue;
743
744    LockDisplay(dpy);
745
746    req = _XkbGetGetMapReq(dpy, xkb);
747    req->firstModMapKey = first;
748    req->nModMapKeys = num;
749    if ((xkb!=NULL) && (xkb->map!=NULL) && (xkb->map->modmap!=NULL)) {
750	if ((num>0)&&(first>=xkb->min_key_code)&&(first+num<=xkb->max_key_code))
751	    bzero(&xkb->map->modmap[first],num);
752    }
753    if (xkb)
754        status= _XkbHandleGetMapReply(dpy, xkb);
755    else
756        status = BadMatch;
757
758    UnlockDisplay(dpy);
759    SyncHandle();
760    return status;
761}
762
763Status
764XkbGetKeyVirtualModMap(Display *dpy,unsigned first,unsigned num,XkbDescPtr xkb)
765{
766    register xkbGetMapReq *req;
767    Status status;
768
769    if ((dpy->flags & XlibDisplayNoXkb) ||
770	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
771	return BadAccess;
772
773    if ((num<1)||(num>XkbMaxKeyCount))
774	return BadValue;
775
776    LockDisplay(dpy);
777
778    req = _XkbGetGetMapReq(dpy, xkb);
779    req->firstVModMapKey = first;
780    req->nVModMapKeys = num;
781    if ((xkb!=NULL) && (xkb->map!=NULL) && (xkb->map->modmap!=NULL)) {
782	if ((num>0)&&(first>=xkb->min_key_code)&&(first+num<=xkb->max_key_code))
783	    bzero(&xkb->server->vmodmap[first],num*sizeof(unsigned short));
784    }
785
786    if (xkb)
787        status= _XkbHandleGetMapReply(dpy, xkb);
788    else
789        status = BadMatch;
790
791    UnlockDisplay(dpy);
792    SyncHandle();
793    return status;
794}
795
796Status
797XkbGetMapChanges(Display *dpy,XkbDescPtr xkb,XkbMapChangesPtr changes)
798{
799    xkbGetMapReq *req;
800
801    if ((dpy->flags & XlibDisplayNoXkb) ||
802	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
803	return BadAccess;
804    LockDisplay(dpy);
805    if (changes->changed) {
806	Status status= Success;
807	req = _XkbGetGetMapReq(dpy, xkb);
808	req->full = 0;
809	req->partial = changes->changed;
810	req->firstType = changes->first_type;
811	req->nTypes = changes->num_types;
812	req->firstKeySym = changes->first_key_sym;
813	req->nKeySyms = changes->num_key_syms;
814	req->firstKeyAct = changes->first_key_act;
815	req->nKeyActs = changes->num_key_acts;
816	req->firstKeyBehavior = changes->first_key_behavior;
817	req->nKeyBehaviors = changes->num_key_behaviors;
818	req->virtualMods = changes->vmods;
819	req->firstKeyExplicit = changes->first_key_explicit;
820	req->nKeyExplicit = changes->num_key_explicit;
821	req->firstModMapKey = changes->first_modmap_key;
822	req->nModMapKeys = changes->num_modmap_keys;
823	req->firstVModMapKey = changes->first_vmodmap_key;
824	req->nVModMapKeys = changes->num_vmodmap_keys;
825	status= _XkbHandleGetMapReply(dpy, xkb);
826	UnlockDisplay(dpy);
827	SyncHandle();
828	return status;
829    }
830    UnlockDisplay(dpy);
831    return Success;
832}
833
834