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 (nKeyActs < sizeof numDescBuf)
    257             numDesc = numDescBuf;
    258         else
    259             numDesc = Xmallocarray(nKeyActs, sizeof(CARD8));
    260 
    261         if (!_XkbCopyFromReadBuffer(buf, (char *) numDesc, nKeyActs)) {
    262             ret = BadLength;
    263             goto done;
    264         }
    265         i = XkbPaddedSize(nKeyActs) - nKeyActs;
    266         if ((i > 0) && (!_XkbSkipReadBufferData(buf, i))) {
    267             ret = BadLength;
    268             goto done;
    269         }
    270         symMap = &info->map->key_sym_map[rep->firstKeyAct];
    271         for (i = 0; i < (int) rep->nKeyActs; i++, symMap++) {
    272             if (numDesc[i] == 0) {
    273                 if ((i + rep->firstKeyAct) > (info->max_key_code + 1)) {
    274                     ret = BadLength;
    275                     goto done;
    276                 }
    277                 info->server->key_acts[i + rep->firstKeyAct] = 0;
    278             }
    279             else {
    280                 XkbAction *newActs;
    281 
    282                 /* 8/16/93 (ef) -- XXX! Verify size here (numdesc must be */
    283                 /*                 either zero or XkbKeyNumSyms(info,key) */
    284                 newActs = XkbResizeKeyActions(info, i + rep->firstKeyAct,
    285                                               numDesc[i]);
    286                 if (newActs == NULL) {
    287                     ret = BadAlloc;
    288                     goto done;
    289                 }
    290                 if (!_XkbCopyFromReadBuffer(buf, (char *) newActs,
    291                             (int) (numDesc[i] * sizeof(XkbAction)))) {
    292                     ret = BadLength;
    293                     goto done;
    294                 }
    295             }
    296         }
    297     }
    298  done:
    299     if (numDesc != NULL && numDesc != numDescBuf)
    300         Xfree(numDesc);
    301     return ret;
    302 }
    303 
    304 static Status
    305 _XkbReadKeyBehaviors(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    306 {
    307     register int i;
    308 
    309     if (rep->totalKeyBehaviors > 0) {
    310         int size = xkb->max_key_code + 1;
    311 
    312         if (((int) rep->firstKeyBehavior + rep->nKeyBehaviors) > size)
    313             return BadLength;
    314         if (xkb->server->behaviors == NULL) {
    315             xkb->server->behaviors = _XkbTypedCalloc(size, XkbBehavior);
    316             if (xkb->server->behaviors == NULL)
    317                 return BadAlloc;
    318         }
    319         else {
    320             bzero(&xkb->server->behaviors[rep->firstKeyBehavior],
    321                   (rep->nKeyBehaviors * sizeof(XkbBehavior)));
    322         }
    323         for (i = 0; i < rep->totalKeyBehaviors; i++) {
    324             xkbBehaviorWireDesc *wire;
    325 
    326             wire = (xkbBehaviorWireDesc *) _XkbGetReadBufferPtr(buf,
    327                                                SIZEOF(xkbBehaviorWireDesc));
    328             if (wire == NULL || wire->key >= size)
    329                 return BadLength;
    330             xkb->server->behaviors[wire->key].type = wire->type;
    331             xkb->server->behaviors[wire->key].data = wire->data;
    332         }
    333     }
    334     return Success;
    335 }
    336 
    337 static Status
    338 _XkbReadVirtualMods(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    339 {
    340     if (rep->virtualMods) {
    341         register int i, bit, nVMods;
    342         register char *data;
    343 
    344         for (i = nVMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    345             if (rep->virtualMods & bit)
    346                 nVMods++;
    347         }
    348         data = _XkbGetReadBufferPtr(buf, XkbPaddedSize(nVMods));
    349         if (data == NULL)
    350             return BadLength;
    351         for (i = 0, bit = 1; (i < XkbNumVirtualMods) && (nVMods > 0);
    352              i++, bit <<= 1) {
    353             if (rep->virtualMods & bit) {
    354                 xkb->server->vmods[i] = *data++;
    355                 nVMods--;
    356             }
    357         }
    358     }
    359     return Success;
    360 }
    361 
    362 static Status
    363 _XkbReadExplicitComponents(XkbReadBufferPtr buf,
    364                            XkbDescPtr xkb,
    365                            xkbGetMapReply *rep)
    366 {
    367     register int i;
    368     unsigned char *wire;
    369 
    370     if (rep->totalKeyExplicit > 0) {
    371         int size = xkb->max_key_code + 1;
    372 
    373         if (((int) rep->firstKeyExplicit + rep->nKeyExplicit) > size)
    374             return BadLength;
    375         if (xkb->server->explicit == NULL) {
    376             xkb->server->explicit = _XkbTypedCalloc(size, unsigned char);
    377 
    378             if (xkb->server->explicit == NULL)
    379                 return BadAlloc;
    380         }
    381         else {
    382             bzero(&xkb->server->explicit[rep->firstKeyExplicit],
    383                   rep->nKeyExplicit);
    384         }
    385         i = XkbPaddedSize(2 * rep->totalKeyExplicit);
    386         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
    387         if (!wire)
    388             return BadLength;
    389         for (i = 0; i < rep->totalKeyExplicit; i++, wire += 2) {
    390             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
    391                 return BadLength;
    392             xkb->server->explicit[wire[0]] = wire[1];
    393         }
    394     }
    395     return Success;
    396 }
    397 
    398 static Status
    399 _XkbReadModifierMap(XkbReadBufferPtr buf, XkbDescPtr xkb, xkbGetMapReply *rep)
    400 {
    401     register int i;
    402     unsigned char *wire;
    403 
    404     if (rep->totalModMapKeys > 0) {
    405         if (((int) rep->firstModMapKey + rep->nModMapKeys) >
    406             (xkb->max_key_code + 1))
    407             return BadLength;
    408         if ((xkb->map->modmap == NULL) &&
    409             (XkbAllocClientMap(xkb, XkbModifierMapMask, 0) != Success)) {
    410             return BadAlloc;
    411         }
    412         else {
    413             bzero(&xkb->map->modmap[rep->firstModMapKey], rep->nModMapKeys);
    414         }
    415         i = XkbPaddedSize(2 * rep->totalModMapKeys);
    416         wire = (unsigned char *) _XkbGetReadBufferPtr(buf, i);
    417         if (!wire)
    418             return BadLength;
    419         for (i = 0; i < rep->totalModMapKeys; i++, wire += 2) {
    420             if (wire[0] > xkb->max_key_code || wire[1] > xkb->max_key_code)
    421                 return BadLength;
    422             xkb->map->modmap[wire[0]] = wire[1];
    423         }
    424     }
    425     return Success;
    426 }
    427 
    428 static Status
    429 _XkbReadVirtualModMap(XkbReadBufferPtr buf,
    430                       XkbDescPtr xkb,
    431                       xkbGetMapReply *rep)
    432 {
    433     register int i;
    434     xkbVModMapWireDesc *wire;
    435     XkbServerMapPtr srv;
    436 
    437     if (rep->totalVModMapKeys > 0) {
    438         if (((int) rep->firstVModMapKey + rep->nVModMapKeys)
    439             > xkb->max_key_code + 1)
    440             return BadLength;
    441         if (((xkb->server == NULL) || (xkb->server->vmodmap == NULL)) &&
    442             (XkbAllocServerMap(xkb, XkbVirtualModMapMask, 0) != Success)) {
    443             return BadAlloc;
    444         }
    445         else {
    446             srv = xkb->server;
    447             if (rep->nVModMapKeys > rep->firstVModMapKey)
    448                 bzero((char *) &srv->vmodmap[rep->firstVModMapKey],
    449                       (rep->nVModMapKeys - rep->firstVModMapKey) *
    450                       sizeof(unsigned short));
    451         }
    452         srv = xkb->server;
    453         i = rep->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
    454         wire = (xkbVModMapWireDesc *) _XkbGetReadBufferPtr(buf, i);
    455         if (!wire)
    456             return BadLength;
    457         for (i = 0; i < rep->totalVModMapKeys; i++, wire++) {
    458             if ((wire->key >= xkb->min_key_code) &&
    459                 (wire->key <= xkb->max_key_code))
    460                 srv->vmodmap[wire->key] = wire->vmods;
    461         }
    462     }
    463     return Success;
    464 }
    465 
    466 static xkbGetMapReq *
    467 _XkbGetGetMapReq(Display *dpy, XkbDescPtr xkb)
    468 {
    469     xkbGetMapReq *req;
    470 
    471     GetReq(kbGetMap, req);
    472     req->reqType = dpy->xkb_info->codes->major_opcode;
    473     req->xkbReqType = X_kbGetMap;
    474     req->deviceSpec = xkb->device_spec;
    475     req->full = req->partial = 0;
    476     req->firstType = req->nTypes = 0;
    477     req->firstKeySym = req->nKeySyms = 0;
    478     req->firstKeyAct = req->nKeyActs = 0;
    479     req->firstKeyBehavior = req->nKeyBehaviors = 0;
    480     req->virtualMods = 0;
    481     req->firstKeyExplicit = req->nKeyExplicit = 0;
    482     req->firstModMapKey = req->nModMapKeys = 0;
    483     req->firstVModMapKey = req->nVModMapKeys = 0;
    484     return req;
    485 }
    486 
    487 Status
    488 _XkbReadGetMapReply(Display *dpy,
    489                     xkbGetMapReply *rep,
    490                     XkbDescPtr xkb,
    491                     int *nread_rtrn)
    492 {
    493     int extraData;
    494     unsigned mask;
    495 
    496     if (xkb->device_spec == XkbUseCoreKbd)
    497         xkb->device_spec = rep->deviceID;
    498     if (rep->maxKeyCode < rep->minKeyCode)
    499         return BadImplementation;
    500     xkb->min_key_code = rep->minKeyCode;
    501     xkb->max_key_code = rep->maxKeyCode;
    502 
    503     if (!xkb->map) {
    504         mask = rep->present & XkbAllClientInfoMask;
    505         if (mask && (XkbAllocClientMap(xkb, mask, rep->nTypes) != Success))
    506             return BadAlloc;
    507     }
    508     if (!xkb->server) {
    509         mask = rep->present & XkbAllServerInfoMask;
    510         if (mask && (XkbAllocServerMap(xkb, mask, rep->totalActs) != Success))
    511             return BadAlloc;
    512     }
    513     extraData = (int) (rep->length * 4);
    514     extraData -= (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
    515     if (rep->length) {
    516         XkbReadBufferRec buf;
    517         int left;
    518 
    519         if (_XkbInitReadBuffer(dpy, &buf, extraData)) {
    520             Status status = Success;
    521 
    522             if (nread_rtrn != NULL)
    523                 *nread_rtrn = extraData;
    524             if (status == Success)
    525                 status = _XkbReadKeyTypes(&buf, xkb, rep);
    526             if (status == Success)
    527                 status = _XkbReadKeySyms(&buf, xkb, rep);
    528             if (status == Success)
    529                 status = _XkbReadKeyActions(&buf, xkb, rep);
    530             if (status == Success)
    531                 status = _XkbReadKeyBehaviors(&buf, xkb, rep);
    532             if (status == Success)
    533                 status = _XkbReadVirtualMods(&buf, xkb, rep);
    534             if (status == Success)
    535                 status = _XkbReadExplicitComponents(&buf, xkb, rep);
    536             if (status == Success)
    537                 status = _XkbReadModifierMap(&buf, xkb, rep);
    538             if (status == Success)
    539                 status = _XkbReadVirtualModMap(&buf, xkb, rep);
    540             left = _XkbFreeReadBuffer(&buf);
    541             if (status != Success)
    542                 return status;
    543             else if (left || buf.error)
    544                 return BadLength;
    545         }
    546         else
    547             return BadAlloc;
    548     }
    549     return Success;
    550 }
    551 
    552 static Status
    553 _XkbHandleGetMapReply(Display *dpy, XkbDescPtr xkb)
    554 {
    555     xkbGetMapReply rep;
    556 
    557     if (!_XReply(dpy, (xReply *) &rep,
    558                  ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2),
    559                  xFalse)) {
    560         return BadImplementation;
    561     }
    562     return _XkbReadGetMapReply(dpy, &rep, xkb, NULL);
    563 }
    564 
    565 Status
    566 XkbGetUpdatedMap(Display *dpy, unsigned which, XkbDescPtr xkb)
    567 {
    568     if ((dpy->flags & XlibDisplayNoXkb) ||
    569         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    570         return BadAccess;
    571     if (which) {
    572         register xkbGetMapReq *req;
    573         Status status;
    574 
    575         LockDisplay(dpy);
    576 
    577         req = _XkbGetGetMapReq(dpy, xkb);
    578         req->full = which;
    579         status = _XkbHandleGetMapReply(dpy, xkb);
    580 
    581         UnlockDisplay(dpy);
    582         SyncHandle();
    583         return status;
    584     }
    585     return Success;
    586 }
    587 
    588 XkbDescPtr
    589 XkbGetMap(Display *dpy, unsigned which, unsigned deviceSpec)
    590 {
    591     XkbDescPtr xkb;
    592 
    593     xkb = _XkbTypedCalloc(1, XkbDescRec);
    594     if (xkb) {
    595         xkb->device_spec = deviceSpec;
    596         xkb->map = _XkbTypedCalloc(1, XkbClientMapRec);
    597         if ((xkb->map == NULL) ||
    598             ((which) && (XkbGetUpdatedMap(dpy, which, xkb) != Success))) {
    599             if (xkb->map) {
    600                 Xfree(xkb->map);
    601                 xkb->map = NULL;
    602             }
    603             Xfree(xkb);
    604             return NULL;
    605         }
    606         xkb->dpy = dpy;
    607     }
    608     return xkb;
    609 }
    610 
    611 Status
    612 XkbGetKeyTypes(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    613 {
    614     register xkbGetMapReq *req;
    615     Status status;
    616 
    617     if ((dpy->flags & XlibDisplayNoXkb) ||
    618         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    619         return BadAccess;
    620     if ((num < 1) || (num > XkbMaxKeyTypes))
    621         return BadValue;
    622 
    623     LockDisplay(dpy);
    624 
    625     req = _XkbGetGetMapReq(dpy, xkb);
    626     req->firstType = first;
    627     req->nTypes = num;
    628     status = _XkbHandleGetMapReply(dpy, xkb);
    629 
    630     UnlockDisplay(dpy);
    631     SyncHandle();
    632     return status;
    633 }
    634 
    635 Status
    636 XkbGetKeyActions(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    637 {
    638     register xkbGetMapReq *req;
    639     Status status;
    640 
    641     if ((dpy->flags & XlibDisplayNoXkb) ||
    642         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    643         return BadAccess;
    644 
    645     if ((num < 1) || (num > XkbMaxKeyCount))
    646         return BadValue;
    647 
    648     LockDisplay(dpy);
    649 
    650     req = _XkbGetGetMapReq(dpy, xkb);
    651     req->firstKeyAct = first;
    652     req->nKeyActs = num;
    653     status = _XkbHandleGetMapReply(dpy, xkb);
    654 
    655     UnlockDisplay(dpy);
    656     SyncHandle();
    657     return status;
    658 }
    659 
    660 Status
    661 XkbGetKeySyms(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    662 {
    663     register xkbGetMapReq *req;
    664     Status status;
    665 
    666     if ((dpy->flags & XlibDisplayNoXkb) ||
    667         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    668         return BadAccess;
    669 
    670     if ((num < 1) || (num > XkbMaxKeyCount))
    671         return BadValue;
    672 
    673     LockDisplay(dpy);
    674 
    675     req = _XkbGetGetMapReq(dpy, xkb);
    676     req->firstKeySym = first;
    677     req->nKeySyms = num;
    678     status = _XkbHandleGetMapReply(dpy, xkb);
    679 
    680     UnlockDisplay(dpy);
    681     SyncHandle();
    682 
    683     return status;
    684 }
    685 
    686 Status
    687 XkbGetKeyBehaviors(Display *dpy, unsigned first, unsigned num, XkbDescPtr xkb)
    688 {
    689     register xkbGetMapReq *req;
    690     Status status;
    691 
    692     if ((dpy->flags & XlibDisplayNoXkb) ||
    693         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    694         return BadAccess;
    695 
    696     if ((num < 1) || (num > XkbMaxKeyCount))
    697         return BadValue;
    698 
    699     LockDisplay(dpy);
    700 
    701     req = _XkbGetGetMapReq(dpy, xkb);
    702     req->firstKeyBehavior = first;
    703     req->nKeyBehaviors = num;
    704     status = _XkbHandleGetMapReply(dpy, xkb);
    705 
    706     UnlockDisplay(dpy);
    707     SyncHandle();
    708     return status;
    709 }
    710 
    711 Status
    712 XkbGetVirtualMods(Display *dpy, unsigned which, XkbDescPtr xkb)
    713 {
    714     register xkbGetMapReq *req;
    715     Status status;
    716 
    717     if ((dpy->flags & XlibDisplayNoXkb) ||
    718         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    719         return BadAccess;
    720 
    721     LockDisplay(dpy);
    722 
    723     req = _XkbGetGetMapReq(dpy, xkb);
    724     req->virtualMods = which;
    725     status = _XkbHandleGetMapReply(dpy, xkb);
    726 
    727     UnlockDisplay(dpy);
    728     SyncHandle();
    729     return status;
    730 }
    731 
    732 Status
    733 XkbGetKeyExplicitComponents(Display *dpy,
    734                             unsigned first,
    735                             unsigned num,
    736                             XkbDescPtr xkb)
    737 {
    738     register xkbGetMapReq *req;
    739     Status status;
    740 
    741     if ((dpy->flags & XlibDisplayNoXkb) ||
    742         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    743         return BadAccess;
    744 
    745     if ((num < 1) || (num > XkbMaxKeyCount))
    746         return BadValue;
    747 
    748     LockDisplay(dpy);
    749 
    750     req = _XkbGetGetMapReq(dpy, xkb);
    751     req->firstKeyExplicit = first;
    752     req->nKeyExplicit = num;
    753     if ((xkb != NULL) && (xkb->server != NULL) &&
    754         (xkb->server->explicit != NULL)) {
    755         if ((num > 0) && (first >= xkb->min_key_code) &&
    756             (first + num <= xkb->max_key_code))
    757             bzero(&xkb->server->explicit[first], num);
    758     }
    759     if (xkb)
    760         status = _XkbHandleGetMapReply(dpy, xkb);
    761     else
    762         status = BadMatch;
    763 
    764     UnlockDisplay(dpy);
    765     SyncHandle();
    766     return status;
    767 }
    768 
    769 Status
    770 XkbGetKeyModifierMap(Display *dpy,
    771                      unsigned first,
    772                      unsigned num,
    773                      XkbDescPtr xkb)
    774 {
    775     register xkbGetMapReq *req;
    776     Status status;
    777 
    778     if ((dpy->flags & XlibDisplayNoXkb) ||
    779         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    780         return BadAccess;
    781 
    782     if ((num < 1) || (num > XkbMaxKeyCount))
    783         return BadValue;
    784 
    785     LockDisplay(dpy);
    786 
    787     req = _XkbGetGetMapReq(dpy, xkb);
    788     req->firstModMapKey = first;
    789     req->nModMapKeys = num;
    790     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
    791         if ((num > 0) && (first >= xkb->min_key_code) &&
    792             (first + num <= xkb->max_key_code))
    793             bzero(&xkb->map->modmap[first], num);
    794     }
    795     if (xkb)
    796         status = _XkbHandleGetMapReply(dpy, xkb);
    797     else
    798         status = BadMatch;
    799 
    800     UnlockDisplay(dpy);
    801     SyncHandle();
    802     return status;
    803 }
    804 
    805 Status
    806 XkbGetKeyVirtualModMap(Display *dpy, unsigned first, unsigned num,
    807                        XkbDescPtr xkb)
    808 {
    809     register xkbGetMapReq *req;
    810     Status status;
    811 
    812     if ((dpy->flags & XlibDisplayNoXkb) ||
    813         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    814         return BadAccess;
    815 
    816     if ((num < 1) || (num > XkbMaxKeyCount))
    817         return BadValue;
    818 
    819     LockDisplay(dpy);
    820 
    821     req = _XkbGetGetMapReq(dpy, xkb);
    822     req->firstVModMapKey = first;
    823     req->nVModMapKeys = num;
    824     if ((xkb != NULL) && (xkb->map != NULL) && (xkb->map->modmap != NULL)) {
    825         if ((num > 0) && (first >= xkb->min_key_code) &&
    826             (first + num <= xkb->max_key_code))
    827             bzero(&xkb->server->vmodmap[first], num * sizeof(unsigned short));
    828     }
    829 
    830     if (xkb)
    831         status = _XkbHandleGetMapReply(dpy, xkb);
    832     else
    833         status = BadMatch;
    834 
    835     UnlockDisplay(dpy);
    836     SyncHandle();
    837     return status;
    838 }
    839 
    840 Status
    841 XkbGetMapChanges(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
    842 {
    843     xkbGetMapReq *req;
    844 
    845     if ((dpy->flags & XlibDisplayNoXkb) ||
    846         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    847         return BadAccess;
    848     LockDisplay(dpy);
    849     if (changes->changed) {
    850         Status status = Success;
    851 
    852         req = _XkbGetGetMapReq(dpy, xkb);
    853         req->full = 0;
    854         req->partial = changes->changed;
    855         req->firstType = changes->first_type;
    856         req->nTypes = changes->num_types;
    857         req->firstKeySym = changes->first_key_sym;
    858         req->nKeySyms = changes->num_key_syms;
    859         req->firstKeyAct = changes->first_key_act;
    860         req->nKeyActs = changes->num_key_acts;
    861         req->firstKeyBehavior = changes->first_key_behavior;
    862         req->nKeyBehaviors = changes->num_key_behaviors;
    863         req->virtualMods = changes->vmods;
    864         req->firstKeyExplicit = changes->first_key_explicit;
    865         req->nKeyExplicit = changes->num_key_explicit;
    866         req->firstModMapKey = changes->first_modmap_key;
    867         req->nModMapKeys = changes->num_modmap_keys;
    868         req->firstVModMapKey = changes->first_vmodmap_key;
    869         req->nVModMapKeys = changes->num_vmodmap_keys;
    870         status = _XkbHandleGetMapReply(dpy, xkb);
    871         UnlockDisplay(dpy);
    872         SyncHandle();
    873         return status;
    874     }
    875     UnlockDisplay(dpy);
    876     return Success;
    877 }
    878