11ab64890Smrg/************************************************************
21ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
31ab64890Smrg
41ab64890SmrgPermission to use, copy, modify, and distribute this
51ab64890Smrgsoftware and its documentation for any purpose and without
61ab64890Smrgfee is hereby granted, provided that the above copyright
71ab64890Smrgnotice appear in all copies and that both that copyright
81ab64890Smrgnotice and this permission notice appear in supporting
961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1061b2299dSmrgused in advertising or publicity pertaining to distribution
111ab64890Smrgof the software without specific prior written permission.
1261b2299dSmrgSilicon Graphics makes no representation about the suitability
131ab64890Smrgof this software for any purpose. It is provided "as is"
141ab64890Smrgwithout any express or implied warranty.
151ab64890Smrg
1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241ab64890Smrg
251ab64890Smrg********************************************************/
261ab64890Smrg
271ab64890Smrg#ifdef HAVE_CONFIG_H
281ab64890Smrg#include <config.h>
291ab64890Smrg#endif
301ab64890Smrg#include <stdio.h>
311ab64890Smrg#define	NEED_MAP_READERS
321ab64890Smrg#include "Xlibint.h"
331ab64890Smrg#include <X11/extensions/XKBproto.h>
341ab64890Smrg#include "XKBlibint.h"
351ab64890Smrg
361ab64890SmrgStatus
37818534a1Smrg_XkbReadGetCompatMapReply(Display *dpy,
38818534a1Smrg                          xkbGetCompatMapReply *rep,
39818534a1Smrg                          XkbDescPtr xkb,
40818534a1Smrg                          int *nread_rtrn)
411ab64890Smrg{
42818534a1Smrg    register int i;
43818534a1Smrg    XkbReadBufferRec buf;
441ab64890Smrg
45818534a1Smrg    if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4))
46818534a1Smrg        return BadAlloc;
471ab64890Smrg
481ab64890Smrg    if (nread_rtrn)
49818534a1Smrg        *nread_rtrn = (int) rep->length * 4;
50818534a1Smrg
51818534a1Smrg    i = rep->firstSI + rep->nSI;
52818534a1Smrg    if ((!xkb->compat) &&
53818534a1Smrg        (XkbAllocCompatMap(xkb, XkbAllCompatMask, i) != Success))
54818534a1Smrg        return BadAlloc;
55818534a1Smrg
56818534a1Smrg    if (rep->nSI != 0) {
57818534a1Smrg        XkbSymInterpretRec *syms;
58818534a1Smrg        xkbSymInterpretWireDesc *wire;
59818534a1Smrg
60818534a1Smrg        wire = (xkbSymInterpretWireDesc *) _XkbGetReadBufferPtr(&buf,
61818534a1Smrg            rep->nSI * SIZEOF (xkbSymInterpretWireDesc));
62818534a1Smrg        if (wire == NULL)
63818534a1Smrg            goto BAILOUT;
64818534a1Smrg        syms = &xkb->compat->sym_interpret[rep->firstSI];
65818534a1Smrg
66818534a1Smrg        for (i = 0; i < rep->nSI; i++, syms++, wire++) {
67818534a1Smrg            syms->sym = wire->sym;
68818534a1Smrg            syms->mods = wire->mods;
69818534a1Smrg            syms->match = wire->match;
70818534a1Smrg            syms->virtual_mod = wire->virtualMod;
71818534a1Smrg            syms->flags = wire->flags;
72818534a1Smrg            syms->act = *((XkbAnyAction *) &wire->act);
73818534a1Smrg        }
74818534a1Smrg        xkb->compat->num_si += rep->nSI;
751ab64890Smrg    }
761ab64890Smrg
77818534a1Smrg    if (rep->groups & XkbAllGroupsMask) {
78818534a1Smrg        register unsigned bit, nGroups;
79818534a1Smrg        xkbModsWireDesc *wire;
80818534a1Smrg
81818534a1Smrg        for (i = 0, nGroups = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
82818534a1Smrg            if (rep->groups & bit)
83818534a1Smrg                nGroups++;
84818534a1Smrg        }
85818534a1Smrg        wire = (xkbModsWireDesc *)
86818534a1Smrg            _XkbGetReadBufferPtr(&buf, nGroups * SIZEOF(xkbModsWireDesc));
87818534a1Smrg        if (wire == NULL)
88818534a1Smrg            goto BAILOUT;
89818534a1Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
90818534a1Smrg            if ((rep->groups & bit) == 0)
91818534a1Smrg                continue;
92818534a1Smrg            xkb->compat->groups[i].mask = wire->mask;
93818534a1Smrg            xkb->compat->groups[i].real_mods = wire->realMods;
94818534a1Smrg            xkb->compat->groups[i].vmods = wire->virtualMods;
95818534a1Smrg            wire++;
96818534a1Smrg        }
971ab64890Smrg    }
98818534a1Smrg    i = _XkbFreeReadBuffer(&buf);
9961b2299dSmrg    if (i)
100818534a1Smrg        fprintf(stderr, "CompatMapReply! Bad length (%d extra bytes)\n", i);
1011ab64890Smrg    if (i || buf.error)
102818534a1Smrg        return BadLength;
1031ab64890Smrg    return Success;
104818534a1Smrg BAILOUT:
1051ab64890Smrg    _XkbFreeReadBuffer(&buf);
1061ab64890Smrg    return BadLength;
1071ab64890Smrg}
1081ab64890Smrg
1091ab64890SmrgStatus
110818534a1SmrgXkbGetCompatMap(Display *dpy, unsigned which, XkbDescPtr xkb)
1111ab64890Smrg{
1121ab64890Smrg    register xkbGetCompatMapReq *req;
113818534a1Smrg    xkbGetCompatMapReply rep;
114818534a1Smrg    Status status;
1151ab64890Smrg    XkbInfoPtr xkbi;
1161ab64890Smrg
117818534a1Smrg    if ((!dpy) || (!xkb) || (dpy->flags & XlibDisplayNoXkb) ||
118818534a1Smrg        ((xkb->dpy != NULL) && (xkb->dpy != dpy)) ||
119818534a1Smrg        (!dpy->xkb_info && (!XkbUseExtension(dpy, NULL, NULL))))
120818534a1Smrg        return BadAccess;
1211ab64890Smrg    LockDisplay(dpy);
1221ab64890Smrg    xkbi = dpy->xkb_info;
1231ab64890Smrg    GetReq(kbGetCompatMap, req);
1241ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
1251ab64890Smrg    req->xkbReqType = X_kbGetCompatMap;
1261ab64890Smrg    req->deviceSpec = xkb->device_spec;
127818534a1Smrg    if (which & XkbSymInterpMask)
128818534a1Smrg        req->getAllSI = True;
129818534a1Smrg    else
130818534a1Smrg        req->getAllSI = False;
131818534a1Smrg    req->firstSI = req->nSI = 0;
132818534a1Smrg
133818534a1Smrg    if (which & XkbGroupCompatMask)
134818534a1Smrg        req->groups = XkbAllGroupsMask;
135818534a1Smrg    else
136818534a1Smrg        req->groups = 0;
137818534a1Smrg
138818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
139818534a1Smrg        UnlockDisplay(dpy);
140818534a1Smrg        SyncHandle();
141818534a1Smrg        return BadLength;
1421ab64890Smrg    }
143818534a1Smrg    if (xkb->dpy == NULL)
144818534a1Smrg        xkb->dpy = dpy;
145818534a1Smrg    if (xkb->device_spec == XkbUseCoreKbd)
146818534a1Smrg        xkb->device_spec = rep.deviceID;
1471ab64890Smrg
148818534a1Smrg    status = _XkbReadGetCompatMapReply(dpy, &rep, xkb, NULL);
1491ab64890Smrg    UnlockDisplay(dpy);
1501ab64890Smrg    SyncHandle();
1511ab64890Smrg    return status;
1521ab64890Smrg}
1531ab64890Smrg
1541ab64890Smrgstatic Bool
155818534a1Smrg_XkbWriteSetCompatMap(Display *dpy, xkbSetCompatMapReq *req, XkbDescPtr xkb)
1561ab64890Smrg{
157818534a1Smrg    CARD16 firstSI;
158818534a1Smrg    CARD16 nSI;
159818534a1Smrg    int size;
160818534a1Smrg    register int i, nGroups;
161818534a1Smrg    register unsigned bit;
162818534a1Smrg    unsigned groups;
163818534a1Smrg    char *buf;
1641ab64890Smrg
1651ab64890Smrg    firstSI = req->firstSI;
1661ab64890Smrg    nSI = req->nSI;
167818534a1Smrg    size = nSI * SIZEOF(xkbSymInterpretWireDesc);
168818534a1Smrg    nGroups = 0;
169818534a1Smrg    groups = req->groups;
170818534a1Smrg    if (groups & XkbAllGroupsMask) {
171818534a1Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
172818534a1Smrg            if (groups & bit)
173818534a1Smrg                nGroups++;
174818534a1Smrg        }
175818534a1Smrg        size += SIZEOF(xkbModsWireDesc) * nGroups;
1761ab64890Smrg    }
177818534a1Smrg    req->length += size / 4;
178818534a1Smrg    BufAlloc(char *, buf, size);
179818534a1Smrg
1801ab64890Smrg    if (!buf)
181818534a1Smrg        return False;
1821ab64890Smrg
1831ab64890Smrg    if (nSI) {
184818534a1Smrg        XkbSymInterpretPtr sym = &xkb->compat->sym_interpret[firstSI];
185818534a1Smrg        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) buf;
186818534a1Smrg
187818534a1Smrg        for (i = 0; i < nSI; i++, wire++, sym++) {
188818534a1Smrg            wire->sym = (CARD32) sym->sym;
189818534a1Smrg            wire->mods = sym->mods;
190818534a1Smrg            wire->match = sym->match;
191818534a1Smrg            wire->flags = sym->flags;
192818534a1Smrg            wire->virtualMod = sym->virtual_mod;
193818534a1Smrg            memcpy(&wire->act, &sym->act, sz_xkbActionWireDesc);
194818534a1Smrg        }
195818534a1Smrg        buf += nSI * SIZEOF(xkbSymInterpretWireDesc);
1961ab64890Smrg    }
197818534a1Smrg    if (groups & XkbAllGroupsMask) {
198818534a1Smrg        xkbModsWireDesc *out = (xkbModsWireDesc *) buf;
199818534a1Smrg
200818534a1Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
201818534a1Smrg            if ((groups & bit) != 0) {
202818534a1Smrg                out->mask = xkb->compat->groups[i].mask;
203818534a1Smrg                out->realMods = xkb->compat->groups[i].real_mods;
204818534a1Smrg                out->virtualMods = xkb->compat->groups[i].vmods;
205818534a1Smrg                out++;
206818534a1Smrg            }
207818534a1Smrg        }
208818534a1Smrg        buf += nGroups * SIZEOF(xkbModsWireDesc);
2091ab64890Smrg    }
2101ab64890Smrg    return True;
2111ab64890Smrg}
2121ab64890Smrg
2131ab64890SmrgBool
214818534a1SmrgXkbSetCompatMap(Display *dpy, unsigned which, XkbDescPtr xkb,
215818534a1Smrg                Bool updateActions)
2161ab64890Smrg{
2171ab64890Smrg    register xkbSetCompatMapReq *req;
218818534a1Smrg    Status ok;
2191ab64890Smrg    XkbInfoPtr xkbi;
2201ab64890Smrg
221818534a1Smrg    if ((dpy->flags & XlibDisplayNoXkb) || (dpy != xkb->dpy) ||
222818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
223818534a1Smrg        return False;
2241ab64890Smrg    if ((!xkb->compat) ||
225818534a1Smrg        ((which & XkbSymInterpMask) && (!xkb->compat->sym_interpret)))
226818534a1Smrg        return False;
2271ab64890Smrg    LockDisplay(dpy);
2281ab64890Smrg    xkbi = dpy->xkb_info;
2291ab64890Smrg    GetReq(kbSetCompatMap, req);
2301ab64890Smrg    req->reqType = xkbi->codes->major_opcode;
2311ab64890Smrg    req->xkbReqType = X_kbSetCompatMap;
2321ab64890Smrg    req->deviceSpec = xkb->device_spec;
2331ab64890Smrg    req->recomputeActions = updateActions;
234818534a1Smrg    if (which & XkbSymInterpMask) {
235818534a1Smrg        req->truncateSI = True;
236818534a1Smrg        req->firstSI = 0;
237818534a1Smrg        req->nSI = xkb->compat->num_si;
2381ab64890Smrg    }
2391ab64890Smrg    else {
240818534a1Smrg        req->truncateSI = False;
241818534a1Smrg        req->firstSI = 0;
242818534a1Smrg        req->nSI = 0;
2431ab64890Smrg    }
244818534a1Smrg    if (which & XkbGroupCompatMask)
245818534a1Smrg        req->groups = XkbAllGroupsMask;
246818534a1Smrg    else
247818534a1Smrg        req->groups = 0;
248818534a1Smrg    ok = _XkbWriteSetCompatMap(dpy, req, xkb);
2491ab64890Smrg    UnlockDisplay(dpy);
2501ab64890Smrg    SyncHandle();
2511ab64890Smrg    return ok;
2521ab64890Smrg}
253