chgfctl.c revision 4642e01f
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#define	 NEED_EVENTS	/* for inputstr.h    */
54#define	 NEED_REPLIES
55#ifdef HAVE_DIX_CONFIG_H
56#include <dix-config.h>
57#endif
58
59#include "inputstr.h"	/* DeviceIntPtr      */
60#include <X11/extensions/XI.h>
61#include <X11/extensions/XIproto.h>	/* control constants */
62
63#include "exglobals.h"
64
65#include "chgfctl.h"
66
67#define DO_ALL    (-1)
68
69/***********************************************************************
70 *
71 * This procedure changes the control attributes for an extension device,
72 * for clients on machines with a different byte ordering than the server.
73 *
74 */
75
76int
77SProcXChangeFeedbackControl(ClientPtr client)
78{
79    char n;
80
81    REQUEST(xChangeFeedbackControlReq);
82    swaps(&stuff->length, n);
83    REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq);
84    swapl(&stuff->mask, n);
85    return (ProcXChangeFeedbackControl(client));
86}
87
88/******************************************************************************
89 *
90 * This procedure changes KbdFeedbackClass data.
91 *
92 */
93
94static int
95ChangeKbdFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
96		  KbdFeedbackPtr k, xKbdFeedbackCtl * f)
97{
98    char n;
99    KeybdCtrl kctrl;
100    int t;
101    int key = DO_ALL;
102
103    if (client->swapped) {
104	swaps(&f->length, n);
105	swaps(&f->pitch, n);
106	swaps(&f->duration, n);
107	swapl(&f->led_mask, n);
108	swapl(&f->led_values, n);
109    }
110
111    kctrl = k->ctrl;
112    if (mask & DvKeyClickPercent) {
113	t = f->click;
114	if (t == -1)
115	    t = defaultKeyboardControl.click;
116	else if (t < 0 || t > 100) {
117	    client->errorValue = t;
118	    return BadValue;
119	}
120	kctrl.click = t;
121    }
122
123    if (mask & DvPercent) {
124	t = f->percent;
125	if (t == -1)
126	    t = defaultKeyboardControl.bell;
127	else if (t < 0 || t > 100) {
128	    client->errorValue = t;
129	    return BadValue;
130	}
131	kctrl.bell = t;
132    }
133
134    if (mask & DvPitch) {
135	t = f->pitch;
136	if (t == -1)
137	    t = defaultKeyboardControl.bell_pitch;
138	else if (t < 0) {
139	    client->errorValue = t;
140	    return BadValue;
141	}
142	kctrl.bell_pitch = t;
143    }
144
145    if (mask & DvDuration) {
146	t = f->duration;
147	if (t == -1)
148	    t = defaultKeyboardControl.bell_duration;
149	else if (t < 0) {
150	    client->errorValue = t;
151	    return BadValue;
152	}
153	kctrl.bell_duration = t;
154    }
155
156    if (mask & DvLed) {
157	kctrl.leds &= ~(f->led_mask);
158	kctrl.leds |= (f->led_mask & f->led_values);
159    }
160
161    if (mask & DvKey) {
162	key = (KeyCode) f->key;
163	if (key < 8 || key > 255) {
164	    client->errorValue = key;
165	    return BadValue;
166	}
167	if (!(mask & DvAutoRepeatMode))
168	    return BadMatch;
169    }
170
171    if (mask & DvAutoRepeatMode) {
172	int inx = (key >> 3);
173	int kmask = (1 << (key & 7));
174
175	t = (CARD8) f->auto_repeat_mode;
176	if (t == AutoRepeatModeOff) {
177	    if (key == DO_ALL)
178		kctrl.autoRepeat = FALSE;
179	    else
180		kctrl.autoRepeats[inx] &= ~kmask;
181	} else if (t == AutoRepeatModeOn) {
182	    if (key == DO_ALL)
183		kctrl.autoRepeat = TRUE;
184	    else
185		kctrl.autoRepeats[inx] |= kmask;
186	} else if (t == AutoRepeatModeDefault) {
187	    if (key == DO_ALL)
188		kctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
189	    else
190		kctrl.autoRepeats[inx] &= ~kmask;
191	    kctrl.autoRepeats[inx] =
192		(kctrl.autoRepeats[inx] & ~kmask) |
193		(defaultKeyboardControl.autoRepeats[inx] & kmask);
194	} else {
195	    client->errorValue = t;
196	    return BadValue;
197	}
198    }
199
200    k->ctrl = kctrl;
201    (*k->CtrlProc) (dev, &k->ctrl);
202    return Success;
203}
204
205/******************************************************************************
206 *
207 * This procedure changes PtrFeedbackClass data.
208 *
209 */
210
211static int
212ChangePtrFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
213		  PtrFeedbackPtr p, xPtrFeedbackCtl * f)
214{
215    char n;
216    PtrCtrl pctrl;	/* might get BadValue part way through */
217
218    if (client->swapped) {
219	swaps(&f->length, n);
220	swaps(&f->num, n);
221	swaps(&f->denom, n);
222	swaps(&f->thresh, n);
223    }
224
225    pctrl = p->ctrl;
226    if (mask & DvAccelNum) {
227	int accelNum;
228
229	accelNum = f->num;
230	if (accelNum == -1)
231	    pctrl.num = defaultPointerControl.num;
232	else if (accelNum < 0) {
233	    client->errorValue = accelNum;
234	    return BadValue;
235	} else
236	    pctrl.num = accelNum;
237    }
238
239    if (mask & DvAccelDenom) {
240	int accelDenom;
241
242	accelDenom = f->denom;
243	if (accelDenom == -1)
244	    pctrl.den = defaultPointerControl.den;
245	else if (accelDenom <= 0) {
246	    client->errorValue = accelDenom;
247	    return BadValue;
248	} else
249	    pctrl.den = accelDenom;
250    }
251
252    if (mask & DvThreshold) {
253	int threshold;
254
255	threshold = f->thresh;
256	if (threshold == -1)
257	    pctrl.threshold = defaultPointerControl.threshold;
258	else if (threshold < 0) {
259	    client->errorValue = threshold;
260	    return BadValue;
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    char n;
282
283    if (client->swapped) {
284	swaps(&f->length, n);
285	swapl(&f->int_to_display, n);
286    }
287
288    i->ctrl.integer_displayed = f->int_to_display;
289    (*i->CtrlProc) (dev, &i->ctrl);
290    return Success;
291}
292
293/******************************************************************************
294 *
295 * This procedure changes StringFeedbackClass data.
296 *
297 */
298
299static int
300ChangeStringFeedback(ClientPtr client, DeviceIntPtr dev,
301		     long unsigned int mask, StringFeedbackPtr s,
302		     xStringFeedbackCtl * f)
303{
304    char n;
305    int i, j;
306    KeySym *syms, *sup_syms;
307
308    syms = (KeySym *) (f + 1);
309    if (client->swapped) {
310	swaps(&f->length, n);	/* swapped num_keysyms in calling proc */
311	SwapLongs((CARD32 *) syms, f->num_keysyms);
312    }
313
314    if (f->num_keysyms > s->ctrl.max_symbols)
315	return BadValue;
316
317    sup_syms = s->ctrl.symbols_supported;
318    for (i = 0; i < f->num_keysyms; i++) {
319	for (j = 0; j < s->ctrl.num_symbols_supported; j++)
320	    if (*(syms + i) == *(sup_syms + j))
321		break;
322	if (j == s->ctrl.num_symbols_supported)
323	    return BadMatch;
324    }
325
326    s->ctrl.num_symbols_displayed = f->num_keysyms;
327    for (i = 0; i < f->num_keysyms; i++)
328	*(s->ctrl.symbols_displayed + i) = *(syms + i);
329    (*s->CtrlProc) (dev, &s->ctrl);
330    return Success;
331}
332
333/******************************************************************************
334 *
335 * This procedure changes BellFeedbackClass data.
336 *
337 */
338
339static int
340ChangeBellFeedback(ClientPtr client, DeviceIntPtr dev,
341		   long unsigned int mask, BellFeedbackPtr b,
342		   xBellFeedbackCtl * f)
343{
344    char n;
345    int t;
346    BellCtrl bctrl;	/* might get BadValue part way through */
347
348    if (client->swapped) {
349	swaps(&f->length, n);
350	swaps(&f->pitch, n);
351	swaps(&f->duration, n);
352    }
353
354    bctrl = b->ctrl;
355    if (mask & DvPercent) {
356	t = f->percent;
357	if (t == -1)
358	    t = defaultKeyboardControl.bell;
359	else if (t < 0 || t > 100) {
360	    client->errorValue = t;
361	    return BadValue;
362	}
363	bctrl.percent = t;
364    }
365
366    if (mask & DvPitch) {
367	t = f->pitch;
368	if (t == -1)
369	    t = defaultKeyboardControl.bell_pitch;
370	else if (t < 0) {
371	    client->errorValue = t;
372	    return BadValue;
373	}
374	bctrl.pitch = t;
375    }
376
377    if (mask & DvDuration) {
378	t = f->duration;
379	if (t == -1)
380	    t = defaultKeyboardControl.bell_duration;
381	else if (t < 0) {
382	    client->errorValue = t;
383	    return BadValue;
384	}
385	bctrl.duration = t;
386    }
387    b->ctrl = bctrl;
388    (*b->CtrlProc) (dev, &b->ctrl);
389    return Success;
390}
391
392/******************************************************************************
393 *
394 * This procedure changes LedFeedbackClass data.
395 *
396 */
397
398static int
399ChangeLedFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask,
400		  LedFeedbackPtr l, xLedFeedbackCtl * f)
401{
402    char n;
403    LedCtrl lctrl;	/* might get BadValue part way through */
404
405    if (client->swapped) {
406	swaps(&f->length, n);
407	swapl(&f->led_values, n);
408	swapl(&f->led_mask, n);
409    }
410
411    f->led_mask &= l->ctrl.led_mask;	/* set only supported leds */
412    f->led_values &= l->ctrl.led_mask;	/* set only supported leds */
413    if (mask & DvLed) {
414	lctrl.led_mask = f->led_mask;
415	lctrl.led_values = f->led_values;
416	(*l->CtrlProc) (dev, &lctrl);
417	l->ctrl.led_values &= ~(f->led_mask);	/* zero changed leds */
418	l->ctrl.led_values |= (f->led_mask & f->led_values);	/* OR in set leds */
419    }
420
421    return Success;
422}
423
424/***********************************************************************
425 *
426 * Change the control attributes.
427 *
428 */
429
430int
431ProcXChangeFeedbackControl(ClientPtr client)
432{
433    unsigned len;
434    DeviceIntPtr dev;
435    KbdFeedbackPtr k;
436    PtrFeedbackPtr p;
437    IntegerFeedbackPtr i;
438    StringFeedbackPtr s;
439    BellFeedbackPtr b;
440    LedFeedbackPtr l;
441    int rc;
442
443    REQUEST(xChangeFeedbackControlReq);
444    REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq);
445
446    len = stuff->length - (sizeof(xChangeFeedbackControlReq) >> 2);
447    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
448    if (rc != Success)
449	return rc;
450
451    switch (stuff->feedbackid) {
452    case KbdFeedbackClass:
453	if (len != (sizeof(xKbdFeedbackCtl) >> 2))
454	    return BadLength;
455
456	for (k = dev->kbdfeed; k; k = k->next)
457	    if (k->ctrl.id == ((xKbdFeedbackCtl *) & stuff[1])->id)
458		return ChangeKbdFeedback(client, dev, stuff->mask, k,
459					 (xKbdFeedbackCtl *) & stuff[1]);
460	break;
461    case PtrFeedbackClass:
462	if (len != (sizeof(xPtrFeedbackCtl) >> 2))
463	    return BadLength;
464
465	for (p = dev->ptrfeed; p; p = p->next)
466	    if (p->ctrl.id == ((xPtrFeedbackCtl *) & stuff[1])->id)
467		return ChangePtrFeedback(client, dev, stuff->mask, p,
468					 (xPtrFeedbackCtl *) & stuff[1]);
469	break;
470    case StringFeedbackClass:
471    {
472	char n;
473	xStringFeedbackCtl *f = ((xStringFeedbackCtl *) & stuff[1]);
474
475	if (client->swapped) {
476	    swaps(&f->num_keysyms, n);
477	}
478	if (len != ((sizeof(xStringFeedbackCtl) >> 2) + 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 != (sizeof(xIntegerFeedbackCtl) >> 2))
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 *)&stuff[1]);
495	break;
496    case LedFeedbackClass:
497	if (len != (sizeof(xLedFeedbackCtl) >> 2))
498	    return BadLength;
499
500	for (l = dev->leds; l; l = l->next)
501	    if (l->ctrl.id == ((xLedFeedbackCtl *) & stuff[1])->id)
502		return ChangeLedFeedback(client, dev, stuff->mask, l,
503					 (xLedFeedbackCtl *) & stuff[1]);
504	break;
505    case BellFeedbackClass:
506	if (len != (sizeof(xBellFeedbackCtl) >> 2))
507	    return BadLength;
508
509	for (b = dev->bell; b; b = b->next)
510	    if (b->ctrl.id == ((xBellFeedbackCtl *) & stuff[1])->id)
511		return ChangeBellFeedback(client, dev, stuff->mask, b,
512					  (xBellFeedbackCtl *) & stuff[1]);
513	break;
514    default:
515	break;
516    }
517
518    return BadMatch;
519}
520
521