XKBCompat.c revision 818534a1
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{
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
109Status
110XkbGetCompatMap(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
154static Bool
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
213Bool
214XkbSetCompatMap(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