Home | History | Annotate | Line # | Download | only in xkb
      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
     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
    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
    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
    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