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