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 #define	NEED_MAP_READERS
     28 #ifdef HAVE_CONFIG_H
     29 #include <config.h>
     30 #endif
     31 #include "Xlibint.h"
     32 #include <X11/extensions/XKBproto.h>
     33 #include "XKBlibint.h"
     34 
     35 static Status
     36 _XkbReadKeyTypes(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
     37 {
     38     int i, n, lastMapCount;
     39     XkbKeyTypePtr type;
     40 
     41     if (rep->nTypes > 0) {
     42         n = rep->firstType + rep->nTypes;
     43         if (xkb->map->num_types >= n)
     44             n = xkb->map->num_types;
     45         else if (XkbAllocClientMap(xkb, XkbKeyTypesMask, n) != Success)
     46             return BadAlloc;
     47 
     48         type = &xkb->map->types[rep->firstType];
     49         for (i = 0; i < (int) rep->nTypes; i++, type++) {
     50             xkbKeyTypeWireDesc *desc;
     51             register int ndx;
     52 
     53             ndx = i + rep->firstType;
     54             if (ndx >= xkb->map->num_types)
     55                 xkb->map->num_types = ndx + 1;
     56 
     57             desc = (xkbKeyTypeWireDesc *)
     58                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbKeyTypeWireDesc));
     59             if (desc == NULL)
     60                 return BadLength;
     61 
     62             lastMapCount = type->map_count;
     63             if (desc->nMapEntries > 0) {
     64                 if ((type->map == NULL) ||
     65                     (desc->nMapEntries > type->map_count)) {
     66                     _XkbResizeArray(type->map, type->map_count,
     67                                   desc->nMapEntries, XkbKTMapEntryRec);
     68                     if (type->map == NULL) {
     69                         return BadAlloc;
     70                     }
     71                 }
     72             }
     73             else if (type->map != NULL) {
     74                 Xfree(type->map);
     75                 type->map_count = 0;
     76                 type->map = NULL;
     77             }
     78 
     79             if (desc->preserve && (desc->nMapEntries > 0)) {
     80                 if ((!type->preserve) || (desc->nMapEntries > lastMapCount)) {
     81                     _XkbResizeArray(type->preserve, lastMapCount,
     82                                     desc->nMapEntries, XkbModsRec);
     83                     if (type->preserve == NULL) {
     84                         return BadAlloc;
     85                     }
     86                 }
     87             }
     88             else if (type->preserve != NULL) {
     89                 Xfree(type->preserve);
     90                 type->preserve = NULL;
     91             }
     92 
     93             type->mods.mask = desc->mask;
     94             type->mods.real_mods = desc->realMods;
     95             type->mods.vmods = desc->virtualMods;
     96             type->num_levels = desc->numLevels;
     97             type->map_count = desc->nMapEntries;
     98             if (desc->nMapEntries > 0) {
     99                 register xkbKTMapEntryWireDesc *wire;
    100                 register XkbKTMapEntryPtr entry;
    101                 register int size;
    102 
    103                 size = type->map_count * SIZEOF(xkbKTMapEntryWireDesc);
    104                 wire =
    105                     (xkbKTMapEntryWireDesc *) _XkbGetReadBufferPtr(buf, size);
    106                 if (wire == NULL)
    107                     return BadLength;
    108                 entry = type->map;
    109                 for (n = 0; n < type->map_count; n++, wire++, entry++) {
    110                     entry->active = wire->active;
    111                     entry->level = wire->level;
    112                     entry->mods.mask = wire->mask;
    113                     entry->mods.real_mods = wire->realMods;
    114                     entry->mods.vmods = wire->virtualMods;
    115                 }
    116 
    117                 if (desc->preserve) {
    118                     register xkbModsWireDesc *pwire;
    119                     register XkbModsPtr preserve;
    120                     register int sz;
    121 
    122                     sz = desc->nMapEntries * SIZEOF(xkbModsWireDesc);
    123                     pwire = (xkbModsWireDesc *) _XkbGetReadBufferPtr(buf, sz);
    124                     if (pwire == NULL)
    125                         return BadLength;
    126                     preserve = type->preserve;
    127                     for (n = 0; n < desc->nMapEntries; n++, pwire++, preserve++) {
    128                         preserve->mask = pwire->mask;
    129                         preserve->vmods = pwire->virtualMods;
    130                         preserve->real_mods = pwire->realMods;
    131                     }
    132                 }
    133             }
    134         }
    135     }
    136     return Success;
    137 }
    138 
    139 static Status
    140 _XkbReadKeySyms(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    141 {
    142     register int i;
    143     XkbClientMapPtr map;
    144     int size = xkb->max_key_code + 1;
    145 
    146     if (((unsigned short) rep->firstKeySym + rep->nKeySyms) > size)
    147         return BadLength;
    148 
    149     map = xkb->map;
    150     if (map->key_sym_map == NULL) {
    151         register int offset;
    152         XkbSymMapPtr oldMap;
    153         xkbSymMapWireDesc *newMap;
    154 
    155         map->key_sym_map = _XkbTypedCalloc(size, XkbSymMapRec);
    156         if (map->key_sym_map == NULL)
    157             return BadAlloc;
    158         if (map->syms == NULL) {
    159             int sz;
    160 
    161             sz = (rep->totalSyms * 12) / 10;
    162             sz = ((sz + (unsigned) 128) / 128) * 128;
    163             map->syms = _XkbTypedCalloc(sz, KeySym);
    164             if (map->syms == NULL)
    165                 return BadAlloc;
    166             map->size_syms = sz;
    167         }
    168         offset = 1;
    169         oldMap = &map->key_sym_map[rep->firstKeySym];
    170         for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
    171             newMap = (xkbSymMapWireDesc *)
    172                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
    173             if (newMap == NULL)
    174                 return BadLength;
    175             oldMap->kt_index[0] = newMap->ktIndex[0];
    176             oldMap->kt_index[1] = newMap->ktIndex[1];
    177             oldMap->kt_index[2] = newMap->ktIndex[2];
    178             oldMap->kt_index[3] = newMap->ktIndex[3];
    179             oldMap->group_info = newMap->groupInfo;
    180             oldMap->width = newMap->width;
    181             oldMap->offset = offset;
    182             if (offset + newMap->nSyms >= map->size_syms) {
    183                 register int sz;
    184 
    185                 sz = offset + newMap->nSyms;
    186                 sz = ((sz + (unsigned) 128) / 128) * 128;
    187                 _XkbResizeArray(map->syms, map->size_syms, sz, KeySym);
    188                 if (map->syms == NULL) {
    189                     map->size_syms = 0;
    190                     return BadAlloc;
    191                 }
    192                 map->size_syms = sz;
    193             }
    194             if (newMap->nSyms > 0) {
    195                 if (_XkbReadBufferCopyKeySyms(buf, (KeySym *) &map->syms[offset],
    196                                               newMap->nSyms) == 0)
    197                     return BadLength;
    198                 offset += newMap->nSyms;
    199             }
    200             else {
    201                 map->syms[offset] = 0;
    202             }
    203         }
    204         map->num_syms = offset;
    205     }
    206     else {
    207         XkbSymMapPtr oldMap = &map->key_sym_map[rep->firstKeySym];
    208 
    209         for (i = 0; i < (int) rep->nKeySyms; i++, oldMap++) {
    210             xkbSymMapWireDesc *newMap;
    211             KeySym *newSyms;
    212             int tmp;
    213 
    214             newMap = (xkbSymMapWireDesc *)
    215                 _XkbGetReadBufferPtr(buf, SIZEOF(xkbSymMapWireDesc));
    216             if (newMap == NULL)
    217                 return BadLength;
    218 
    219             if (newMap->nSyms > 0)
    220                 tmp = newMap->nSyms;
    221             else
    222                 tmp = 0;
    223 
    224             newSyms = XkbResizeKeySyms(xkb, i + rep->firstKeySym, tmp);
    225             if (newSyms == NULL)
    226                 return BadAlloc;
    227             if (newMap->nSyms > 0) {
    228                 if (_XkbReadBufferCopyKeySyms(buf, newSyms, newMap->nSyms) == 0)
    229                     return BadLength;
    230             }
    231             else
    232                 newSyms[0] = NoSymbol;
    233             oldMap->kt_index[0] = newMap->ktIndex[0];
    234             oldMap->kt_index[1] = newMap->ktIndex[1];
    235             oldMap->kt_index[2] = newMap->ktIndex[2];
    236             oldMap->kt_index[3] = newMap->ktIndex[3];
    237             oldMap->group_info = newMap->groupInfo;
    238             oldMap->width = newMap->width;
    239         }
    240     }
    241     return Success;
    242 }
    243 
    244 static Status
    245 _XkbReadKeyActions(XkbReadBufferPtr buf, XkbDescPtr info, xkbGetMapReply *rep)
    246 {
    247     int i;
    248     CARD8 numDescBuf[248];
    249     CARD8 *numDesc = NULL;
    250     register int nKeyActs;
    251     Status ret = Success;
    252 
    253     if ((nKeyActs = rep->nKeyActs) > 0) {
    254         XkbSymMapPtr symMap;
    255 
    256         if (((int) rep->firstKeyAct + rep->nKeyActs) > (info->max_key_code + 1))
    257             return BadLength;
    258 
    259         if (nKeyActs < sizeof numDescBuf)
    260             numDesc = numDescBuf;
    261         else
    262             numDesc = Xmallocarray(nKeyActs, sizeof(CARD8));
    263 
    264         if (!_XkbCopyFromReadBuffer(buf, (char *) numDesc, nKeyActs)) {
    265             ret = BadLength;
    266             goto done;
    267         }
    268         i = XkbPaddedSize(nKeyActs) - nKeyActs;
    269         if ((i > 0) && (!_XkbSkipReadBufferData(buf, i))) {
    270             ret = BadLength;
    271             goto done;
    272         }
    273         symMap = &info->map->key_sym_map[rep->firstKeyAct];
    274         for (i = 0; i < (int) rep->nKeyActs; i++, symMap++) {
    275             if (numDesc[i] == 0) {
    276                 if ((i + rep->firstKeyAct) > (info->max_key_code + 1)) {
    277                     ret = BadLength;
    278                     goto done;
    279                 }
    280                 info->server->key_acts[i + rep->firstKeyAct] = 0;
    281             }
    282             else {
    283                 XkbAction *newActs;
    284 
    285                 /* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
    286                 /*                 either zero or XkbKeyNumSyms(info,key) */
    287                 newActs = XkbResizeKeyActions(info, i + rep->firstKeyAct,
    288                                               numDesc[i]);
    289                 if (newActs == NULL) {
    290                     ret = BadAlloc;
    291                     goto done;
    292                 }
    293                 if (!_XkbCopyFromReadBuffer(buf, (char *) newActs,
    294                             (int) (numDesc[i] * sizeof(XkbAction)))) {
    295                     ret = BadLength;
    296                     goto done;
    297                 }
    298             }
    299         }
    300     }
    301  done:
    302     if (numDesc != NULL && numDesc != numDescBuf)
    303         Xfree(numDesc);
    304     return ret;
    305 }
    306 
    307 static Status
    308 _XkbReadKeyBehaviors(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    309 {
    310     register int i;
    311 
    312     if (rep->totalKeyBehaviors > 0) {
    313         int size = xkb->max_key_code + 1;
    314 
    315         if (((int) rep->firstKeyBehavior + rep->nKeyBehaviors) > size)
    316             return BadLength;
    317         if (xkb->server->behaviors == NULL) {
    318             xkb->server->behaviors = _XkbTypedCalloc(size, XkbBehavior);
    319             if (xkb->server->behaviors == NULL)
    320                 return BadAlloc;
    321         }
    322         else {
    323             bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
    324                   (rep->nKeyBehaviors * sizeof(XkbBehavior)));
    325         }
    326         for (i = 0; i < rep->totalKeyBehaviors; i++) {
    327             xkbBehaviorWireDesc *wire;
    328 
    329             wire = (xkbBehaviorWireDesc *) _XkbGetReadBufferPtr(buf,
    330                                                SIZEOF(xkbBehaviorWireDesc));
    331             if (wire == NULL || wire->key >= size)
    332                 return BadLength;
    333             xkb->server->behaviors[wire->key].type = wire->type;
    334             xkb->server->behaviors[wire->key].data = wire->data;
    335         }
    336     }
    337     return Success;
    338 }
    339 
    340 static Status
    341 _XkbReadVirtualMods(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    342 {
    343     if (rep->virtualMods) {
    344         register int i, bit, nVMods;
    345         register char *data;
    346 
    347         for (i = nVMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    348             if (rep->virtualMods & bit)
    349                 nVMods++;
    350         }
    351         data = _XkbGetReadBufferPtr(buf, XkbPaddedSize(nVMods));
    352         if (data == NULL)
    353             return BadLength;
    354         for (i = 0, bit = 1; (i < XkbNumVirtualMods) && (nVMods > 0);
    355              i++, bit <<= 1) {
    356             if (rep->virtualMods & bit) {
    357                 xkb->server->vmods[i] = *data++;
    358                 nVMods--;
    359             }
    360         }
    361     }
    362     return Success;
    363 }
    364 
    365 static Status
    366 _XkbReadExplicitComponents(XkbReadBufferPtr buf,
    367                            XkbDescPtr xkb,
    368                            xkbGetMapReply *rep)
    369 {
    370     register int i;
    371     unsigned char *wire;
    372 
    373     if (rep->totalKeyExplicit > 0) {
    374         int size = xkb->max_key_code + 1;
    375 
    376         if (((int) rep->firstKeyExplicit + rep->nKeyExplicit) > size)
    377             return BadLength;
    378         if (xkb->server->explicit == NULL) {
    379             xkb->server->explicit = _XkbTypedCalloc(size, unsigned char);
    380 
    381             if (xkb->server->explicit == NULL)
    382                 return BadAlloc;
    383         }
    384         else {
    385             bzero(&xkb->server->explicit[rep->firstKeyExplicit],
    386                   rep->nKeyExplicit);
    387         }
    388         i = XkbPaddedSize(2 * rep->totalKeyExplicit);
    389         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
    390         if (!wire)
    391             return BadLength;
    392         for (i = 0; i < rep->totalKeyExplicit; i++, wire += 2) {
    393             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
    394                 return BadLength;
    395             xkb->server->explicit[wire[0]] = wire[1];
    396         }
    397     }
    398     return Success;
    399 }
    400 
    401 static Status
    402 _XkbReadModifierMap(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    403 {
    404     register int i;
    405     unsigned char *wire;
    406 
    407     if (rep->totalModMapKeys > 0) {
    408         if (((int) rep->firstModMapKey + rep->nModMapKeys) >
    409             (xkb->max_key_code + 1))
    410             return BadLength;
    411         if ((xkb->map->modmap == NULL) &&
    412             (XkbAllocClientMap(xkb, XkbModifierMapMask, 0) != Success)) {
    413             return BadAlloc;
    414         }
    415         else {
    416             bzero(&xkb->map->modmap[rep->firstModMapKey], rep->nModMapKeys);
    417         }
    418         i = XkbPaddedSize(2 * rep->totalModMapKeys);
    419         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
    420         if (!wire)
    421             return BadLength;
    422         for (i = 0; i < rep->totalModMapKeys; i++, wire += 2) {
    423             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
    424                 return BadLength;
    425             xkb->map->modmap[wire[0]] = wire[1];
    426         }
    427     }
    428     return Success;
    429 }
    430 
    431 static Status
    432 _XkbReadVirtualModMap(XkbReadBufferPtr buf,
    433                       XkbDescPtr xkb,
    434                       xkbGetMapReply *rep)
    435 {
    436     register int i;
    437     xkbVModMapWireDesc *wire;
    438     XkbServerMapPtr srv;
    439 
    440     if (rep->totalVModMapKeys > 0) {
    441         if (((int) rep->firstVModMapKey + rep->nVModMapKeys)
    442             > xkb->max_key_code + 1)
    443             return BadLength;
    444         if (((xkb->server == NULL) || (xkb->server->vmodmap == NULL)) &&
    445             (XkbAllocServerMap(xkb, XkbVirtualModMapMask, 0) != Success)) {
    446             return BadAlloc;
    447         }
    448         else {
    449             srv = xkb->server;
    450             if (rep->nVModMapKeys > rep->firstVModMapKey)
    451                 bzero((char *) &srv->vmodmap[rep->firstVModMapKey],
    452                       (rep->nVModMapKeys - rep->firstVModMapKey) *
    453                       sizeof(unsigned short));
    454         }
    455         srv = xkb->server;
    456         i = rep->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
    457         wire = (xkbVModMapWireDesc *) _XkbGetReadBufferPtr(buf, i);
    458         if (!wire)
    459             return BadLength;
    460         for (i = 0; i < rep->totalVModMapKeys; i++, wire++) {
    461             if ((wire->key >= xkb->min_key_code) &&
    462                 (wire->key <= xkb->max_key_code))
    463                 srv->vmodmap[wire->key] = wire->vmods;
    464         }
    465     }
    466     return Success;
    467 }
    468 
    469 static xkbGetMapReq *
    470 _XkbGetGetMapReq(Display *dpy, XkbDescPtr xkb)
    471 {
    472     xkbGetMapReq *req;
    473 
    474     GetReq(kbGetMap, req);
    475     req->reqType = dpy->xkb_info->codes->major_opcode;
    476     req->xkbReqType = X_kbGetMap;
    477     req->deviceSpec = xkb->device_spec;
    478     req->full = req->partial = 0;
    479     req->firstType = req->nTypes = 0;
    480     req->firstKeySym = req->nKeySyms = 0;
    481     req->firstKeyAct = req->nKeyActs = 0;
    482     req->firstKeyBehavior = req->nKeyBehaviors = 0;
    483     req->virtualMods = 0;
    484     req->firstKeyExplicit = req->nKeyExplicit = 0;
    485     req->firstModMapKey = req->nModMapKeys = 0;
    486     req->firstVModMapKey = req->nVModMapKeys = 0;
    487     return req;
    488 }
    489 
    490 Status
    491 _XkbReadGetMapReply(Display *dpy,
    492                     xkbGetMapReply *rep,
    493                     XkbDescPtr xkb,
    494                     int *nread_rtrn)
    495 {
    496     int extraData;
    497     unsigned mask;
    498 
    499     if (xkb->device_spec == XkbUseCoreKbd)
    500         xkb->device_spec = rep->deviceID;
    501     if (rep->maxKeyCode < rep->minKeyCode)
    502         return BadImplementation;
    503     xkb->min_key_code = rep->minKeyCode;
    504     xkb->max_key_code = rep->maxKeyCode;
    505 
    506     if (!xkb->map) {
    507         mask = rep->present & XkbAllClientInfoMask;
    508         if (mask && (XkbAllocClientMap(xkb, mask, rep->nTypes) != Success))
    509             return BadAlloc;
    510     }
    511     if (!xkb->server) {
    512         mask = rep->present & XkbAllServerInfoMask;
    513         if (mask && (XkbAllocServerMap(xkb, mask, rep->totalActs) != Success))
    514             return BadAlloc;
    515     }
    516     extraData = (int) (rep->length * 4);
    517     extraData -= (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
    518     if (rep->length) {
    519         XkbReadBufferRec buf;
    520         int left;
    521 
    522         if (_XkbInitReadBuffer(dpy, &buf, extraData)) {
    523             Status status = Success;
    524 
    525             if (nread_rtrn != NULL)
    526                 *nread_rtrn = extraData;
    527             if (status == Success)
    528                 status = _XkbReadKeyTypes(&buf, xkb, rep);
    529             if (status == Success)
    530                 status = _XkbReadKeySyms(&buf, xkb, rep);
    531             if (status == Success)
    532                 status = _XkbReadKeyActions(&buf, xkb, rep);
    533             if (status == Success)
    534                 status = _XkbReadKeyBehaviors(&buf, xkb, rep);
    535             if (status == Success)
    536                 status = _XkbReadVirtualMods(&buf, xkb, rep);
    537             if (status == Success)
    538                 status = _XkbReadExplicitComponents(&buf, xkb, rep);
    539             if (status == Success)
    540                 status = _XkbReadModifierMap(&buf, xkb, rep);
    541             if (status == Success)
    542                 status = _XkbReadVirtualModMap(&buf, xkb, rep);
    543             left = _XkbFreeReadBuffer(&buf);
    544             if (status != Success)
    545                 return status;
    546             else if (left || buf.error)
    547                 return BadLength;
    548         }
    549         else
    550             return BadAlloc;
    551     }
    552     return Success;
    553 }
    554 
    555 static Status
    556 _XkbHandleGetMapReply(Display *dpy, XkbDescPtr xkb)
    557 {
    558     xkbGetMapReply rep;
    559 
    560     if (!_XReply(dpy, (xReply *) &rep,
    561                  ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2),
    562                  xFalse)) {
    563         return BadImplementation;
    564     }
    565     return _XkbReadGetMapReply(dpy, &rep, xkb, NULL);
    566 }
    567 
    568 Status
    569 XkbGetUpdatedMap(Display *dpy, unsigned which, XkbDescPtr xkb)
    570 {
    571     if ((dpy->flags & XlibDisplayNoXkb) ||
    572         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    573         return BadAccess;
    574     if (which) {
    575         register xkbGetMapReq *req;
    576         Status status;
    577 
    578         LockDisplay(dpy);
    579 
    580         req = _XkbGetGetMapReq(dpy, xkb);
    581         req->full = which;
    582         status = _XkbHandleGetMapReply(dpy, xkb);
    583 
    584         UnlockDisplay(dpy);
    585         SyncHandle();
    586         return status;
    587     }
    588     return Success;
    589 }
    590 
    591 XkbDescPtr
    592 XkbGetMap(Display *dpy, unsigned which, unsigned deviceSpec)
    593 {
    594     XkbDescPtr xkb;
    595 
    596     xkb = _XkbTypedCalloc(1, XkbDescRec);
    597     if (xkb) {
    598         xkb->device_spec = deviceSpec;
    599         xkb->map = _XkbTypedCalloc(1, XkbClientMapRec);
    600         if ((xkb->map == NULL) ||
    601             ((which) && (XkbGetUpdatedMap(dpy, which, xkb) != Success))) {
    602             if (xkb->map) {
    603                 Xfree(xkb->map);
    604                 xkb->map = NULL;
    605             }
    606             Xfree(xkb);
    607             return NULL;
    608         }
    609         xkb->dpy = dpy;
    610     }
    611     return xkb;
    612 }
    613 
    614 Status
    615 XkbGetKeyTypes(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    616 {
    617     register xkbGetMapReq *req;
    618     Status status;
    619 
    620     if ((dpy->flags & XlibDisplayNoXkb) ||
    621         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    622         return BadAccess;
    623     if ((num < 1) || (num > XkbMaxKeyTypes))
    624         return BadValue;
    625 
    626     LockDisplay(dpy);
    627 
    628     req = _XkbGetGetMapReq(dpy, xkb);
    629     req->firstType = first;
    630     req->nTypes = num;
    631     status = _XkbHandleGetMapReply(dpy, xkb);
    632 
    633     UnlockDisplay(dpy);
    634     SyncHandle();
    635     return status;
    636 }
    637 
    638 Status
    639 XkbGetKeyActions(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    640 {
    641     register xkbGetMapReq *req;
    642     Status status;
    643 
    644     if ((dpy->flags & XlibDisplayNoXkb) ||
    645         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    646         return BadAccess;
    647 
    648     if ((num < 1) || (num > XkbMaxKeyCount))
    649         return BadValue;
    650 
    651     LockDisplay(dpy);
    652 
    653     req = _XkbGetGetMapReq(dpy, xkb);
    654     req->firstKeyAct = first;
    655     req->nKeyActs = num;
    656     status = _XkbHandleGetMapReply(dpy, xkb);
    657 
    658     UnlockDisplay(dpy);
    659     SyncHandle();
    660     return status;
    661 }
    662 
    663 Status
    664 XkbGetKeySyms(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    665 {
    666     register xkbGetMapReq *req;
    667     Status status;
    668 
    669     if ((dpy->flags & XlibDisplayNoXkb) ||
    670         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    671         return BadAccess;
    672 
    673     if ((num < 1) || (num > XkbMaxKeyCount))
    674         return BadValue;
    675 
    676     LockDisplay(dpy);
    677 
    678     req = _XkbGetGetMapReq(dpy, xkb);
    679     req->firstKeySym = first;
    680     req->nKeySyms = num;
    681     status = _XkbHandleGetMapReply(dpy, xkb);
    682 
    683     UnlockDisplay(dpy);
    684     SyncHandle();
    685 
    686     return status;
    687 }
    688 
    689 Status
    690 XkbGetKeyBehaviors(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    691 {
    692     register xkbGetMapReq *req;
    693     Status status;
    694 
    695     if ((dpy->flags & XlibDisplayNoXkb) ||
    696         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    697         return BadAccess;
    698 
    699     if ((num < 1) || (num > XkbMaxKeyCount))
    700         return BadValue;
    701 
    702     LockDisplay(dpy);
    703 
    704     req = _XkbGetGetMapReq(dpy, xkb);
    705     req->firstKeyBehavior = first;
    706     req->nKeyBehaviors = num;
    707     status = _XkbHandleGetMapReply(dpy, xkb);
    708 
    709     UnlockDisplay(dpy);
    710     SyncHandle();
    711     return status;
    712 }
    713 
    714 Status
    715 XkbGetVirtualMods(Display *dpy, unsigned which, XkbDescPtr xkb)
    716 {
    717     register xkbGetMapReq *req;
    718     Status status;
    719 
    720     if ((dpy->flags & XlibDisplayNoXkb) ||
    721         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    722         return BadAccess;
    723 
    724     LockDisplay(dpy);
    725 
    726     req = _XkbGetGetMapReq(dpy, xkb);
    727     req->virtualMods = which;
    728     status = _XkbHandleGetMapReply(dpy, xkb);
    729 
    730     UnlockDisplay(dpy);
    731     SyncHandle();
    732     return status;
    733 }
    734 
    735 Status
    736 XkbGetKeyExplicitComponents(Display *dpy,
    737                             unsigned first,
    738                             unsigned num,
    739                             XkbDescPtr xkb)
    740 {
    741     register xkbGetMapReq *req;
    742     Status status;
    743 
    744     if ((dpy->flags & XlibDisplayNoXkb) ||
    745         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    746         return BadAccess;
    747 
    748     if ((num < 1) || (num > XkbMaxKeyCount))
    749         return BadValue;
    750 
    751     LockDisplay(dpy);
    752 
    753     req = _XkbGetGetMapReq(dpy, xkb);
    754     req->firstKeyExplicit = first;
    755     req->nKeyExplicit = num;
    756     if ((xkb != NULL) && (xkb->server != NULL) &&
    757         (xkb->server->explicit != NULL)) {
    758         if ((num > 0) && (first >= xkb->min_key_code) &&
    759             (first + num <= xkb->max_key_code))
    760             bzero(&xkb->server->explicit[first], num);
    761     }
    762     if (xkb)
    763         status = _XkbHandleGetMapReply(dpy, xkb);
    764     else
    765         status = BadMatch;
    766 
    767     UnlockDisplay(dpy);
    768     SyncHandle();
    769     return status;
    770 }
    771 
    772 Status
    773 XkbGetKeyModifierMap(Display *dpy,
    774                      unsigned first,
    775                      unsigned num,
    776                      XkbDescPtr xkb)
    777 {
    778     register xkbGetMapReq *req;
    779     Status status;
    780 
    781     if ((dpy->flags & XlibDisplayNoXkb) ||
    782         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    783         return BadAccess;
    784 
    785     if ((num < 1) || (num > XkbMaxKeyCount))
    786         return BadValue;
    787 
    788     LockDisplay(dpy);
    789 
    790     req = _XkbGetGetMapReq(dpy, xkb);
    791     req->firstModMapKey = first;
    792     req->nModMapKeys = num;
    793     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
    794         if ((num > 0) && (first >= xkb->min_key_code) &&
    795             (first + num <= xkb->max_key_code))
    796             bzero(&xkb->map->modmap[first], num);
    797     }
    798     if (xkb)
    799         status = _XkbHandleGetMapReply(dpy, xkb);
    800     else
    801         status = BadMatch;
    802 
    803     UnlockDisplay(dpy);
    804     SyncHandle();
    805     return status;
    806 }
    807 
    808 Status
    809 XkbGetKeyVirtualModMap(Display *dpy, unsigned first, unsigned num,
    810                        XkbDescPtr xkb)
    811 {
    812     register xkbGetMapReq *req;
    813     Status status;
    814 
    815     if ((dpy->flags & XlibDisplayNoXkb) ||
    816         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    817         return BadAccess;
    818 
    819     if ((num < 1) || (num > XkbMaxKeyCount))
    820         return BadValue;
    821 
    822     LockDisplay(dpy);
    823 
    824     req = _XkbGetGetMapReq(dpy, xkb);
    825     req->firstVModMapKey = first;
    826     req->nVModMapKeys = num;
    827     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
    828         if ((num > 0) && (first >= xkb->min_key_code) &&
    829             (first + num <= xkb->max_key_code))
    830             bzero(&xkb->server->vmodmap[first], num * sizeof(unsigned short));
    831     }
    832 
    833     if (xkb)
    834         status = _XkbHandleGetMapReply(dpy, xkb);
    835     else
    836         status = BadMatch;
    837 
    838     UnlockDisplay(dpy);
    839     SyncHandle();
    840     return status;
    841 }
    842 
    843 Status
    844 XkbGetMapChanges(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
    845 {
    846     xkbGetMapReq *req;
    847 
    848     if ((dpy->flags & XlibDisplayNoXkb) ||
    849         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    850         return BadAccess;
    851     LockDisplay(dpy);
    852     if (changes->changed) {
    853         Status status = Success;
    854 
    855         req = _XkbGetGetMapReq(dpy, xkb);
    856         req->full = 0;
    857         req->partial = changes->changed;
    858         req->firstType = changes->first_type;
    859         req->nTypes = changes->num_types;
    860         req->firstKeySym = changes->first_key_sym;
    861         req->nKeySyms = changes->num_key_syms;
    862         req->firstKeyAct = changes->first_key_act;
    863         req->nKeyActs = changes->num_key_acts;
    864         req->firstKeyBehavior = changes->first_key_behavior;
    865         req->nKeyBehaviors = changes->num_key_behaviors;
    866         req->virtualMods = changes->vmods;
    867         req->firstKeyExplicit = changes->first_key_explicit;
    868         req->nKeyExplicit = changes->num_key_explicit;
    869         req->firstModMapKey = changes->first_modmap_key;
    870         req->nModMapKeys = changes->num_modmap_keys;
    871         req->firstVModMapKey = changes->first_vmodmap_key;
    872         req->nVModMapKeys = changes->num_vmodmap_keys;
    873         status = _XkbHandleGetMapReply(dpy, xkb);
    874         UnlockDisplay(dpy);
    875         SyncHandle();
    876         return status;
    877     }
    878     UnlockDisplay(dpy);
    879     return Success;
    880 }
    881