1 /************************************************************
2 
3 Copyright 1989, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24 
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26 
27 			All Rights Reserved
28 
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36 
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44 
45 ********************************************************/
46 
47 /********************************************************************
48  *
49  *  Change feedback control attributes for an extension device.
50  *
51  */
52 
53 #ifdef HAVE_DIX_CONFIG_H
54 #include <dix-config.h>
55 #endif
56 
57 #include "inputstr.h"           /* DeviceIntPtr      */
58 #include <X11/extensions/XI.h>
59 #include <X11/extensions/XIproto.h>     /* control constants */
60 
61 #include "exglobals.h"
62 
63 #include "chgfctl.h"
64 
65 #define DO_ALL    (-1)
66 
67 /***********************************************************************
68  *
69  * This procedure changes the control attributes for an extension device,
70  * for clients on machines with a different byte ordering than the server.
71  *
72  */
73 
74 int _X_COLD
SProcXChangeFeedbackControl(ClientPtr client)75 SProcXChangeFeedbackControl(ClientPtr client)
76 {
77     REQUEST(xChangeFeedbackControlReq);
78     swaps(&stuff->length);
79     REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq);
80     swapl(&stuff->mask);
81     return (ProcXChangeFeedbackControl(client));
82 }
83 
84 /******************************************************************************
85  *
86  * This procedure changes KbdFeedbackClass data.
87  *
88  */
89 
90 static int
ChangeKbdFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,KbdFeedbackPtr k,xKbdFeedbackCtl * f)91 ChangeKbdFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
92                   KbdFeedbackPtr k, xKbdFeedbackCtl * f)
93 {
94     KeybdCtrl kctrl;
95     int t;
96     int key = DO_ALL;
97 
98     if (client->swapped) {
99         swaps(&f->length);
100         swaps(&f->pitch);
101         swaps(&f->duration);
102         swapl(&f->led_mask);
103         swapl(&f->led_values);
104     }
105 
106     kctrl = k->ctrl;
107     if (mask & DvKeyClickPercent) {
108         t = f->click;
109         if (t == -1)
110             t = defaultKeyboardControl.click;
111         else if (t < 0 || t > 100) {
112             client->errorValue = t;
113             return BadValue;
114         }
115         kctrl.click = t;
116     }
117 
118     if (mask & DvPercent) {
119         t = f->percent;
120         if (t == -1)
121             t = defaultKeyboardControl.bell;
122         else if (t < 0 || t > 100) {
123             client->errorValue = t;
124             return BadValue;
125         }
126         kctrl.bell = t;
127     }
128 
129     if (mask & DvPitch) {
130         t = f->pitch;
131         if (t == -1)
132             t = defaultKeyboardControl.bell_pitch;
133         else if (t < 0) {
134             client->errorValue = t;
135             return BadValue;
136         }
137         kctrl.bell_pitch = t;
138     }
139 
140     if (mask & DvDuration) {
141         t = f->duration;
142         if (t == -1)
143             t = defaultKeyboardControl.bell_duration;
144         else if (t < 0) {
145             client->errorValue = t;
146             return BadValue;
147         }
148         kctrl.bell_duration = t;
149     }
150 
151     if (mask & DvLed) {
152         kctrl.leds &= ~(f->led_mask);
153         kctrl.leds |= (f->led_mask & f->led_values);
154     }
155 
156     if (mask & DvKey) {
157         key = (KeyCode) f->key;
158         if (key < 8 || key > 255) {
159             client->errorValue = key;
160             return BadValue;
161         }
162         if (!(mask & DvAutoRepeatMode))
163             return BadMatch;
164     }
165 
166     if (mask & DvAutoRepeatMode) {
167         int inx = (key >> 3);
168         int kmask = (1 << (key & 7));
169 
170         t = (CARD8) f->auto_repeat_mode;
171         if (t == AutoRepeatModeOff) {
172             if (key == DO_ALL)
173                 kctrl.autoRepeat = FALSE;
174             else
175                 kctrl.autoRepeats[inx] &= ~kmask;
176         }
177         else if (t == AutoRepeatModeOn) {
178             if (key == DO_ALL)
179                 kctrl.autoRepeat = TRUE;
180             else
181                 kctrl.autoRepeats[inx] |= kmask;
182         }
183         else if (t == AutoRepeatModeDefault) {
184             if (key == DO_ALL)
185                 kctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
186             else
187                 kctrl.autoRepeats[inx] &= ~kmask;
188             kctrl.autoRepeats[inx] =
189                 (kctrl.autoRepeats[inx] & ~kmask) |
190                 (defaultKeyboardControl.autoRepeats[inx] & kmask);
191         }
192         else {
193             client->errorValue = t;
194             return BadValue;
195         }
196     }
197 
198     k->ctrl = kctrl;
199     (*k->CtrlProc) (dev, &k->ctrl);
200     return Success;
201 }
202 
203 /******************************************************************************
204  *
205  * This procedure changes PtrFeedbackClass data.
206  *
207  */
208 
209 static int
ChangePtrFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,PtrFeedbackPtr p,xPtrFeedbackCtl * f)210 ChangePtrFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
211                   PtrFeedbackPtr p, xPtrFeedbackCtl * f)
212 {
213     PtrCtrl pctrl;              /* might get BadValue part way through */
214 
215     if (client->swapped) {
216         swaps(&f->length);
217         swaps(&f->num);
218         swaps(&f->denom);
219         swaps(&f->thresh);
220     }
221 
222     pctrl = p->ctrl;
223     if (mask & DvAccelNum) {
224         int accelNum;
225 
226         accelNum = f->num;
227         if (accelNum == -1)
228             pctrl.num = defaultPointerControl.num;
229         else if (accelNum < 0) {
230             client->errorValue = accelNum;
231             return BadValue;
232         }
233         else
234             pctrl.num = accelNum;
235     }
236 
237     if (mask & DvAccelDenom) {
238         int accelDenom;
239 
240         accelDenom = f->denom;
241         if (accelDenom == -1)
242             pctrl.den = defaultPointerControl.den;
243         else if (accelDenom <= 0) {
244             client->errorValue = accelDenom;
245             return BadValue;
246         }
247         else
248             pctrl.den = accelDenom;
249     }
250 
251     if (mask & DvThreshold) {
252         int threshold;
253 
254         threshold = f->thresh;
255         if (threshold == -1)
256             pctrl.threshold = defaultPointerControl.threshold;
257         else if (threshold < 0) {
258             client->errorValue = threshold;
259             return BadValue;
260         }
261         else
262             pctrl.threshold = threshold;
263     }
264 
265     p->ctrl = pctrl;
266     (*p->CtrlProc) (dev, &p->ctrl);
267     return Success;
268 }
269 
270 /******************************************************************************
271  *
272  * This procedure changes IntegerFeedbackClass data.
273  *
274  */
275 
276 static int
ChangeIntegerFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,IntegerFeedbackPtr i,xIntegerFeedbackCtl * f)277 ChangeIntegerFeedback(ClientPtr client, DeviceIntPtr dev,
278                       long unsigned int mask, IntegerFeedbackPtr i,
279                       xIntegerFeedbackCtl * f)
280 {
281     if (client->swapped) {
282         swaps(&f->length);
283         swapl(&f->int_to_display);
284     }
285 
286     i->ctrl.integer_displayed = f->int_to_display;
287     (*i->CtrlProc) (dev, &i->ctrl);
288     return Success;
289 }
290 
291 /******************************************************************************
292  *
293  * This procedure changes StringFeedbackClass data.
294  *
295  */
296 
297 static int
ChangeStringFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,StringFeedbackPtr s,xStringFeedbackCtl * f)298 ChangeStringFeedback(ClientPtr client, DeviceIntPtr dev,
299                      long unsigned int mask, StringFeedbackPtr s,
300                      xStringFeedbackCtl * f)
301 {
302     int i, j;
303     KeySym *syms, *sup_syms;
304 
305     syms = (KeySym *) (f + 1);
306     if (client->swapped) {
307         swaps(&f->length);      /* swapped num_keysyms in calling proc */
308         SwapLongs((CARD32 *) syms, f->num_keysyms);
309     }
310 
311     if (f->num_keysyms > s->ctrl.max_symbols)
312         return BadValue;
313 
314     sup_syms = s->ctrl.symbols_supported;
315     for (i = 0; i < f->num_keysyms; i++) {
316         for (j = 0; j < s->ctrl.num_symbols_supported; j++)
317             if (*(syms + i) == *(sup_syms + j))
318                 break;
319         if (j == s->ctrl.num_symbols_supported)
320             return BadMatch;
321     }
322 
323     s->ctrl.num_symbols_displayed = f->num_keysyms;
324     for (i = 0; i < f->num_keysyms; i++)
325         *(s->ctrl.symbols_displayed + i) = *(syms + i);
326     (*s->CtrlProc) (dev, &s->ctrl);
327     return Success;
328 }
329 
330 /******************************************************************************
331  *
332  * This procedure changes BellFeedbackClass data.
333  *
334  */
335 
336 static int
ChangeBellFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,BellFeedbackPtr b,xBellFeedbackCtl * f)337 ChangeBellFeedback(ClientPtr client, DeviceIntPtr dev,
338                    long unsigned int mask, BellFeedbackPtr b,
339                    xBellFeedbackCtl * f)
340 {
341     int t;
342     BellCtrl bctrl;             /* might get BadValue part way through */
343 
344     if (client->swapped) {
345         swaps(&f->length);
346         swaps(&f->pitch);
347         swaps(&f->duration);
348     }
349 
350     bctrl = b->ctrl;
351     if (mask & DvPercent) {
352         t = f->percent;
353         if (t == -1)
354             t = defaultKeyboardControl.bell;
355         else if (t < 0 || t > 100) {
356             client->errorValue = t;
357             return BadValue;
358         }
359         bctrl.percent = t;
360     }
361 
362     if (mask & DvPitch) {
363         t = f->pitch;
364         if (t == -1)
365             t = defaultKeyboardControl.bell_pitch;
366         else if (t < 0) {
367             client->errorValue = t;
368             return BadValue;
369         }
370         bctrl.pitch = t;
371     }
372 
373     if (mask & DvDuration) {
374         t = f->duration;
375         if (t == -1)
376             t = defaultKeyboardControl.bell_duration;
377         else if (t < 0) {
378             client->errorValue = t;
379             return BadValue;
380         }
381         bctrl.duration = t;
382     }
383     b->ctrl = bctrl;
384     (*b->CtrlProc) (dev, &b->ctrl);
385     return Success;
386 }
387 
388 /******************************************************************************
389  *
390  * This procedure changes LedFeedbackClass data.
391  *
392  */
393 
394 static int
ChangeLedFeedback(ClientPtr client,DeviceIntPtr dev,long unsigned int mask,LedFeedbackPtr l,xLedFeedbackCtl * f)395 ChangeLedFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
396                   LedFeedbackPtr l, xLedFeedbackCtl * f)
397 {
398     LedCtrl lctrl;              /* might get BadValue part way through */
399 
400     if (client->swapped) {
401         swaps(&f->length);
402         swapl(&f->led_values);
403         swapl(&f->led_mask);
404     }
405 
406     f->led_mask &= l->ctrl.led_mask;    /* set only supported leds */
407     f->led_values &= l->ctrl.led_mask;  /* set only supported leds */
408     if (mask & DvLed) {
409         lctrl.led_mask = f->led_mask;
410         lctrl.led_values = f->led_values;
411         (*l->CtrlProc) (dev, &lctrl);
412         l->ctrl.led_values &= ~(f->led_mask);   /* zero changed leds */
413         l->ctrl.led_values |= (f->led_mask & f->led_values);    /* OR in set leds */
414     }
415 
416     return Success;
417 }
418 
419 /***********************************************************************
420  *
421  * Change the control attributes.
422  *
423  */
424 
425 int
ProcXChangeFeedbackControl(ClientPtr client)426 ProcXChangeFeedbackControl(ClientPtr client)
427 {
428     unsigned len;
429     DeviceIntPtr dev;
430     KbdFeedbackPtr k;
431     PtrFeedbackPtr p;
432     IntegerFeedbackPtr i;
433     StringFeedbackPtr s;
434     BellFeedbackPtr b;
435     LedFeedbackPtr l;
436     int rc;
437 
438     REQUEST(xChangeFeedbackControlReq);
439     REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq);
440 
441     len = stuff->length - bytes_to_int32(sizeof(xChangeFeedbackControlReq));
442     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
443     if (rc != Success)
444         return rc;
445 
446     switch (stuff->feedbackid) {
447     case KbdFeedbackClass:
448         if (len != bytes_to_int32(sizeof(xKbdFeedbackCtl)))
449             return BadLength;
450 
451         for (k = dev->kbdfeed; k; k = k->next)
452             if (k->ctrl.id == ((xKbdFeedbackCtl *) &stuff[1])->id)
453                 return ChangeKbdFeedback(client, dev, stuff->mask, k,
454                                          (xKbdFeedbackCtl *) &stuff[1]);
455         break;
456     case PtrFeedbackClass:
457         if (len != bytes_to_int32(sizeof(xPtrFeedbackCtl)))
458             return BadLength;
459 
460         for (p = dev->ptrfeed; p; p = p->next)
461             if (p->ctrl.id == ((xPtrFeedbackCtl *) &stuff[1])->id)
462                 return ChangePtrFeedback(client, dev, stuff->mask, p,
463                                          (xPtrFeedbackCtl *) &stuff[1]);
464         break;
465     case StringFeedbackClass:
466     {
467         xStringFeedbackCtl *f;
468 
469         REQUEST_AT_LEAST_EXTRA_SIZE(xChangeFeedbackControlReq,
470                                     sizeof(xStringFeedbackCtl));
471         f = ((xStringFeedbackCtl *) &stuff[1]);
472         if (client->swapped) {
473             if (len < bytes_to_int32(sizeof(xStringFeedbackCtl)))
474                 return BadLength;
475             swaps(&f->num_keysyms);
476         }
477         if (len !=
478             (bytes_to_int32(sizeof(xStringFeedbackCtl)) + f->num_keysyms))
479             return BadLength;
480 
481         for (s = dev->stringfeed; s; s = s->next)
482             if (s->ctrl.id == ((xStringFeedbackCtl *) &stuff[1])->id)
483                 return ChangeStringFeedback(client, dev, stuff->mask, s,
484                                             (xStringFeedbackCtl *) &stuff[1]);
485         break;
486     }
487     case IntegerFeedbackClass:
488         if (len != bytes_to_int32(sizeof(xIntegerFeedbackCtl)))
489             return BadLength;
490 
491         for (i = dev->intfeed; i; i = i->next)
492             if (i->ctrl.id == ((xIntegerFeedbackCtl *) &stuff[1])->id)
493                 return ChangeIntegerFeedback(client, dev, stuff->mask, i,
494                                              (xIntegerFeedbackCtl *) &
495                                              stuff[1]);
496         break;
497     case LedFeedbackClass:
498         if (len != bytes_to_int32(sizeof(xLedFeedbackCtl)))
499             return BadLength;
500 
501         for (l = dev->leds; l; l = l->next)
502             if (l->ctrl.id == ((xLedFeedbackCtl *) &stuff[1])->id)
503                 return ChangeLedFeedback(client, dev, stuff->mask, l,
504                                          (xLedFeedbackCtl *) &stuff[1]);
505         break;
506     case BellFeedbackClass:
507         if (len != bytes_to_int32(sizeof(xBellFeedbackCtl)))
508             return BadLength;
509 
510         for (b = dev->bell; b; b = b->next)
511             if (b->ctrl.id == ((xBellFeedbackCtl *) &stuff[1])->id)
512                 return ChangeBellFeedback(client, dev, stuff->mask, b,
513                                           (xBellFeedbackCtl *) &stuff[1]);
514         break;
515     default:
516         break;
517     }
518 
519     return BadMatch;
520 }
521