XKBCompat.c revision 1ab64890
1/* $Xorg: XKBCompat.c,v 1.3 2000/08/17 19:45:00 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$ */
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <stdio.h>
33#define NEED_REPLIES
34#define NEED_EVENTS
35#define	NEED_MAP_READERS
36#include "Xlibint.h"
37#include <X11/extensions/XKBproto.h>
38#include "XKBlibint.h"
39
40Status
41_XkbReadGetCompatMapReply(	Display *		dpy,
42				xkbGetCompatMapReply *	rep,
43				XkbDescPtr		xkb,
44				int	*		nread_rtrn)
45{
46register int 		i;
47XkbReadBufferRec	buf;
48
49    if (!_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4))
50	return BadAlloc;
51
52    if (nread_rtrn)
53	*nread_rtrn= (int)rep->length*4;
54
55    i= rep->firstSI+rep->nSI;
56    if ((!xkb->compat)&&
57	(XkbAllocCompatMap(xkb,XkbAllCompatMask,i)!=Success))
58	return BadAlloc;
59
60    if (rep->nSI!=0) {
61	XkbSymInterpretRec *syms;
62	xkbSymInterpretWireDesc *wire;
63
64	wire= (xkbSymInterpretWireDesc *)_XkbGetReadBufferPtr(&buf,
65				   rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
66	if (wire==NULL)
67	    goto BAILOUT;
68	syms= &xkb->compat->sym_interpret[rep->firstSI];
69
70	for (i=0;i<rep->nSI;i++,syms++,wire++) {
71	    syms->sym= wire->sym;
72	    syms->mods= wire->mods;
73	    syms->match= wire->match;
74	    syms->virtual_mod= wire->virtualMod;
75	    syms->flags= wire->flags;
76	    syms->act= *((XkbAnyAction *)&wire->act);
77	}
78	xkb->compat->num_si+= rep->nSI;
79    }
80
81    if (rep->groups&XkbAllGroupsMask) {
82	register unsigned	bit,nGroups;
83	xkbModsWireDesc * 	wire;
84	for (i=0,nGroups=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
85	    if (rep->groups&bit)
86		nGroups++;
87	}
88	wire= (xkbModsWireDesc *)_XkbGetReadBufferPtr(&buf,
89				  nGroups*SIZEOF(xkbModsWireDesc));
90	if (wire==NULL)
91	    goto BAILOUT;
92	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
93	    if ((rep->groups&bit)==0)
94		continue;
95	    xkb->compat->groups[i].mask= wire->mask;
96	    xkb->compat->groups[i].real_mods= wire->realMods;
97	    xkb->compat->groups[i].vmods= wire->virtualMods;
98	    wire++;
99	}
100    }
101    i= _XkbFreeReadBuffer(&buf);
102    if (i)
103	fprintf(stderr,"CompatMapReply! Bad length (%d extra bytes)\n",i);
104    if (i || buf.error)
105	return BadLength;
106    return Success;
107BAILOUT:
108    _XkbFreeReadBuffer(&buf);
109    return BadLength;
110}
111
112Status
113XkbGetCompatMap(Display *dpy,unsigned which,XkbDescPtr xkb)
114{
115    register xkbGetCompatMapReq *req;
116    xkbGetCompatMapReply	 rep;
117    Status			status;
118    XkbInfoPtr xkbi;
119
120    if ( (!dpy) || (!xkb) || (dpy->flags & XlibDisplayNoXkb) ||
121	((xkb->dpy!=NULL)&&(xkb->dpy!=dpy)) ||
122	(!dpy->xkb_info && (!XkbUseExtension(dpy,NULL,NULL))))
123	return BadAccess;
124    LockDisplay(dpy);
125    xkbi = dpy->xkb_info;
126    GetReq(kbGetCompatMap, req);
127    req->reqType = xkbi->codes->major_opcode;
128    req->xkbReqType = X_kbGetCompatMap;
129    req->deviceSpec = xkb->device_spec;
130    if (which&XkbSymInterpMask)
131	 req->getAllSI= True;
132    else req->getAllSI= False;
133    req->firstSI= req->nSI= 0;
134
135    if (which&XkbGroupCompatMask)
136	 req->groups= XkbAllGroupsMask;
137    else req->groups=  0;
138
139    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
140	UnlockDisplay(dpy);
141	SyncHandle();
142	return BadLength;
143    }
144    if (xkb->dpy==NULL)
145	xkb->dpy= dpy;
146    if (xkb->device_spec==XkbUseCoreKbd)
147	xkb->device_spec= rep.deviceID;
148
149    status = _XkbReadGetCompatMapReply(dpy,&rep,xkb,NULL);
150    UnlockDisplay(dpy);
151    SyncHandle();
152    return status;
153}
154
155static Bool
156_XkbWriteSetCompatMap(Display *dpy,xkbSetCompatMapReq *req,XkbDescPtr xkb)
157{
158CARD16			firstSI;
159CARD16			nSI;
160int			size;
161register int 		i,nGroups;
162register unsigned	bit;
163unsigned		groups;
164char *			buf;
165
166    firstSI = req->firstSI;
167    nSI = req->nSI;
168    size= nSI*SIZEOF(xkbSymInterpretWireDesc);
169    nGroups= 0;
170    groups= req->groups;
171    if (groups&XkbAllGroupsMask) {
172	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
173	    if (groups&bit)
174		nGroups++;
175	}
176	size+= SIZEOF(xkbModsWireDesc)*nGroups;
177    }
178    req->length+= size/4;
179    BufAlloc(char *,buf,size);
180    if (!buf)
181	return False;
182
183    if (nSI) {
184	XkbSymInterpretPtr sym= &xkb->compat->sym_interpret[firstSI];
185	xkbSymInterpretWireDesc *wire= (xkbSymInterpretWireDesc *)buf;
186	for (i=0;i<nSI;i++,wire++,sym++) {
187	    wire->sym= (CARD32)sym->sym;
188	    wire->mods= sym->mods;
189	    wire->match= sym->match;
190	    wire->flags= sym->flags;
191	    wire->virtualMod= sym->virtual_mod;
192	    memcpy(&wire->act,&sym->act,sz_xkbActionWireDesc);
193	}
194	buf+= nSI*SIZEOF(xkbSymInterpretWireDesc);
195    }
196    if (groups&XkbAllGroupsMask) {
197	xkbModsWireDesc *	out;
198
199	out= (xkbModsWireDesc *)buf;
200	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
201	    if ((groups&bit)!=0) {
202		out->mask= xkb->compat->groups[i].mask;
203		out->realMods= xkb->compat->groups[i].real_mods;
204		out->virtualMods=  xkb->compat->groups[i].vmods;
205		out++;
206	    }
207	}
208	buf+= nGroups*SIZEOF(xkbModsWireDesc);
209    }
210    return True;
211}
212
213Bool
214XkbSetCompatMap(Display *dpy,unsigned which,XkbDescPtr xkb,Bool updateActions)
215{
216    register xkbSetCompatMapReq *req;
217    Status		     ok;
218    XkbInfoPtr xkbi;
219
220    if ((dpy->flags & XlibDisplayNoXkb) || (dpy!=xkb->dpy) ||
221	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
222	return False;
223    if ((!xkb->compat) ||
224	((which&XkbSymInterpMask)&&(!xkb->compat->sym_interpret)))
225	return False;
226    LockDisplay(dpy);
227    xkbi = dpy->xkb_info;
228    GetReq(kbSetCompatMap, req);
229    req->reqType = xkbi->codes->major_opcode;
230    req->xkbReqType = X_kbSetCompatMap;
231    req->deviceSpec = xkb->device_spec;
232    req->recomputeActions = updateActions;
233    if (which&XkbSymInterpMask) {
234	req->truncateSI = True;
235	req->firstSI= 0;
236	req->nSI= xkb->compat->num_si;
237    }
238    else {
239	req->truncateSI = False;
240	req->firstSI= 0;
241	req->nSI= 0;
242    }
243    if (which&XkbGroupCompatMask)
244	 req->groups= XkbAllGroupsMask;
245    else req->groups=  0;
246    ok= _XkbWriteSetCompatMap(dpy,req,xkb);
247    UnlockDisplay(dpy);
248    SyncHandle();
249    return ok;
250}
251
252