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