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