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