chgfctl.c revision f7df2e56
1/************************************************************
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27			All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
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
74int
75SProcXChangeFeedbackControl(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
90static int
91ChangeKbdFeedback(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
209static int
210ChangePtrFeedback(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
276static int
277ChangeIntegerFeedback(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
297static int
298ChangeStringFeedback(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
336static int
337ChangeBellFeedback(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
394static int
395ChangeLedFeedback(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
425int
426ProcXChangeFeedbackControl(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 = ((xStringFeedbackCtl *) &stuff[1]);
468
469        if (client->swapped) {
470            if (len < bytes_to_int32(sizeof(xStringFeedbackCtl)))
471                return BadLength;
472            swaps(&f->num_keysyms);
473        }
474        if (len !=
475            (bytes_to_int32(sizeof(xStringFeedbackCtl)) + f->num_keysyms))
476            return BadLength;
477
478        for (s = dev->stringfeed; s; s = s->next)
479            if (s->ctrl.id == ((xStringFeedbackCtl *) &stuff[1])->id)
480                return ChangeStringFeedback(client, dev, stuff->mask, s,
481                                            (xStringFeedbackCtl *) &stuff[1]);
482        break;
483    }
484    case IntegerFeedbackClass:
485        if (len != bytes_to_int32(sizeof(xIntegerFeedbackCtl)))
486            return BadLength;
487
488        for (i = dev->intfeed; i; i = i->next)
489            if (i->ctrl.id == ((xIntegerFeedbackCtl *) &stuff[1])->id)
490                return ChangeIntegerFeedback(client, dev, stuff->mask, i,
491                                             (xIntegerFeedbackCtl *) &
492                                             stuff[1]);
493        break;
494    case LedFeedbackClass:
495        if (len != bytes_to_int32(sizeof(xLedFeedbackCtl)))
496            return BadLength;
497
498        for (l = dev->leds; l; l = l->next)
499            if (l->ctrl.id == ((xLedFeedbackCtl *) &stuff[1])->id)
500                return ChangeLedFeedback(client, dev, stuff->mask, l,
501                                         (xLedFeedbackCtl *) &stuff[1]);
502        break;
503    case BellFeedbackClass:
504        if (len != bytes_to_int32(sizeof(xBellFeedbackCtl)))
505            return BadLength;
506
507        for (b = dev->bell; b; b = b->next)
508            if (b->ctrl.id == ((xBellFeedbackCtl *) &stuff[1])->id)
509                return ChangeBellFeedback(client, dev, stuff->mask, b,
510                                          (xBellFeedbackCtl *) &stuff[1]);
511        break;
512    default:
513        break;
514    }
515
516    return BadMatch;
517}
518