Home | History | Annotate | Line # | Download | only in xkb
      1 /************************************************************
      2 Copyright (c) 1995 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 #include <X11/extensions/XI.h>
     36 
     37 /***====================================================================***/
     38 
     39 void
     40 XkbNoteDeviceChanges(XkbDeviceChangesPtr old,
     41                      XkbExtensionDeviceNotifyEvent *new,
     42                      unsigned int wanted)
     43 {
     44     if ((!old) || (!new) || (!wanted) || ((new->reason & wanted) == 0))
     45         return;
     46     if ((wanted & new->reason) & XkbXI_ButtonActionsMask) {
     47         if (old->changed & XkbXI_ButtonActionsMask) {
     48             int first, last, newLast;
     49 
     50             if (new->first_btn < old->first_btn)
     51                 first = new->first_btn;
     52             else
     53                 first = old->first_btn;
     54             last = old->first_btn + old->num_btns - 1;
     55             newLast = new->first_btn + new->num_btns - 1;
     56             if (newLast > last)
     57                 last = newLast;
     58             old->first_btn = first;
     59             old->num_btns = (last - first) + 1;
     60         }
     61         else {
     62             old->changed |= XkbXI_ButtonActionsMask;
     63             old->first_btn = new->first_btn;
     64             old->num_btns = new->num_btns;
     65         }
     66     }
     67     if ((wanted & new->reason) & XkbXI_IndicatorsMask) {
     68         XkbDeviceLedChangesPtr this;
     69 
     70         if (old->changed & XkbXI_IndicatorsMask) {
     71             XkbDeviceLedChangesPtr found = NULL;
     72 
     73             for (this = &old->leds; this && (!found); this = this->next) {
     74                 if ((this->led_class == new->led_class) &&
     75                     (this->led_id == new->led_id)) {
     76                     found = this;
     77                 }
     78             }
     79             if (!found) {
     80                 found = _XkbTypedCalloc(1, XkbDeviceLedChangesRec);
     81                 if (!found)
     82                     return;
     83                 found->next = old->leds.next;
     84                 found->led_class = new->led_class;
     85                 found->led_id = new->led_id;
     86                 old->leds.next = found;
     87             }
     88             if ((wanted & new->reason) & XkbXI_IndicatorNamesMask)
     89                 found->defined = new->leds_defined;
     90         }
     91         else {
     92             old->changed |= ((wanted & new->reason) & XkbXI_IndicatorsMask);
     93             old->leds.led_class = new->led_class;
     94             old->leds.led_id = new->led_id;
     95             old->leds.defined = new->leds_defined;
     96             if (old->leds.next) {
     97                 XkbDeviceLedChangesPtr next;
     98 
     99                 for (this = old->leds.next; this; this = next) {
    100                     next = this->next;
    101                     _XkbFree(this);
    102                 }
    103                 old->leds.next = NULL;
    104             }
    105         }
    106     }
    107     return;
    108 }
    109 
    110 /***====================================================================***/
    111 
    112 static Status
    113 _XkbReadDeviceLedInfo(XkbReadBufferPtr buf,
    114                       unsigned present,
    115                       XkbDeviceInfoPtr devi)
    116 {
    117     register unsigned i, bit;
    118     XkbDeviceLedInfoPtr devli;
    119     xkbDeviceLedsWireDesc *wireli;
    120 
    121     wireli = _XkbGetTypedRdBufPtr(buf, 1, xkbDeviceLedsWireDesc);
    122     if (!wireli)
    123         return BadLength;
    124     devli = XkbAddDeviceLedInfo(devi, wireli->ledClass, wireli->ledID);
    125     if (!devli)
    126         return BadAlloc;
    127     devli->phys_indicators = wireli->physIndicators;
    128 
    129     if (present & XkbXI_IndicatorStateMask)
    130         devli->state = wireli->state;
    131 
    132     if (present & XkbXI_IndicatorNamesMask) {
    133         devli->names_present = wireli->namesPresent;
    134         if (devli->names_present) {
    135             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    136                 if (wireli->namesPresent & bit) {
    137                     if (!_XkbCopyFromReadBuffer(buf,
    138                                                 (char *) &devli->names[i], 4))
    139                         return BadLength;
    140                 }
    141             }
    142         }
    143     }
    144 
    145     if (present & XkbXI_IndicatorMapsMask) {
    146         devli->maps_present = wireli->mapsPresent;
    147         if (devli->maps_present) {
    148             XkbIndicatorMapPtr im;
    149             xkbIndicatorMapWireDesc *wireim;
    150 
    151             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    152                 if (wireli->mapsPresent & bit) {
    153                     wireim =
    154                         _XkbGetTypedRdBufPtr(buf, 1, xkbIndicatorMapWireDesc);
    155                     if (!wireim)
    156                         return BadAlloc;
    157                     im = &devli->maps[i];
    158                     im->flags = wireim->flags;
    159                     im->which_groups = wireim->whichGroups;
    160                     im->groups = wireim->groups;
    161                     im->which_mods = wireim->whichMods;
    162                     im->mods.mask = wireim->mods;
    163                     im->mods.real_mods = wireim->realMods;
    164                     im->mods.vmods = wireim->virtualMods;
    165                     im->ctrls = wireim->ctrls;
    166                 }
    167             }
    168         }
    169     }
    170     return Success;
    171 }
    172 
    173 static Status
    174 _XkbReadGetDeviceInfoReply(Display *dpy,
    175                            xkbGetDeviceInfoReply *rep,
    176                            XkbDeviceInfoPtr devi)
    177 {
    178     XkbReadBufferRec buf;
    179     XkbAction *act;
    180     int tmp;
    181 
    182     if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4))
    183         return BadAlloc;
    184 
    185     if ((rep->totalBtns > 0) && (rep->totalBtns != devi->num_btns)) {
    186         tmp = XkbResizeDeviceButtonActions(devi, rep->totalBtns);
    187         if (tmp != Success)
    188             return tmp;
    189     }
    190     if (rep->nBtnsWanted > 0) {
    191         if (((unsigned short) rep->firstBtnWanted + rep->nBtnsWanted) > devi->num_btns)
    192             goto BAILOUT;
    193         act = &devi->btn_acts[rep->firstBtnWanted];
    194         bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction)));
    195     }
    196 
    197     _XkbFree(devi->name);
    198     if (!_XkbGetReadBufferCountedString(&buf, &devi->name))
    199         goto BAILOUT;
    200     if (rep->nBtnsRtrn > 0) {
    201         int size;
    202 
    203         if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn) > devi->num_btns)
    204             goto BAILOUT;
    205         act = &devi->btn_acts[rep->firstBtnRtrn];
    206         size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc);
    207         if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size))
    208             goto BAILOUT;
    209     }
    210     if (rep->nDeviceLedFBs > 0) {
    211         register int i;
    212 
    213         for (i = 0; i < rep->nDeviceLedFBs; i++) {
    214             if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi))
    215                 != Success)
    216                 return tmp;
    217         }
    218     }
    219     tmp = _XkbFreeReadBuffer(&buf);
    220     if (tmp)
    221         fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp);
    222     if (tmp || buf.error)
    223         return BadLength;
    224     return Success;
    225  BAILOUT:
    226     _XkbFreeReadBuffer(&buf);
    227     return BadLength;
    228 }
    229 
    230 XkbDeviceInfoPtr
    231 XkbGetDeviceInfo(Display *dpy,
    232                  unsigned which,
    233                  unsigned deviceSpec,
    234                  unsigned class,
    235                  unsigned id)
    236 {
    237     register xkbGetDeviceInfoReq *req;
    238     xkbGetDeviceInfoReply rep;
    239     Status status;
    240     XkbDeviceInfoPtr devi;
    241 
    242     if ((dpy->flags & XlibDisplayNoXkb) ||
    243         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    244         return NULL;
    245     LockDisplay(dpy);
    246     GetReq(kbGetDeviceInfo, req);
    247     req->reqType = dpy->xkb_info->codes->major_opcode;
    248     req->xkbReqType = X_kbGetDeviceInfo;
    249     req->deviceSpec = deviceSpec;
    250     req->wanted = which;
    251     req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0);
    252     req->firstBtn = req->nBtns = 0;
    253     req->ledClass = class;
    254     req->ledID = id;
    255     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    256         UnlockDisplay(dpy);
    257         SyncHandle();
    258         return NULL;
    259     }
    260     devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs);
    261     if (devi) {
    262         devi->supported = rep.supported;
    263         devi->unsupported = rep.unsupported;
    264         devi->type = rep.devType;
    265         devi->has_own_state = rep.hasOwnState;
    266         devi->dflt_kbd_fb = rep.dfltKbdFB;
    267         devi->dflt_led_fb = rep.dfltLedFB;
    268         status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
    269         if (status != Success) {
    270             XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True);
    271             devi = NULL;
    272         }
    273     }
    274     UnlockDisplay(dpy);
    275     SyncHandle();
    276     return devi;
    277 }
    278 
    279 Status
    280 XkbGetDeviceInfoChanges(Display *dpy,
    281                         XkbDeviceInfoPtr devi,
    282                         XkbDeviceChangesPtr changes)
    283 {
    284     register xkbGetDeviceInfoReq *req;
    285     xkbGetDeviceInfoReply rep;
    286     Status status;
    287 
    288     if ((dpy->flags & XlibDisplayNoXkb) ||
    289         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    290         return BadMatch;
    291     if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0)
    292         return Success;
    293     changes->changed &= ~XkbXI_AllDeviceFeaturesMask;
    294     status = Success;
    295     LockDisplay(dpy);
    296     while ((changes->changed) && (status == Success)) {
    297         GetReq(kbGetDeviceInfo, req);
    298         req->reqType = dpy->xkb_info->codes->major_opcode;
    299         req->xkbReqType = X_kbGetDeviceInfo;
    300         req->deviceSpec = devi->device_spec;
    301         req->wanted = changes->changed;
    302         req->allBtns = False;
    303         if (changes->changed & XkbXI_ButtonActionsMask) {
    304             req->firstBtn = changes->first_btn;
    305             req->nBtns = changes->num_btns;
    306             changes->changed &= ~XkbXI_ButtonActionsMask;
    307         }
    308         else
    309             req->firstBtn = req->nBtns = 0;
    310         if (changes->changed & XkbXI_IndicatorsMask) {
    311             req->ledClass = changes->leds.led_class;
    312             req->ledID = changes->leds.led_id;
    313             if (changes->leds.next == NULL)
    314                 changes->changed &= ~XkbXI_IndicatorsMask;
    315             else {
    316                 XkbDeviceLedChangesPtr next;
    317 
    318                 next = changes->leds.next;
    319                 changes->leds = *next;
    320                 _XkbFree(next);
    321             }
    322         }
    323         else {
    324             req->ledClass = XkbDfltXIClass;
    325             req->ledID = XkbDfltXIId;
    326         }
    327         if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    328             status = BadLength;
    329             break;
    330         }
    331         devi->supported |= rep.supported;
    332         devi->unsupported |= rep.unsupported;
    333         devi->type = rep.devType;
    334         status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
    335     }
    336     UnlockDisplay(dpy);
    337     SyncHandle();
    338     return status;
    339 }
    340 
    341 Status
    342 XkbGetDeviceButtonActions(Display *dpy,
    343                           XkbDeviceInfoPtr devi,
    344                           Bool all,
    345                           unsigned int first,
    346                           unsigned int num)
    347 {
    348     register xkbGetDeviceInfoReq *req;
    349     xkbGetDeviceInfoReply rep;
    350     Status status;
    351 
    352     if ((dpy->flags & XlibDisplayNoXkb) ||
    353         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    354         return BadMatch;
    355     if (!devi)
    356         return BadValue;
    357     LockDisplay(dpy);
    358     GetReq(kbGetDeviceInfo, req);
    359     req->reqType = dpy->xkb_info->codes->major_opcode;
    360     req->xkbReqType = X_kbGetDeviceInfo;
    361     req->deviceSpec = devi->device_spec;
    362     req->wanted = XkbXI_ButtonActionsMask;
    363     req->allBtns = all;
    364     req->firstBtn = first;
    365     req->nBtns = num;
    366     req->ledClass = XkbDfltXIClass;
    367     req->ledID = XkbDfltXIId;
    368     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    369         UnlockDisplay(dpy);
    370         SyncHandle();
    371         return BadLength;
    372     }
    373     devi->type = rep.devType;
    374     devi->supported = rep.supported;
    375     devi->unsupported = rep.unsupported;
    376     status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
    377     UnlockDisplay(dpy);
    378     SyncHandle();
    379     return status;
    380 }
    381 
    382 Status
    383 XkbGetDeviceLedInfo(Display *dpy,
    384                     XkbDeviceInfoPtr devi,
    385                     unsigned int ledClass,
    386                     unsigned int ledId,
    387                     unsigned int which)
    388 {
    389     register xkbGetDeviceInfoReq *req;
    390     xkbGetDeviceInfoReply rep;
    391     Status status;
    392 
    393     if ((dpy->flags & XlibDisplayNoXkb) ||
    394         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    395         return BadMatch;
    396     if (((which & XkbXI_IndicatorsMask) == 0) ||
    397         (which & (~XkbXI_IndicatorsMask)))
    398         return BadMatch;
    399     if (!devi)
    400         return BadValue;
    401     LockDisplay(dpy);
    402     GetReq(kbGetDeviceInfo, req);
    403     req->reqType = dpy->xkb_info->codes->major_opcode;
    404     req->xkbReqType = X_kbGetDeviceInfo;
    405     req->deviceSpec = devi->device_spec;
    406     req->wanted = which;
    407     req->allBtns = False;
    408     req->firstBtn = req->nBtns = 0;
    409     req->ledClass = ledClass;
    410     req->ledID = ledId;
    411     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    412         UnlockDisplay(dpy);
    413         SyncHandle();
    414         return BadLength;
    415     }
    416     devi->type = rep.devType;
    417     devi->supported = rep.supported;
    418     devi->unsupported = rep.unsupported;
    419     status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
    420     UnlockDisplay(dpy);
    421     SyncHandle();
    422     return status;
    423 }
    424 
    425 /***====================================================================***/
    426 
    427 typedef struct _LedInfoStuff {
    428     Bool used;
    429     XkbDeviceLedInfoPtr devli;
    430 } LedInfoStuff;
    431 
    432 typedef struct _SetLedStuff {
    433     unsigned wanted;
    434     int num_info;
    435     int dflt_class;
    436     LedInfoStuff *dflt_kbd_fb;
    437     LedInfoStuff *dflt_led_fb;
    438     LedInfoStuff *info;
    439 } SetLedStuff;
    440 
    441 static void
    442 _InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi)
    443 {
    444     int i;
    445     register XkbDeviceLedInfoPtr devli;
    446 
    447     bzero(stuff, sizeof(SetLedStuff));
    448     stuff->wanted = wanted;
    449     stuff->dflt_class = XkbXINone;
    450     if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0))
    451         return;
    452     stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff);
    453     if (!stuff->info)
    454         return;
    455     stuff->num_info = devi->num_leds;
    456     for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) {
    457         stuff->info[i].devli = devli;
    458         if (devli->led_class == KbdFeedbackClass) {
    459             stuff->dflt_class = KbdFeedbackClass;
    460             if (stuff->dflt_kbd_fb == NULL)
    461                 stuff->dflt_kbd_fb = &stuff->info[i];
    462         }
    463         else if (devli->led_class == LedFeedbackClass) {
    464             if (stuff->dflt_class == XkbXINone)
    465                 stuff->dflt_class = LedFeedbackClass;
    466             if (stuff->dflt_led_fb == NULL)
    467                 stuff->dflt_led_fb = &stuff->info[i];
    468         }
    469     }
    470     return;
    471 }
    472 
    473 static void
    474 _FreeLedStuff(SetLedStuff * stuff)
    475 {
    476     if (stuff->num_info > 0)
    477         _XkbFree(stuff->info);
    478     bzero(stuff, sizeof(SetLedStuff));
    479     return;
    480 }
    481 
    482 static int
    483 _XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli)
    484 {
    485     register int i, size;
    486     register unsigned bit, namesNeeded, mapsNeeded;
    487 
    488     size = SIZEOF(xkbDeviceLedsWireDesc);
    489     namesNeeded = mapsNeeded = 0;
    490     if (changed & XkbXI_IndicatorNamesMask)
    491         namesNeeded = devli->names_present;
    492     if (changed & XkbXI_IndicatorMapsMask)
    493         mapsNeeded = devli->maps_present;
    494     if ((namesNeeded) || (mapsNeeded)) {
    495         for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    496             if (namesNeeded & bit)
    497                 size += 4;      /* atoms are 4 bytes on the wire */
    498             if (mapsNeeded & bit)
    499                 size += SIZEOF(xkbIndicatorMapWireDesc);
    500         }
    501     }
    502     return size;
    503 }
    504 
    505 static Bool
    506 _SizeMatches(SetLedStuff *stuff,
    507              XkbDeviceLedChangesPtr changes,
    508              int *sz_rtrn,
    509              int *nleds_rtrn)
    510 {
    511     int i, nMatch, class, id;
    512     LedInfoStuff *linfo;
    513     Bool match;
    514 
    515     nMatch = 0;
    516     class = changes->led_class;
    517     id = changes->led_id;
    518     if (class == XkbDfltXIClass)
    519         class = stuff->dflt_class;
    520     for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
    521         XkbDeviceLedInfoPtr devli;
    522         LedInfoStuff *dflt;
    523 
    524         devli = linfo->devli;
    525         match = ((class == devli->led_class) || (class == XkbAllXIClasses));
    526         if (devli->led_class == KbdFeedbackClass)
    527             dflt = stuff->dflt_kbd_fb;
    528         else
    529             dflt = stuff->dflt_led_fb;
    530         match = (match && (id == devli->led_id)) ||
    531             (id == XkbAllXIIds) ||
    532             ((id == XkbDfltXIId) && (linfo == dflt));
    533         if (match) {
    534             if (!linfo->used) {
    535                 *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli);
    536                 *nleds_rtrn += 1;
    537                 linfo->used = True;
    538                 if ((class != XkbAllXIClasses) && (id != XkbAllXIIds))
    539                     return True;
    540             }
    541             nMatch++;
    542             linfo->used = True;
    543         }
    544     }
    545     return (nMatch > 0);
    546 }
    547 
    548 /***====================================================================***/
    549 
    550 
    551 static Status
    552 _XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi,
    553                       XkbDeviceChangesPtr changes,
    554                       SetLedStuff *stuff,
    555                       int *sz_rtrn,
    556                       int *num_leds_rtrn)
    557 {
    558     *sz_rtrn = 0;
    559     if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) {
    560         if (!XkbXI_LegalDevBtn
    561             (devi, (changes->first_btn + changes->num_btns - 1)))
    562             return BadMatch;
    563         *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc);
    564     }
    565     else {
    566         changes->changed &= ~XkbXI_ButtonActionsMask;
    567         changes->first_btn = changes->num_btns = 0;
    568     }
    569     if ((changes->changed & XkbXI_IndicatorsMask) &&
    570         XkbLegalXILedClass(changes->leds.led_class)) {
    571         XkbDeviceLedChangesPtr leds;
    572 
    573         for (leds = &changes->leds; leds != NULL; leds = leds->next) {
    574             if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn))
    575                 return BadMatch;
    576         }
    577     }
    578     else {
    579         changes->changed &= ~XkbXI_IndicatorsMask;
    580         *num_leds_rtrn = 0;
    581     }
    582     return Success;
    583 }
    584 
    585 static char *
    586 _XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli)
    587 {
    588     register int i;
    589     register unsigned bit, namesNeeded, mapsNeeded;
    590     xkbDeviceLedsWireDesc *lwire;
    591 
    592     namesNeeded = mapsNeeded = 0;
    593     if (changed & XkbXI_IndicatorNamesMask)
    594         namesNeeded = devli->names_present;
    595     if (changed & XkbXI_IndicatorMapsMask)
    596         mapsNeeded = devli->maps_present;
    597 
    598     lwire = (xkbDeviceLedsWireDesc *) wire;
    599     lwire->ledClass = devli->led_class;
    600     lwire->ledID = devli->led_id;
    601     lwire->namesPresent = namesNeeded;
    602     lwire->mapsPresent = mapsNeeded;
    603     lwire->physIndicators = devli->phys_indicators;
    604     lwire->state = devli->state;
    605     wire = (char *) &lwire[1];
    606     if (namesNeeded) {
    607         CARD32 *awire = (CARD32 *) wire;
    608 
    609         for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    610             if (namesNeeded & bit) {
    611                 *awire = (CARD32) devli->names[i];
    612                 awire++;
    613             }
    614         }
    615         wire = (char *) awire;
    616     }
    617     if (mapsNeeded) {
    618         xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire;
    619 
    620         for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    621             if (mapsNeeded & bit) {
    622                 XkbIndicatorMapPtr map = &devli->maps[i];
    623 
    624                 mwire->flags = map->flags;
    625                 mwire->whichGroups = map->which_groups;
    626                 mwire->groups = map->groups;
    627                 mwire->whichMods = map->which_mods;
    628                 mwire->mods = map->mods.mask;
    629                 mwire->realMods = map->mods.real_mods;
    630                 mwire->virtualMods = map->mods.vmods;
    631                 mwire->ctrls = map->ctrls;
    632                 mwire++;
    633             }
    634         }
    635         wire = (char *) mwire;
    636     }
    637     return wire;
    638 }
    639 
    640 
    641 static int
    642 _XkbWriteSetDeviceInfo(char *wire,
    643                        XkbDeviceChangesPtr changes,
    644                        SetLedStuff *stuff,
    645                        XkbDeviceInfoPtr devi)
    646 {
    647     char *start = wire;
    648 
    649     if (changes->changed & XkbXI_ButtonActionsMask) {
    650         int size = changes->num_btns * SIZEOF(xkbActionWireDesc);
    651 
    652         memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], (size_t) size);
    653         wire += size;
    654     }
    655     if (changes->changed & XkbXI_IndicatorsMask) {
    656         register int i;
    657         register LedInfoStuff *linfo;
    658 
    659         for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
    660             if (linfo->used) {
    661                 register char *new_wire;
    662 
    663                 new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli);
    664                 if (!new_wire)
    665                     return wire - start;
    666                 wire = new_wire;
    667             }
    668         }
    669     }
    670     return wire - start;
    671 }
    672 
    673 Bool
    674 XkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi)
    675 {
    676     register xkbSetDeviceInfoReq *req;
    677     Status ok = 0;
    678     int size, nLeds;
    679     XkbInfoPtr xkbi;
    680     XkbDeviceChangesRec changes;
    681     SetLedStuff lstuff;
    682 
    683     if ((dpy->flags & XlibDisplayNoXkb) ||
    684         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    685         return False;
    686     if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) ||
    687         ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) ||
    688         ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi))))
    689         return False;
    690 
    691     bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
    692     changes.changed = which;
    693     changes.first_btn = 0;
    694     changes.num_btns = devi->num_btns;
    695     changes.leds.led_class = XkbAllXIClasses;
    696     changes.leds.led_id = XkbAllXIIds;
    697     changes.leds.defined = 0;
    698     size = nLeds = 0;
    699     _InitLedStuff(&lstuff, changes.changed, devi);
    700     if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) !=
    701         Success)
    702         return False;
    703     LockDisplay(dpy);
    704     xkbi = dpy->xkb_info;
    705     GetReq(kbSetDeviceInfo, req);
    706     req->length += size / 4;
    707     req->reqType = xkbi->codes->major_opcode;
    708     req->xkbReqType = X_kbSetDeviceInfo;
    709     req->deviceSpec = devi->device_spec;
    710     req->firstBtn = changes.first_btn;
    711     req->nBtns = changes.num_btns;
    712     req->change = changes.changed;
    713     req->nDeviceLedFBs = nLeds;
    714     if (size > 0) {
    715         char *wire;
    716 
    717         BufAlloc(char *, wire, size);
    718         ok = (wire != NULL) &&
    719             (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
    720     }
    721     UnlockDisplay(dpy);
    722     SyncHandle();
    723     _FreeLedStuff(&lstuff);
    724     /* 12/11/95 (ef) -- XXX!! should clear changes here */
    725     return ok;
    726 }
    727 
    728 Bool
    729 XkbChangeDeviceInfo(Display *dpy,
    730                     XkbDeviceInfoPtr devi,
    731                     XkbDeviceChangesPtr changes)
    732 {
    733     register xkbSetDeviceInfoReq *req;
    734     Status ok = 0;
    735     int size, nLeds;
    736     XkbInfoPtr xkbi;
    737     SetLedStuff lstuff;
    738 
    739     if ((dpy->flags & XlibDisplayNoXkb) ||
    740         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    741         return False;
    742     if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) ||
    743         ((changes->changed & XkbXI_ButtonActionsMask) &&
    744          (!XkbXI_DevHasBtnActs(devi))) ||
    745         ((changes->changed & XkbXI_IndicatorsMask) &&
    746          (!XkbXI_DevHasLeds(devi))))
    747         return False;
    748 
    749     size = nLeds = 0;
    750     _InitLedStuff(&lstuff, changes->changed, devi);
    751     if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success)
    752         return False;
    753     LockDisplay(dpy);
    754     xkbi = dpy->xkb_info;
    755     GetReq(kbSetDeviceInfo, req);
    756     req->length += size / 4;
    757     req->reqType = xkbi->codes->major_opcode;
    758     req->xkbReqType = X_kbSetDeviceInfo;
    759     req->deviceSpec = devi->device_spec;
    760     req->firstBtn = changes->first_btn;
    761     req->nBtns = changes->num_btns;
    762     req->change = changes->changed;
    763     req->nDeviceLedFBs = nLeds;
    764     if (size > 0) {
    765         char *wire;
    766 
    767         BufAlloc(char *, wire, size);
    768         ok = (wire != NULL) &&
    769             (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size);
    770     }
    771     UnlockDisplay(dpy);
    772     SyncHandle();
    773     _FreeLedStuff(&lstuff);
    774     /* 12/11/95 (ef) -- XXX!! should clear changes here */
    775     return ok;
    776 }
    777 
    778 Bool
    779 XkbSetDeviceLedInfo(Display *dpy,
    780                     XkbDeviceInfoPtr devi,
    781                     unsigned ledClass,
    782                     unsigned ledID,
    783                     unsigned which)
    784 {
    785     return False;
    786 }
    787 
    788 Bool
    789 XkbSetDeviceButtonActions(Display *dpy,
    790                           XkbDeviceInfoPtr devi,
    791                           unsigned int first,
    792                           unsigned int nBtns)
    793 {
    794     register xkbSetDeviceInfoReq *req;
    795     Status ok = 0;
    796     int size, nLeds;
    797     XkbInfoPtr xkbi;
    798     XkbDeviceChangesRec changes;
    799     SetLedStuff lstuff;
    800 
    801     if ((dpy->flags & XlibDisplayNoXkb) ||
    802         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    803         return False;
    804     if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) ||
    805         (first + nBtns > devi->num_btns))
    806         return False;
    807     if (nBtns == 0)
    808         return True;
    809 
    810     bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
    811     changes.changed = XkbXI_ButtonActionsMask;
    812     changes.first_btn = first;
    813     changes.num_btns = nBtns;
    814     changes.leds.led_class = XkbXINone;
    815     changes.leds.led_id = XkbXINone;
    816     changes.leds.defined = 0;
    817     size = nLeds = 0;
    818     if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success)
    819         return False;
    820     LockDisplay(dpy);
    821     xkbi = dpy->xkb_info;
    822     GetReq(kbSetDeviceInfo, req);
    823     req->length += size / 4;
    824     req->reqType = xkbi->codes->major_opcode;
    825     req->xkbReqType = X_kbSetDeviceInfo;
    826     req->deviceSpec = devi->device_spec;
    827     req->firstBtn = changes.first_btn;
    828     req->nBtns = changes.num_btns;
    829     req->change = changes.changed;
    830     req->nDeviceLedFBs = nLeds;
    831     if (size > 0) {
    832         char *wire;
    833 
    834         BufAlloc(char *, wire, size);
    835         ok = (wire != NULL) &&
    836             (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
    837     }
    838     UnlockDisplay(dpy);
    839     SyncHandle();
    840     return ok;
    841 }
    842