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