XKBExtDev.c revision 9c019ec5
1/************************************************************
2Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <stdio.h>
31#define	NEED_MAP_READERS
32#include "Xlibint.h"
33#include <X11/extensions/XKBproto.h>
34#include "XKBlibint.h"
35#include <X11/extensions/XI.h>
36
37/***====================================================================***/
38
39void
40XkbNoteDeviceChanges(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
112static 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
173static 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)
192            >= devi->num_btns)
193            goto BAILOUT;
194        act = &devi->btn_acts[rep->firstBtnWanted];
195        bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction)));
196    }
197
198    _XkbFree(devi->name);
199    if (!_XkbGetReadBufferCountedString(&buf, &devi->name))
200        goto BAILOUT;
201    if (rep->nBtnsRtrn > 0) {
202        int size;
203
204        if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn)
205            >= devi->num_btns)
206            goto BAILOUT;
207        act = &devi->btn_acts[rep->firstBtnRtrn];
208        size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc);
209        if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size))
210            goto BAILOUT;
211    }
212    if (rep->nDeviceLedFBs > 0) {
213        register int i;
214
215        for (i = 0; i < rep->nDeviceLedFBs; i++) {
216            if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi))
217                != Success)
218                return tmp;
219        }
220    }
221    tmp = _XkbFreeReadBuffer(&buf);
222    if (tmp)
223        fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp);
224    if (tmp || buf.error)
225        return BadLength;
226    return Success;
227 BAILOUT:
228    _XkbFreeReadBuffer(&buf);
229    return BadLength;
230}
231
232XkbDeviceInfoPtr
233XkbGetDeviceInfo(Display *dpy,
234                 unsigned which,
235                 unsigned deviceSpec,
236                 unsigned class,
237                 unsigned id)
238{
239    register xkbGetDeviceInfoReq *req;
240    xkbGetDeviceInfoReply rep;
241    Status status;
242    XkbDeviceInfoPtr devi;
243
244    if ((dpy->flags & XlibDisplayNoXkb) ||
245        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
246        return NULL;
247    LockDisplay(dpy);
248    GetReq(kbGetDeviceInfo, req);
249    req->reqType = dpy->xkb_info->codes->major_opcode;
250    req->xkbReqType = X_kbGetDeviceInfo;
251    req->deviceSpec = deviceSpec;
252    req->wanted = which;
253    req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0);
254    req->firstBtn = req->nBtns = 0;
255    req->ledClass = class;
256    req->ledID = id;
257    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
258        UnlockDisplay(dpy);
259        SyncHandle();
260        return NULL;
261    }
262    devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs);
263    if (devi) {
264        devi->supported = rep.supported;
265        devi->unsupported = rep.unsupported;
266        devi->type = rep.devType;
267        devi->has_own_state = rep.hasOwnState;
268        devi->dflt_kbd_fb = rep.dfltKbdFB;
269        devi->dflt_led_fb = rep.dfltLedFB;
270        status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
271        if (status != Success) {
272            XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True);
273            devi = NULL;
274        }
275    }
276    UnlockDisplay(dpy);
277    SyncHandle();
278    return devi;
279}
280
281Status
282XkbGetDeviceInfoChanges(Display *dpy,
283                        XkbDeviceInfoPtr devi,
284                        XkbDeviceChangesPtr changes)
285{
286    register xkbGetDeviceInfoReq *req;
287    xkbGetDeviceInfoReply rep;
288    Status status;
289
290    if ((dpy->flags & XlibDisplayNoXkb) ||
291        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
292        return BadMatch;
293    if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0)
294        return Success;
295    changes->changed &= ~XkbXI_AllDeviceFeaturesMask;
296    status = Success;
297    LockDisplay(dpy);
298    while ((changes->changed) && (status == Success)) {
299        GetReq(kbGetDeviceInfo, req);
300        req->reqType = dpy->xkb_info->codes->major_opcode;
301        req->xkbReqType = X_kbGetDeviceInfo;
302        req->deviceSpec = devi->device_spec;
303        req->wanted = changes->changed;
304        req->allBtns = False;
305        if (changes->changed & XkbXI_ButtonActionsMask) {
306            req->firstBtn = changes->first_btn;
307            req->nBtns = changes->num_btns;
308            changes->changed &= ~XkbXI_ButtonActionsMask;
309        }
310        else
311            req->firstBtn = req->nBtns = 0;
312        if (changes->changed & XkbXI_IndicatorsMask) {
313            req->ledClass = changes->leds.led_class;
314            req->ledID = changes->leds.led_id;
315            if (changes->leds.next == NULL)
316                changes->changed &= ~XkbXI_IndicatorsMask;
317            else {
318                XkbDeviceLedChangesPtr next;
319
320                next = changes->leds.next;
321                changes->leds = *next;
322                _XkbFree(next);
323            }
324        }
325        else {
326            req->ledClass = XkbDfltXIClass;
327            req->ledID = XkbDfltXIId;
328        }
329        if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
330            status = BadLength;
331            break;
332        }
333        devi->supported |= rep.supported;
334        devi->unsupported |= rep.unsupported;
335        devi->type = rep.devType;
336        status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
337    }
338    UnlockDisplay(dpy);
339    SyncHandle();
340    return status;
341}
342
343Status
344XkbGetDeviceButtonActions(Display *dpy,
345                          XkbDeviceInfoPtr devi,
346                          Bool all,
347                          unsigned int first,
348                          unsigned int num)
349{
350    register xkbGetDeviceInfoReq *req;
351    xkbGetDeviceInfoReply rep;
352    Status status;
353
354    if ((dpy->flags & XlibDisplayNoXkb) ||
355        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
356        return BadMatch;
357    if (!devi)
358        return BadValue;
359    LockDisplay(dpy);
360    GetReq(kbGetDeviceInfo, req);
361    req->reqType = dpy->xkb_info->codes->major_opcode;
362    req->xkbReqType = X_kbGetDeviceInfo;
363    req->deviceSpec = devi->device_spec;
364    req->wanted = XkbXI_ButtonActionsMask;
365    req->allBtns = all;
366    req->firstBtn = first;
367    req->nBtns = num;
368    req->ledClass = XkbDfltXIClass;
369    req->ledID = XkbDfltXIId;
370    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
371        UnlockDisplay(dpy);
372        SyncHandle();
373        return BadLength;
374    }
375    devi->type = rep.devType;
376    devi->supported = rep.supported;
377    devi->unsupported = rep.unsupported;
378    status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
379    UnlockDisplay(dpy);
380    SyncHandle();
381    return status;
382}
383
384Status
385XkbGetDeviceLedInfo(Display *dpy,
386                    XkbDeviceInfoPtr devi,
387                    unsigned int ledClass,
388                    unsigned int ledId,
389                    unsigned int which)
390{
391    register xkbGetDeviceInfoReq *req;
392    xkbGetDeviceInfoReply rep;
393    Status status;
394
395    if ((dpy->flags & XlibDisplayNoXkb) ||
396        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
397        return BadMatch;
398    if (((which & XkbXI_IndicatorsMask) == 0) ||
399        (which & (~XkbXI_IndicatorsMask)))
400        return BadMatch;
401    if (!devi)
402        return BadValue;
403    LockDisplay(dpy);
404    GetReq(kbGetDeviceInfo, req);
405    req->reqType = dpy->xkb_info->codes->major_opcode;
406    req->xkbReqType = X_kbGetDeviceInfo;
407    req->deviceSpec = devi->device_spec;
408    req->wanted = which;
409    req->allBtns = False;
410    req->firstBtn = req->nBtns = 0;
411    req->ledClass = ledClass;
412    req->ledID = ledId;
413    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
414        UnlockDisplay(dpy);
415        SyncHandle();
416        return BadLength;
417    }
418    devi->type = rep.devType;
419    devi->supported = rep.supported;
420    devi->unsupported = rep.unsupported;
421    status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
422    UnlockDisplay(dpy);
423    SyncHandle();
424    return status;
425}
426
427/***====================================================================***/
428
429typedef struct _LedInfoStuff {
430    Bool used;
431    XkbDeviceLedInfoPtr devli;
432} LedInfoStuff;
433
434typedef struct _SetLedStuff {
435    unsigned wanted;
436    int num_info;
437    int dflt_class;
438    LedInfoStuff *dflt_kbd_fb;
439    LedInfoStuff *dflt_led_fb;
440    LedInfoStuff *info;
441} SetLedStuff;
442
443static void
444_InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi)
445{
446    int i;
447    register XkbDeviceLedInfoPtr devli;
448
449    bzero(stuff, sizeof(SetLedStuff));
450    stuff->wanted = wanted;
451    stuff->dflt_class = XkbXINone;
452    if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0))
453        return;
454    stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff);
455    if (!stuff->info)
456        return;
457    stuff->num_info = devi->num_leds;
458    for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) {
459        stuff->info[i].devli = devli;
460        if (devli->led_class == KbdFeedbackClass) {
461            stuff->dflt_class = KbdFeedbackClass;
462            if (stuff->dflt_kbd_fb == NULL)
463                stuff->dflt_kbd_fb = &stuff->info[i];
464        }
465        else if (devli->led_class == LedFeedbackClass) {
466            if (stuff->dflt_class == XkbXINone)
467                stuff->dflt_class = LedFeedbackClass;
468            if (stuff->dflt_led_fb == NULL)
469                stuff->dflt_led_fb = &stuff->info[i];
470        }
471    }
472    return;
473}
474
475static void
476_FreeLedStuff(SetLedStuff * stuff)
477{
478    if (stuff->num_info > 0)
479        _XkbFree(stuff->info);
480    bzero(stuff, sizeof(SetLedStuff));
481    return;
482}
483
484static int
485_XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli)
486{
487    register int i, size;
488    register unsigned bit, namesNeeded, mapsNeeded;
489
490    size = SIZEOF(xkbDeviceLedsWireDesc);
491    namesNeeded = mapsNeeded = 0;
492    if (changed & XkbXI_IndicatorNamesMask)
493        namesNeeded = devli->names_present;
494    if (changed & XkbXI_IndicatorMapsMask)
495        mapsNeeded = devli->maps_present;
496    if ((namesNeeded) || (mapsNeeded)) {
497        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
498            if (namesNeeded & bit)
499                size += 4;      /* atoms are 4 bytes on the wire */
500            if (mapsNeeded & bit)
501                size += SIZEOF(xkbIndicatorMapWireDesc);
502        }
503    }
504    return size;
505}
506
507static Bool
508_SizeMatches(SetLedStuff *stuff,
509             XkbDeviceLedChangesPtr changes,
510             int *sz_rtrn,
511             int *nleds_rtrn)
512{
513    int i, nMatch, class, id;
514    LedInfoStuff *linfo;
515    Bool match;
516
517    nMatch = 0;
518    class = changes->led_class;
519    id = changes->led_id;
520    if (class == XkbDfltXIClass)
521        class = stuff->dflt_class;
522    for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
523        XkbDeviceLedInfoPtr devli;
524        LedInfoStuff *dflt;
525
526        devli = linfo->devli;
527        match = ((class == devli->led_class) || (class == XkbAllXIClasses));
528        if (devli->led_class == KbdFeedbackClass)
529            dflt = stuff->dflt_kbd_fb;
530        else
531            dflt = stuff->dflt_led_fb;
532        match = (match && (id == devli->led_id)) ||
533            (id == XkbAllXIIds) ||
534            ((id == XkbDfltXIId) && (linfo == dflt));
535        if (match) {
536            if (!linfo->used) {
537                *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli);
538                *nleds_rtrn += 1;
539                linfo->used = True;
540                if ((class != XkbAllXIClasses) && (id != XkbAllXIIds))
541                    return True;
542            }
543            nMatch++;
544            linfo->used = True;
545        }
546    }
547    return (nMatch > 0);
548}
549
550/***====================================================================***/
551
552
553static Status
554_XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi,
555                      XkbDeviceChangesPtr changes,
556                      SetLedStuff *stuff,
557                      int *sz_rtrn,
558                      int *num_leds_rtrn)
559{
560    *sz_rtrn = 0;
561    if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) {
562        if (!XkbXI_LegalDevBtn
563            (devi, (changes->first_btn + changes->num_btns - 1)))
564            return BadMatch;
565        *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc);
566    }
567    else {
568        changes->changed &= ~XkbXI_ButtonActionsMask;
569        changes->first_btn = changes->num_btns = 0;
570    }
571    if ((changes->changed & XkbXI_IndicatorsMask) &&
572        XkbLegalXILedClass(changes->leds.led_class)) {
573        XkbDeviceLedChangesPtr leds;
574
575        for (leds = &changes->leds; leds != NULL; leds = leds->next) {
576            if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn))
577                return BadMatch;
578        }
579    }
580    else {
581        changes->changed &= ~XkbXI_IndicatorsMask;
582        *num_leds_rtrn = 0;
583    }
584    return Success;
585}
586
587static char *
588_XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli)
589{
590    register int i;
591    register unsigned bit, namesNeeded, mapsNeeded;
592    xkbDeviceLedsWireDesc *lwire;
593
594    namesNeeded = mapsNeeded = 0;
595    if (changed & XkbXI_IndicatorNamesMask)
596        namesNeeded = devli->names_present;
597    if (changed & XkbXI_IndicatorMapsMask)
598        mapsNeeded = devli->maps_present;
599
600    lwire = (xkbDeviceLedsWireDesc *) wire;
601    lwire->ledClass = devli->led_class;
602    lwire->ledID = devli->led_id;
603    lwire->namesPresent = namesNeeded;
604    lwire->mapsPresent = mapsNeeded;
605    lwire->physIndicators = devli->phys_indicators;
606    lwire->state = devli->state;
607    wire = (char *) &lwire[1];
608    if (namesNeeded) {
609        CARD32 *awire = (CARD32 *) wire;
610
611        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
612            if (namesNeeded & bit) {
613                *awire = (CARD32) devli->names[i];
614                awire++;
615            }
616        }
617        wire = (char *) awire;
618    }
619    if (mapsNeeded) {
620        xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire;
621
622        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
623            if (mapsNeeded & bit) {
624                XkbIndicatorMapPtr map = &devli->maps[i];
625
626                mwire->flags = map->flags;
627                mwire->whichGroups = map->which_groups;
628                mwire->groups = map->groups;
629                mwire->whichMods = map->which_mods;
630                mwire->mods = map->mods.mask;
631                mwire->realMods = map->mods.real_mods;
632                mwire->virtualMods = map->mods.vmods;
633                mwire->ctrls = map->ctrls;
634                mwire++;
635            }
636        }
637        wire = (char *) mwire;
638    }
639    return wire;
640}
641
642
643static int
644_XkbWriteSetDeviceInfo(char *wire,
645                       XkbDeviceChangesPtr changes,
646                       SetLedStuff *stuff,
647                       XkbDeviceInfoPtr devi)
648{
649    char *start = wire;
650
651    if (changes->changed & XkbXI_ButtonActionsMask) {
652        int size = changes->num_btns * SIZEOF(xkbActionWireDesc);
653
654        memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], (size_t) size);
655        wire += size;
656    }
657    if (changes->changed & XkbXI_IndicatorsMask) {
658        register int i;
659        register LedInfoStuff *linfo;
660
661        for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
662            if (linfo->used) {
663                register char *new_wire;
664
665                new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli);
666                if (!new_wire)
667                    return wire - start;
668                wire = new_wire;
669            }
670        }
671    }
672    return wire - start;
673}
674
675Bool
676XkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi)
677{
678    register xkbSetDeviceInfoReq *req;
679    Status ok = 0;
680    int size, nLeds;
681    XkbInfoPtr xkbi;
682    XkbDeviceChangesRec changes;
683    SetLedStuff lstuff;
684
685    if ((dpy->flags & XlibDisplayNoXkb) ||
686        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
687        return False;
688    if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) ||
689        ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) ||
690        ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi))))
691        return False;
692
693    bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
694    changes.changed = which;
695    changes.first_btn = 0;
696    changes.num_btns = devi->num_btns;
697    changes.leds.led_class = XkbAllXIClasses;
698    changes.leds.led_id = XkbAllXIIds;
699    changes.leds.defined = 0;
700    size = nLeds = 0;
701    _InitLedStuff(&lstuff, changes.changed, devi);
702    if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) !=
703        Success)
704        return False;
705    LockDisplay(dpy);
706    xkbi = dpy->xkb_info;
707    GetReq(kbSetDeviceInfo, req);
708    req->length += size / 4;
709    req->reqType = xkbi->codes->major_opcode;
710    req->xkbReqType = X_kbSetDeviceInfo;
711    req->deviceSpec = devi->device_spec;
712    req->firstBtn = changes.first_btn;
713    req->nBtns = changes.num_btns;
714    req->change = changes.changed;
715    req->nDeviceLedFBs = nLeds;
716    if (size > 0) {
717        char *wire;
718
719        BufAlloc(char *, wire, size);
720        ok = (wire != NULL) &&
721            (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
722    }
723    UnlockDisplay(dpy);
724    SyncHandle();
725    _FreeLedStuff(&lstuff);
726    /* 12/11/95 (ef) -- XXX!! should clear changes here */
727    return ok;
728}
729
730Bool
731XkbChangeDeviceInfo(Display *dpy,
732                    XkbDeviceInfoPtr devi,
733                    XkbDeviceChangesPtr changes)
734{
735    register xkbSetDeviceInfoReq *req;
736    Status ok = 0;
737    int size, nLeds;
738    XkbInfoPtr xkbi;
739    SetLedStuff lstuff;
740
741    if ((dpy->flags & XlibDisplayNoXkb) ||
742        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
743        return False;
744    if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) ||
745        ((changes->changed & XkbXI_ButtonActionsMask) &&
746         (!XkbXI_DevHasBtnActs(devi))) ||
747        ((changes->changed & XkbXI_IndicatorsMask) &&
748         (!XkbXI_DevHasLeds(devi))))
749        return False;
750
751    size = nLeds = 0;
752    _InitLedStuff(&lstuff, changes->changed, devi);
753    if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success)
754        return False;
755    LockDisplay(dpy);
756    xkbi = dpy->xkb_info;
757    GetReq(kbSetDeviceInfo, req);
758    req->length += size / 4;
759    req->reqType = xkbi->codes->major_opcode;
760    req->xkbReqType = X_kbSetDeviceInfo;
761    req->deviceSpec = devi->device_spec;
762    req->firstBtn = changes->first_btn;
763    req->nBtns = changes->num_btns;
764    req->change = changes->changed;
765    req->nDeviceLedFBs = nLeds;
766    if (size > 0) {
767        char *wire;
768
769        BufAlloc(char *, wire, size);
770        ok = (wire != NULL) &&
771            (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size);
772    }
773    UnlockDisplay(dpy);
774    SyncHandle();
775    _FreeLedStuff(&lstuff);
776    /* 12/11/95 (ef) -- XXX!! should clear changes here */
777    return ok;
778}
779
780Bool
781XkbSetDeviceLedInfo(Display *dpy,
782                    XkbDeviceInfoPtr devi,
783                    unsigned ledClass,
784                    unsigned ledID,
785                    unsigned which)
786{
787    return False;
788}
789
790Bool
791XkbSetDeviceButtonActions(Display *dpy,
792                          XkbDeviceInfoPtr devi,
793                          unsigned int first,
794                          unsigned int nBtns)
795{
796    register xkbSetDeviceInfoReq *req;
797    Status ok = 0;
798    int size, nLeds;
799    XkbInfoPtr xkbi;
800    XkbDeviceChangesRec changes;
801    SetLedStuff lstuff;
802
803    if ((dpy->flags & XlibDisplayNoXkb) ||
804        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
805        return False;
806    if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) ||
807        (first + nBtns > devi->num_btns))
808        return False;
809    if (nBtns == 0)
810        return True;
811
812    bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
813    changes.changed = XkbXI_ButtonActionsMask;
814    changes.first_btn = first;
815    changes.num_btns = nBtns;
816    changes.leds.led_class = XkbXINone;
817    changes.leds.led_id = XkbXINone;
818    changes.leds.defined = 0;
819    size = nLeds = 0;
820    if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success)
821        return False;
822    LockDisplay(dpy);
823    xkbi = dpy->xkb_info;
824    GetReq(kbSetDeviceInfo, req);
825    req->length += size / 4;
826    req->reqType = xkbi->codes->major_opcode;
827    req->xkbReqType = X_kbSetDeviceInfo;
828    req->deviceSpec = devi->device_spec;
829    req->firstBtn = changes.first_btn;
830    req->nBtns = changes.num_btns;
831    req->change = changes.changed;
832    req->nDeviceLedFBs = nLeds;
833    if (size > 0) {
834        char *wire;
835
836        BufAlloc(char *, wire, size);
837        ok = (wire != NULL) &&
838            (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
839    }
840    UnlockDisplay(dpy);
841    SyncHandle();
842    return ok;
843}
844