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