1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE 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
36 Status
_XkbReadGetCompatMapReply(Display * dpy,xkbGetCompatMapReply * rep,XkbDescPtr xkb,int * nread_rtrn)37 _XkbReadGetCompatMapReply(Display *dpy,
38 xkbGetCompatMapReply *rep,
39 XkbDescPtr xkb,
40 int *nread_rtrn)
41 {
42 register int i;
43 XkbReadBufferRec 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
81 for (i = 0, nGroups = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
82 if (rep->groups & bit)
83 nGroups++;
84 }
85 wire = (xkbModsWireDesc *)
86 _XkbGetReadBufferPtr(&buf, nGroups * SIZEOF(xkbModsWireDesc));
87 if (wire == NULL)
88 goto BAILOUT;
89 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
90 if ((rep->groups & bit) == 0)
91 continue;
92 xkb->compat->groups[i].mask = wire->mask;
93 xkb->compat->groups[i].real_mods = wire->realMods;
94 xkb->compat->groups[i].vmods = wire->virtualMods;
95 wire++;
96 }
97 }
98 i = _XkbFreeReadBuffer(&buf);
99 if (i)
100 fprintf(stderr, "CompatMapReply! Bad length (%d extra bytes)\n", i);
101 if (i || buf.error)
102 return BadLength;
103 return Success;
104 BAILOUT:
105 _XkbFreeReadBuffer(&buf);
106 return BadLength;
107 }
108
109 Status
XkbGetCompatMap(Display * dpy,unsigned which,XkbDescPtr xkb)110 XkbGetCompatMap(Display *dpy, unsigned which, XkbDescPtr xkb)
111 {
112 register xkbGetCompatMapReq *req;
113 xkbGetCompatMapReply rep;
114 Status status;
115 XkbInfoPtr xkbi;
116
117 if ((!dpy) || (!xkb) || (dpy->flags & XlibDisplayNoXkb) ||
118 ((xkb->dpy != NULL) && (xkb->dpy != dpy)) ||
119 (!dpy->xkb_info && (!XkbUseExtension(dpy, NULL, NULL))))
120 return BadAccess;
121 LockDisplay(dpy);
122 xkbi = dpy->xkb_info;
123 GetReq(kbGetCompatMap, req);
124 req->reqType = xkbi->codes->major_opcode;
125 req->xkbReqType = X_kbGetCompatMap;
126 req->deviceSpec = xkb->device_spec;
127 if (which & XkbSymInterpMask)
128 req->getAllSI = True;
129 else
130 req->getAllSI = False;
131 req->firstSI = req->nSI = 0;
132
133 if (which & XkbGroupCompatMask)
134 req->groups = XkbAllGroupsMask;
135 else
136 req->groups = 0;
137
138 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
139 UnlockDisplay(dpy);
140 SyncHandle();
141 return BadLength;
142 }
143 if (xkb->dpy == NULL)
144 xkb->dpy = dpy;
145 if (xkb->device_spec == XkbUseCoreKbd)
146 xkb->device_spec = rep.deviceID;
147
148 status = _XkbReadGetCompatMapReply(dpy, &rep, xkb, NULL);
149 UnlockDisplay(dpy);
150 SyncHandle();
151 return status;
152 }
153
154 static Bool
_XkbWriteSetCompatMap(Display * dpy,xkbSetCompatMapReq * req,XkbDescPtr xkb)155 _XkbWriteSetCompatMap(Display *dpy, xkbSetCompatMapReq *req, XkbDescPtr xkb)
156 {
157 CARD16 firstSI;
158 CARD16 nSI;
159 int size;
160 register int i, nGroups;
161 register unsigned bit;
162 unsigned groups;
163 char *buf;
164
165 firstSI = req->firstSI;
166 nSI = req->nSI;
167 size = nSI * SIZEOF(xkbSymInterpretWireDesc);
168 nGroups = 0;
169 groups = req->groups;
170 if (groups & XkbAllGroupsMask) {
171 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
172 if (groups & bit)
173 nGroups++;
174 }
175 size += SIZEOF(xkbModsWireDesc) * nGroups;
176 }
177 req->length += size / 4;
178 BufAlloc(char *, buf, size);
179
180 if (!buf)
181 return False;
182
183 if (nSI) {
184 XkbSymInterpretPtr sym = &xkb->compat->sym_interpret[firstSI];
185 xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) buf;
186
187 for (i = 0; i < nSI; i++, wire++, sym++) {
188 wire->sym = (CARD32) sym->sym;
189 wire->mods = sym->mods;
190 wire->match = sym->match;
191 wire->flags = sym->flags;
192 wire->virtualMod = sym->virtual_mod;
193 memcpy(&wire->act, &sym->act, sz_xkbActionWireDesc);
194 }
195 buf += nSI * SIZEOF(xkbSymInterpretWireDesc);
196 }
197 if (groups & XkbAllGroupsMask) {
198 xkbModsWireDesc *out = (xkbModsWireDesc *) buf;
199
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
213 Bool
XkbSetCompatMap(Display * dpy,unsigned which,XkbDescPtr xkb,Bool updateActions)214 XkbSetCompatMap(Display *dpy, unsigned which, XkbDescPtr xkb,
215 Bool updateActions)
216 {
217 register xkbSetCompatMapReq *req;
218 Status ok;
219 XkbInfoPtr xkbi;
220
221 if ((dpy->flags & XlibDisplayNoXkb) || (dpy != xkb->dpy) ||
222 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
223 return False;
224 if ((!xkb->compat) ||
225 ((which & XkbSymInterpMask) && (!xkb->compat->sym_interpret)))
226 return False;
227 LockDisplay(dpy);
228 xkbi = dpy->xkb_info;
229 GetReq(kbSetCompatMap, req);
230 req->reqType = xkbi->codes->major_opcode;
231 req->xkbReqType = X_kbSetCompatMap;
232 req->deviceSpec = xkb->device_spec;
233 req->recomputeActions = updateActions;
234 if (which & XkbSymInterpMask) {
235 req->truncateSI = True;
236 req->firstSI = 0;
237 req->nSI = xkb->compat->num_si;
238 }
239 else {
240 req->truncateSI = False;
241 req->firstSI = 0;
242 req->nSI = 0;
243 }
244 if (which & XkbGroupCompatMask)
245 req->groups = XkbAllGroupsMask;
246 else
247 req->groups = 0;
248 ok = _XkbWriteSetCompatMap(dpy, req, xkb);
249 UnlockDisplay(dpy);
250 SyncHandle();
251 return ok;
252 }
253