xset.c revision feee4651
1/*
2
3Copyright 1985, 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
25*/
26/* Modified by Stephen so keyboard rate is set using XKB extensions */
27
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
32#ifdef HAVE_X11_EXTENSIONS_DPMS_H
33# define DPMSExtension
34#endif
35
36#ifdef HAVE_X11_EXTENSIONS_MITMISC_H
37# define MITMISC
38#endif
39
40#ifdef HAVE_X11_XKBLIB_H
41# define XKB
42#endif
43
44#if defined(HAVE_X11_EXTENSIONS_XF86MISC_H) && defined(HAVE_X11_EXTENSIONS_XF86MSCSTR_H)
45# define XF86MISC
46#endif
47
48#if defined(HAVE_X11_EXTENSIONS_FONTCACHE_H) && defined(HAVE_X11_EXTENSIONS_FONTCACHEP_H)
49# define FONTCACHE
50#endif
51
52#include <stdio.h>
53#include <ctype.h>
54#include <stdarg.h>
55#include <stdlib.h>
56#ifdef HAVE_USLEEP
57#include <unistd.h>
58#endif
59#include <X11/Xos.h>
60#include <X11/Xfuncs.h>
61#include <X11/Xlib.h>
62#include <X11/keysym.h>
63#include <X11/Xproto.h>
64#include <X11/Xutil.h>
65#include <X11/Xmu/Error.h>
66#ifdef MITMISC
67# include <X11/extensions/MITMisc.h>
68#endif
69#ifdef DPMSExtension
70# include <X11/extensions/dpms.h>
71#endif /* DPMSExtension */
72
73#ifdef XF86MISC
74# include <X11/extensions/xf86misc.h>
75# include <X11/extensions/xf86mscstr.h>
76#endif
77#ifdef XKB
78# include <X11/XKBlib.h>
79#endif
80#ifdef FONTCACHE
81# include <X11/extensions/fontcache.h>
82# include <X11/extensions/fontcacheP.h>
83
84static Status set_font_cache(Display *, long, long, long);
85static void query_cache_status(Display *dpy);
86#endif
87
88#define ON 1
89#define OFF 0
90
91#define SERVER_DEFAULT (-1)
92#define DONT_CHANGE -2
93
94#define DEFAULT_ON (-50)
95#define DEFAULT_TIMEOUT (-600)
96
97#define ALL -1
98#define TIMEOUT 1
99#define INTERVAL 2
100#define PREFER_BLANK 3
101#define ALLOW_EXP 4
102
103#ifdef XF86MISC
104# define KBDDELAY_DEFAULT 500
105# define KBDRATE_DEFAULT 30
106#endif
107#ifdef XKB
108# define XKBDDELAY_DEFAULT 660
109# define XKBDRATE_DEFAULT (1000/40)
110#endif
111
112#define	nextarg(i, argv) \
113	argv[i]; \
114	if (i >= argc) \
115		break; \
116
117static char *progName;
118
119static int error_status = 0;
120
121static int is_number(const char *arg, int maximum);
122static void set_click(Display *dpy, int percent);
123static void set_bell_vol(Display *dpy, int percent);
124static void set_bell_pitch(Display *dpy, int pitch);
125static void set_bell_dur(Display *dpy, int duration);
126static void set_font_path(Display *dpy, const char *path, int special,
127			  int before, int after);
128static void set_led(Display *dpy, int led, int led_mode);
129static void xkbset_led(Display *dpy, const char *led, int led_mode);
130static void set_mouse(Display *dpy, int acc_num, int acc_denom, int threshold);
131static void set_saver(Display *dpy, int mask, int value);
132static void set_repeat(Display *dpy, int key, int auto_repeat_mode);
133static void set_pixels(Display *dpy, unsigned long *pixels, caddr_t *colors,
134		       int numpixels);
135static void set_lock(Display *dpy, Bool onoff);
136static const char *on_or_off(int val, int onval, const char *onstr,
137                             int offval, const char *offstr,
138                             char buf[], size_t bufsize);
139static void query(Display *dpy);
140static void usage(const char *fmt, ...) _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2);
141static void error(const char *message) _X_NORETURN;
142static int local_xerror(Display *dpy, XErrorEvent *rep);
143
144#ifdef XF86MISC
145static void set_repeatrate(Display *dpy, int delay, int rate);
146#endif
147#ifdef XKB
148static void xkbset_repeatrate(Display *dpy, int delay, int rate);
149#endif
150
151int
152main(int argc, char *argv[])
153{
154    const char *arg;
155    register int i;
156    int percent;
157    int acc_num, acc_denom, threshold;
158
159#ifdef DPMSExtension
160    CARD16 standby_timeout, suspend_timeout, off_timeout;
161#endif
162    int key, auto_repeat_mode;
163    XKeyboardControl values;
164
165#define MAX_PIXEL_COUNT 512
166    unsigned long pixels[MAX_PIXEL_COUNT];
167    caddr_t colors[MAX_PIXEL_COUNT];
168    int numpixels = 0;
169    char *disp = NULL;
170    Display *dpy;
171    Bool hasargs = False;
172
173    int miscpresent = 0;
174    int xkbpresent = 0;
175
176#ifdef XKB
177    int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion;
178    int xkbopcode, xkbevent, xkberror;
179#else
180#endif
181#ifdef FONTCACHE
182    long himark, lowmark, balance;
183#endif
184
185    progName = argv[0];
186    for (i = 1; i < argc; i++) {
187	arg = argv[i];
188	if (strcmp(arg, "-display") == 0 || strcmp(arg, "-d") == 0) {
189	    if (++i >= argc)
190		usage("missing argument to -display");
191	    disp = argv[i];
192	} else if (strcmp(arg, "-version") == 0) {
193	    puts(PACKAGE_STRING);
194	    exit(EXIT_SUCCESS);
195	} else {
196	    hasargs = True;
197	}
198    }
199    if (!hasargs) {
200	usage(NULL);		       /* replace with window interface */
201    }
202
203    dpy = XOpenDisplay(disp);    /*  Open display and check for success */
204    if (dpy == NULL) {
205	fprintf(stderr, "%s:  unable to open display \"%s\"\n",
206		argv[0], XDisplayName(disp));
207	exit(EXIT_FAILURE);
208    }
209    XSetErrorHandler(local_xerror);
210    for (i = 1; i < argc;) {
211	arg = argv[i++];
212	if (strcmp(arg, "-display") == 0 || strcmp(arg, "-d") == 0) {
213	    ++i;		       		/* already dealt with */
214	    continue;
215	} else if (*arg == '-' && *(arg + 1) == 'c') {	/* Does arg start
216							   with "-c"? */
217	    set_click(dpy, 0);	       		/* If so, turn click off */
218	} else if (*arg == 'c') {      		/* Well, does it start
219						   with "c", then? */
220	    percent = SERVER_DEFAULT;  		/* Default click volume. */
221	    if (i >= argc) {
222		set_click(dpy, percent);	/* set click to default */
223		break;
224	    }
225	    arg = nextarg(i, argv);
226	    if (strcmp(arg, "on") == 0) {	/* Let click be default. */
227		percent = DEFAULT_ON;
228		i++;
229	    } else if (strcmp(arg, "off") == 0) {
230		percent = 0;	       		/* Turn it off.          */
231		i++;
232	    } else if (is_number(arg, 100)) {
233		percent = atoi(arg);		/* Set to spec. volume */
234		i++;
235	    }
236	    set_click(dpy, percent);
237	} else if (strcmp(arg, "-b") == 0) {
238	    set_bell_vol(dpy, 0);      		/* Then turn off bell.    */
239	} else if (strcmp(arg, "b") == 0) {
240	    percent = SERVER_DEFAULT;  		/* Set bell to default. */
241	    if (i >= argc) {
242		set_bell_vol(dpy, percent);	/* set bell to default */
243		set_bell_pitch(dpy, percent);	/* set pitch to default */
244		set_bell_dur(dpy, percent);	/* set duration to default */
245		break;
246	    }
247	    arg = nextarg(i, argv);
248	    if (strcmp(arg, "on") == 0) {	/* Let it stay that way.  */
249		set_bell_vol(dpy, DEFAULT_ON);	/* set bell on */
250		set_bell_pitch(dpy, percent);	/* set pitch to default */
251		set_bell_dur(dpy, percent);	/* set duration to default */
252		i++;
253	    } else if (strcmp(arg, "off") == 0) {
254		percent = 0;	       		/* Turn the bell off.     */
255		set_bell_vol(dpy, percent);
256		i++;
257	    } else if (is_number(arg, 100)) {	/* If volume is given:    */
258		percent = atoi(arg);   	       	/* set bell appropriately. */
259		set_bell_vol(dpy, percent);
260		i++;
261		arg = nextarg(i, argv);
262
263		if (is_number(arg, 32767)) {	/* If pitch is given:     */
264		    set_bell_pitch(dpy, atoi(arg));	/* set the bell.  */
265		    i++;
266
267		    arg = nextarg(i, argv);
268		    if (is_number(arg, 32767)) { /* If duration is given:  */
269			set_bell_dur(dpy, atoi(arg));	/*  set the bell.  */
270			i++;
271		    }
272		}
273	    } else
274		set_bell_vol(dpy, percent);	/* set bell to default */
275	}
276#ifdef MITMISC
277	else if (strcmp(arg, "bc") == 0) {
278	    int dummy;
279
280	    if (XMITMiscQueryExtension(dpy, &dummy, &dummy))
281		XMITMiscSetBugMode(dpy, True);
282	    else
283		fprintf(stderr,
284			"server does not have extension for bc option\n");
285	} else if (strcmp(arg, "-bc") == 0) {
286	    int dummy;
287
288	    if (XMITMiscQueryExtension(dpy, &dummy, &dummy))
289		XMITMiscSetBugMode(dpy, False);
290	    else
291		fprintf(stderr,
292			"server does not have extension for -bc option\n");
293	}
294#endif
295#ifdef FONTCACHE
296	else if (strcmp(arg, "fc") == 0) {
297	    int dummy;
298	    FontCacheSettings cs;
299
300	    if (FontCacheQueryExtension(dpy, &dummy, &dummy)) {
301		FontCacheGetCacheSettings(dpy, &cs);
302		himark = cs.himark / 1024;
303		lowmark = cs.lowmark / 1024;
304		balance = cs.balance;
305		if (i >= argc) {
306		    /* Set to server's values, and clear all cache
307		       in side effect */
308		    set_font_cache(dpy, himark, lowmark, balance);
309		    break;
310		}
311		arg = nextarg(i, argv);
312		if (is_number(arg, 32767)) {	/* If hi-mark is given: */
313		    himark = atoi(arg);
314		    i++;
315		    if (himark <= 0) {
316			usage("hi-mark must be greater than 0");
317		    }
318		    if (i >= argc) {
319			lowmark = (himark * 70) / 100;
320			set_font_cache(dpy, himark, lowmark, balance);
321			break;
322		    }
323		    arg = nextarg(i, argv);
324		    if (is_number(arg, 32767)) { /* If low-mark is given: */
325			lowmark = atoi(arg);
326			i++;
327			if (lowmark <= 0) {
328			    usage("low-mark must be greater than 0");
329			}
330			if (himark <= lowmark) {
331			    usage("hi-mark must be greater than low-mark");
332			}
333			if (i >= argc) {
334			    set_font_cache(dpy, himark, lowmark, balance);
335			    break;
336			}
337			arg = nextarg(i, argv);
338			if (is_number(arg, 90)) {
339			    balance = atoi(arg);
340			    i++;
341			    if (!(10 <= balance && balance <= 90)) {
342				usage("balance must be 10 to 90\n");
343			    }
344			    set_font_cache(dpy, himark, lowmark, balance);
345			}
346		    }
347		} else if (strcmp(arg, "s") == 0
348		    || strcmp(arg, "status") == 0) {
349		    /* display cache status */
350		    query_cache_status(dpy);
351		}
352	    } else {
353		fprintf(stderr,
354			"server does not have extension for fc option\n");
355	    }
356	}
357#endif
358	else if (strcmp(arg, "fp") == 0) {	/* set font path */
359	    if (i >= argc) {
360		arg = "default";
361	    } else {
362		arg = nextarg(i, argv);
363	    }
364	    set_font_path(dpy, arg, 1, 0, 0);	/* special argument */
365	    i++;
366	} else if (strcmp(arg, "fp=") == 0) {	/* unconditionally set */
367	    if (i >= argc) {
368		usage("missing fp= argument");
369	    } else {
370		arg = nextarg(i, argv);
371	    }
372	    set_font_path(dpy, arg, 0, 0, 0);	/* not special, set */
373	    i++;
374	} else if (strcmp(arg, "+fp") == 0) {	/* set font path */
375	    if (i >= argc)
376		usage("missing +fp argument");
377	    arg = nextarg(i, argv);
378	    set_font_path(dpy, arg, 0, 1, 0);	/* not special, prepend */
379	    i++;
380	} else if (strcmp(arg, "fp+") == 0) {	/* set font path */
381	    if (i >= argc)
382		usage("missing fp+ argument");
383	    arg = nextarg(i, argv);
384	    set_font_path(dpy, arg, 0, 0, 1);	/* not special, append */
385	    i++;
386	} else if (strcmp(arg, "-fp") == 0) {	/* set font path */
387	    if (i >= argc)
388		usage("missing -fp argument");
389	    arg = nextarg(i, argv);
390	    set_font_path(dpy, arg, 0, -1, 0);	/* not special, preremove */
391	    i++;
392	} else if (strcmp(arg, "fp-") == 0) {	/* set font path */
393	    if (i >= argc)
394		usage("missing fp- argument");
395	    arg = nextarg(i, argv);
396	    set_font_path(dpy, arg, 0, 0, -1);	/* not special, postremove */
397	    i++;
398	} else if (strcmp(arg, "-led") == 0) {	/* Turn off one or all LEDs */
399	    values.led_mode = OFF;
400	    values.led = ALL;	       		/* None specified */
401	    if (i >= argc) {
402		set_led(dpy, values.led, values.led_mode);
403		break;
404	    }
405	    arg = nextarg(i, argv);
406	    if (strcmp(arg, "named") == 0) {
407		if (++i >= argc) {
408		    usage("missing argument to led named");
409		} else {
410		    arg = nextarg(i, argv);
411		    xkbset_led(dpy, arg, values.led_mode);
412		}
413		break;
414	    }
415	    if (is_number(arg, 32) && atoi(arg) > 0) {
416		values.led = atoi(arg);
417		i++;
418	    }
419	    set_led(dpy, values.led, values.led_mode);
420	} else if (strcmp(arg, "led") == 0) {	/* Turn on one or all LEDs  */
421	    values.led_mode = ON;
422	    values.led = ALL;
423	    if (i >= argc) {
424		set_led(dpy, values.led,
425			values.led_mode);	/* set led to def */
426		break;
427	    }
428	    arg = nextarg(i, argv);
429	    if (strcmp(arg, "named") == 0) {
430		if (++i >= argc) {
431		    usage("missing argument to -led named");
432		} else {
433		    arg = nextarg(i, argv);
434		    xkbset_led(dpy, arg, values.led_mode);
435		}
436		break;
437	    }
438	    if (strcmp(arg, "on") == 0) {
439		i++;
440	    } else if (strcmp(arg, "off") == 0) { /* ...except in this case. */
441		values.led_mode = OFF;
442		i++;
443	    } else if (is_number(arg, 32) && atoi(arg) > 0) {
444		values.led = atoi(arg);
445		i++;
446	    }
447	    set_led(dpy, values.led, values.led_mode);
448	}
449/*  Set pointer (mouse) settings:  Acceleration and Threshold. */
450	else if (strcmp(arg, "m") == 0 || strcmp(arg, "mouse") == 0) {
451	    acc_num = SERVER_DEFAULT;		/* restore server defaults */
452	    acc_denom = SERVER_DEFAULT;
453	    threshold = SERVER_DEFAULT;
454	    if (i >= argc) {
455		set_mouse(dpy, acc_num, acc_denom, threshold);
456		break;
457	    }
458	    arg = argv[i];
459	    if (strcmp(arg, "default") == 0) {
460		i++;
461	    } else if (*arg >= '0' && *arg <= '9') {
462		acc_denom = 1;
463		sscanf(arg, "%d/%d", &acc_num, &acc_denom);
464		i++;
465		if (i >= argc) {
466		    set_mouse(dpy, acc_num, acc_denom, threshold);
467		    break;
468		}
469		arg = argv[i];
470		if (*arg >= '0' && *arg <= '9') {
471		    threshold = atoi(arg); /* Set threshold as user specified. */
472		    i++;
473		}
474	    }
475	    set_mouse(dpy, acc_num, acc_denom, threshold);
476	}
477#ifdef DPMSExtension
478	else if (strcmp(arg, "+dpms") == 0) {	/* turn on DPMS */
479	    int dummy;
480
481	    if (DPMSQueryExtension(dpy, &dummy, &dummy))
482		DPMSEnable(dpy);
483	    else
484		fprintf(stderr,
485		    "server does not have extension for +dpms option\n");
486	} else if (strcmp(arg, "-dpms") == 0) {	/* shut off DPMS */
487	    int dummy;
488
489	    if (DPMSQueryExtension(dpy, &dummy, &dummy))
490		DPMSDisable(dpy);
491	    else
492		fprintf(stderr,
493		    "server does not have extension for -dpms option\n");
494
495	} else if (strcmp(arg, "dpms") == 0) {	/* tune DPMS */
496	    int dummy;
497
498	    if (DPMSQueryExtension(dpy, &dummy, &dummy)) {
499		DPMSGetTimeouts(dpy, &standby_timeout, &suspend_timeout,
500		    &off_timeout);
501		if (i >= argc) {
502		    DPMSEnable(dpy);
503		    break;
504		}
505		arg = argv[i];
506		if (*arg >= '0' && *arg <= '9') {
507		    sscanf(arg, "%hu", &standby_timeout);
508		    i++;
509		    arg = argv[i];
510		    if ((arg) && (*arg >= '0' && *arg <= '9')) {
511			sscanf(arg, "%hu", &suspend_timeout);
512			i++;
513			arg = argv[i];
514			if ((arg) && (*arg >= '0' && *arg <= '9')) {
515			    sscanf(arg, "%hu", &off_timeout);
516			    i++;
517			    arg = argv[i];
518			}
519		    }
520		    if ((suspend_timeout != 0)
521			&& (standby_timeout > suspend_timeout)) {
522			fprintf(stderr, "illegal combination of values\n");
523			fprintf(stderr,
524			    "  standby time of %d is greater than suspend time of %d\n",
525			    standby_timeout, suspend_timeout);
526			exit(EXIT_FAILURE);
527		    }
528		    if ((off_timeout != 0) && (suspend_timeout > off_timeout)) {
529			fprintf(stderr, "illegal combination of values\n");
530			fprintf(stderr,
531			    "  suspend time of %d is greater than off time of %d\n",
532			    suspend_timeout, off_timeout);
533			exit(EXIT_FAILURE);
534		    }
535		    if ((suspend_timeout == 0) && (off_timeout != 0) &&
536			(standby_timeout > off_timeout)) {
537			fprintf(stderr, "illegal combination of values\n");
538			fprintf(stderr,
539			    "  standby time of %d is greater than off time of %d\n",
540			    standby_timeout, off_timeout);
541			exit(EXIT_FAILURE);
542		    }
543		    DPMSEnable(dpy);
544		    DPMSSetTimeouts(dpy, standby_timeout, suspend_timeout,
545			off_timeout);
546		} else if (strcmp(arg, "force") == 0) {
547		    if (++i >= argc)
548			usage("missing argument to dpms force");
549		    arg = argv[i];
550		    /*
551		     * The calls to usleep below are necessary to
552		     * delay the actual DPMS mode setting briefly.
553		     * Without them, it's likely that the mode will be
554		     * set between the Down and Up key transitions, in
555		     * which case the Up transition may immediately
556		     * turn the display back on.
557		     *
558		     */
559
560#ifdef HAVE_USLEEP
561# define Usleep(us) usleep((us))
562#elif defined(WIN32)
563# define Usleep(us) Sleep(us)
564#else
565# define Usleep(us) sleep((us / 1000000 > 0) ? us / 1000000 : 1)
566#endif /* HAVE_USLEEP */
567
568		    if (strcmp(arg, "on") == 0) {
569			DPMSEnable(dpy);
570			DPMSForceLevel(dpy, DPMSModeOn);
571			i++;
572		    } else if (strcmp(arg, "standby") == 0) {
573			DPMSEnable(dpy);
574			Usleep(100000);
575			DPMSForceLevel(dpy, DPMSModeStandby);
576			i++;
577		    } else if (strcmp(arg, "suspend") == 0) {
578			DPMSEnable(dpy);
579			Usleep(100000);
580			DPMSForceLevel(dpy, DPMSModeSuspend);
581			i++;
582		    } else if (strcmp(arg, "off") == 0) {
583			DPMSEnable(dpy);
584			Usleep(100000);
585			DPMSForceLevel(dpy, DPMSModeOff);
586			i++;
587		    } else {
588			fprintf(stderr, "bad parameter %s\n", arg);
589			i++;
590		    }
591		}
592	    } else {
593		fprintf(stderr,
594		    "server does not have extension for dpms option\n");
595	    }
596	}
597#endif /* DPMSExtension */
598	else if (strcmp(arg, "s") == 0) {
599	    if (i >= argc) {
600		set_saver(dpy, ALL, 0);	/* Set everything to default  */
601		break;
602	    }
603	    arg = argv[i];
604	    if (strcmp(arg, "blank") == 0) { /* Alter blanking preference. */
605		set_saver(dpy, PREFER_BLANK, PreferBlanking);
606		i++;
607	    } else if (strcmp(arg, "noblank") == 0) {	/*  Ditto.  */
608		set_saver(dpy, PREFER_BLANK, DontPreferBlanking);
609		i++;
610	    } else if (strcmp(arg, "expose") == 0) {	/* Alter exposure preference. */
611		set_saver(dpy, ALLOW_EXP, AllowExposures);
612		i++;
613	    } else if (strcmp(arg, "noexpose") == 0) {	/*  Ditto.  */
614		set_saver(dpy, ALLOW_EXP, DontAllowExposures);
615		i++;
616	    } else if (strcmp(arg, "off") == 0) {
617		set_saver(dpy, TIMEOUT, 0);	/*  Turn off screen saver.  */
618		i++;
619		if (i >= argc)
620		    break;
621		arg = argv[i];
622		if (strcmp(arg, "off") == 0) {
623		    set_saver(dpy, INTERVAL, 0);
624		    i++;
625		}
626	    } else if (strcmp(arg, "default") == 0) {	/* Leave as default. */
627		set_saver(dpy, ALL, SERVER_DEFAULT);
628		i++;
629	    } else if (strcmp(arg, "on") == 0) {	/* Turn on.       */
630		set_saver(dpy, ALL, DEFAULT_TIMEOUT);
631		i++;
632	    } else if (strcmp(arg, "activate") == 0) {	/* force it active */
633		XActivateScreenSaver(dpy);
634		i++;
635	    } else if (strcmp(arg, "reset") == 0) {	/* force it inactive */
636		XResetScreenSaver(dpy);
637		i++;
638	    } else if (*arg >= '0' && *arg <= '9') {	/* Set as user wishes. */
639		set_saver(dpy, TIMEOUT, atoi(arg));
640		i++;
641		if (i >= argc)
642		    break;
643		arg = argv[i];
644		if (*arg >= '0' && *arg <= '9') {
645		    set_saver(dpy, INTERVAL, atoi(arg));
646		    i++;
647		}
648	    }
649	} else if (strcmp(arg, "-r") == 0) {		/* Turn off one or
650							   all autorepeats */
651	    auto_repeat_mode = OFF;
652	    key = ALL;		       			/* None specified */
653	    arg = argv[i];
654	    if (i < argc)
655		if (is_number(arg, 255)) {
656		    key = atoi(arg);
657		    i++;
658		}
659	    set_repeat(dpy, key, auto_repeat_mode);
660	} else if (strcmp(arg, "r") == 0) {		/* Turn on one or
661							   all autorepeats */
662	    auto_repeat_mode = ON;
663	    key = ALL;		       			/* None specified */
664	    arg = argv[i];
665	    if (i < argc) {
666		if (strcmp(arg, "on") == 0) {
667		    i++;
668		} else if (strcmp(arg, "off") == 0) {	/*  ...except in
669							    this case */
670		    auto_repeat_mode = OFF;
671		    i++;
672		}
673#if defined(XF86MISC) || defined(XKB)
674		else if (strcmp(arg, "rate") == 0) {	/*  ...or this one. */
675		    int delay = 0, rate = 0;
676
677#ifdef XF86MISC
678		    int rate_set = 0;
679#endif
680
681#ifdef XKB
682		    if (XkbQueryExtension(dpy, &xkbopcode, &xkbevent,
683					  &xkberror, &xkbmajor, &xkbminor)) {
684			delay = XKBDDELAY_DEFAULT;
685			rate = XKBDRATE_DEFAULT;
686			xkbpresent = 1;
687		    }
688#endif
689#ifdef XF86MISC
690		    if (!xkbpresent) {
691			int dummy;
692
693			if (XF86MiscQueryExtension(dpy, &dummy, &dummy)) {
694			    delay = KBDDELAY_DEFAULT;
695			    rate = KBDRATE_DEFAULT;
696			    miscpresent = 1;
697			}
698		    }
699#endif
700		    if (!xkbpresent && !miscpresent)
701			fprintf(stderr,
702				"server does not have extension for \"r rate\" option\n");
703		    i++;
704		    arg = argv[i];
705		    if (i < argc) {
706			if (is_number(arg, 10000) && atoi(arg) > 0) {
707			    delay = atoi(arg);
708			    i++;
709			    arg = argv[i];
710			    if (i < argc) {
711				if (is_number(arg, 255) && atoi(arg) > 0) {
712				    rate = atoi(arg);
713				    i++;
714				}
715			    }
716			}
717		    }
718#ifdef XKB
719		    if (xkbpresent) {
720			xkbset_repeatrate(dpy, delay, 1000 / rate);
721#ifdef XF86MISC
722			rate_set = 1;
723#endif
724		    }
725#endif
726#ifdef XF86MISC
727		    if (miscpresent && !rate_set) {
728			set_repeatrate(dpy, delay, rate);
729		    }
730#endif
731		}
732#endif
733		else if (is_number(arg, 255)) {
734		    key = atoi(arg);
735		    i++;
736		}
737	    }
738	    set_repeat(dpy, key, auto_repeat_mode);
739	} else if (strcmp(arg, "p") == 0) {
740	    if (i + 1 >= argc)
741		usage("missing argument to p");
742	    arg = argv[i];
743	    if (numpixels >= MAX_PIXEL_COUNT)
744		usage("more than %d pixels specified", MAX_PIXEL_COUNT);
745	    if (*arg >= '0' && *arg <= '9')
746		pixels[numpixels] = strtoul(arg, NULL, 10);
747	    else
748		usage("invalid pixel number %s", arg);
749	    i++;
750	    colors[numpixels] = argv[i];
751	    i++;
752	    numpixels++;
753	} else if (strcmp(arg, "-k") == 0) {
754	    set_lock(dpy, OFF);
755	} else if (strcmp(arg, "k") == 0) {
756	    set_lock(dpy, ON);
757	} else if (strcmp(arg, "q") == 0 || strcmp(arg, "-q") == 0) {
758	    query(dpy);
759	} else
760	    usage("unknown option %s", arg);
761    }
762
763    if (numpixels)
764	set_pixels(dpy, pixels, colors, numpixels);
765
766    XCloseDisplay(dpy);
767
768    exit(error_status);		       /*  Done.  We can go home now.  */
769}
770
771static int
772is_number(const char *arg, int maximum)
773{
774    const char *p;
775
776    if (arg[0] == '-' && arg[1] == '1' && arg[2] == '\0')
777	return (1);
778    for (p = arg; isdigit(*p); p++) ;
779    if (*p || atoi(arg) > maximum)
780	return (0);
781    return (1);
782}
783
784/*  These next few functions do the real work (xsetting things).
785 */
786static void
787set_click(Display *dpy, int percent)
788{
789    XKeyboardControl values;
790    XKeyboardState kbstate;
791
792    values.key_click_percent = percent;
793    if (percent == DEFAULT_ON)
794	values.key_click_percent = SERVER_DEFAULT;
795    XChangeKeyboardControl(dpy, KBKeyClickPercent, &values);
796    if (percent == DEFAULT_ON) {
797	XGetKeyboardControl(dpy, &kbstate);
798	if (!kbstate.key_click_percent) {
799	    values.key_click_percent = -percent;
800	    XChangeKeyboardControl(dpy, KBKeyClickPercent, &values);
801	}
802    }
803    return;
804}
805
806static void
807set_bell_vol(Display *dpy, int percent)
808{
809    XKeyboardControl values;
810    XKeyboardState kbstate;
811
812    values.bell_percent = percent;
813    if (percent == DEFAULT_ON)
814	values.bell_percent = SERVER_DEFAULT;
815    XChangeKeyboardControl(dpy, KBBellPercent, &values);
816    if (percent == DEFAULT_ON) {
817	XGetKeyboardControl(dpy, &kbstate);
818	if (!kbstate.bell_percent) {
819	    values.bell_percent = -percent;
820	    XChangeKeyboardControl(dpy, KBBellPercent, &values);
821	}
822    }
823    return;
824}
825
826static void
827set_bell_pitch(Display *dpy, int pitch)
828{
829    XKeyboardControl values;
830
831    values.bell_pitch = pitch;
832    XChangeKeyboardControl(dpy, KBBellPitch, &values);
833    return;
834}
835
836static void
837set_bell_dur(Display *dpy, int duration)
838{
839    XKeyboardControl values;
840
841    values.bell_duration = duration;
842    XChangeKeyboardControl(dpy, KBBellDuration, &values);
843    return;
844}
845
846/*
847 * Set, add, or subtract the path according to before and after flags:
848 *
849 *	before	after	action
850 *
851 *	   0      0	FontPath := path
852 *	  -1      0	FontPath := current - path
853 *	   0     -1	FontPath := current - path
854 *	   1      0	FontPath := path + current
855 *	   0      1	FontPath := current + path
856 */
857static void
858set_font_path(Display *dpy, const char *path, int special, int before, int after)
859{
860    char *directories = NULL;
861    char **directoryList = NULL;
862    unsigned int ndirs = 0;
863    char **currentList = NULL;
864    unsigned int ncurrent = 0;
865
866    if (special) {
867	if (strcmp(path, "default") == 0) {
868	    XSetFontPath(dpy, NULL, 0);
869	    return;
870	}
871	if (strcmp(path, "rehash") == 0) {
872	    currentList = XGetFontPath(dpy, (int *) &ncurrent);
873	    if (!currentList) {
874		fprintf(stderr, "%s:  unable to get current font path.\n",
875			progName);
876		return;
877	    }
878	    XSetFontPath(dpy, currentList, (int) ncurrent);
879	    XFreeFontPath(currentList);
880	    return;
881	}
882	/*
883	 * for now, fall though and process keyword and directory list for
884	 * compatibility with previous versions.
885	 */
886    }
887
888    /*
889     * parse the path list.  If before or after is non-zero, we'll need
890     * the current value.
891     */
892
893    if (before != 0 || after != 0) {
894	currentList = XGetFontPath(dpy, (int *) &ncurrent);
895	if (!currentList) {
896	    fprintf(stderr, "%s:  unable to get old font path.\n", progName);
897	    before = after = 0;
898	}
899    }
900
901    {
902	/* count the number of directories in path */
903	const char *cp = path;
904
905	ndirs = 1;
906	while ((cp = strchr(cp, ',')) != NULL) {
907	    ndirs++;
908	    cp++;
909	}
910    }
911
912    directoryList = (char **)malloc(ndirs * sizeof(char *));
913    if (!directoryList)
914	error("out of memory for font path directory list");
915
916    directories = strdup(path);
917    if (!directories)
918        error("out of memory for font path directory string");
919    else
920    {
921	/* mung the path and set directoryList pointers */
922	unsigned int i = 0;
923	char *cp = directories;
924
925	directoryList[i++] = cp;
926	while ((cp = strchr(cp, ',')) != NULL) {
927	    directoryList[i++] = cp + 1;
928	    *cp++ = '\0';
929	}
930	if (i != ndirs) {
931	    fprintf(stderr,
932		"%s: internal error, only parsed %d of %d directories.\n",
933		progName, i, ndirs);
934	    exit(EXIT_FAILURE);
935	}
936    }
937
938    /*
939     * now we have have parsed the input path, so we can set it
940     */
941
942    if (before == 0 && after == 0) {
943	XSetFontPath(dpy, directoryList, (int) ndirs);
944    }
945
946    /* if adding to list, build a superset */
947    if (before > 0 || after > 0) {
948	unsigned int nnew = ndirs + ncurrent;
949	char **newList = (char **)malloc(nnew * sizeof(char *));
950
951	if (!newList)
952	    error("out of memory");
953	if (before > 0) {	       /* new + current */
954	    memmove((char *)newList, (char *)directoryList,
955                    (ndirs * sizeof(char *)));
956	    memmove((char *)(newList + ndirs), (char *)currentList,
957		    (ncurrent * sizeof(char *)));
958	    XSetFontPath(dpy, newList, (int) nnew);
959	} else if (after > 0) {
960	    memmove((char *)newList, (char *)currentList,
961		    (ncurrent * sizeof(char *)));
962	    memmove((char *)(newList + ncurrent), (char *)directoryList,
963		    (ndirs * sizeof(char *)));
964	    XSetFontPath(dpy, newList,(int) nnew);
965	}
966	free((char *)newList);
967    }
968
969    /* if deleting from list, build one the same size */
970    if (before < 0 || after < 0) {
971	unsigned int i, j;
972	unsigned int nnew = 0;
973	char **newList = (char **)malloc(ncurrent * sizeof(char *));
974
975	if (!newList)
976	    error("out of memory");
977	for (i = 0; i < ncurrent; i++) {
978	    for (j = 0; j < ndirs; j++) {
979		if (strcmp(currentList[i], directoryList[j]) == 0)
980		    break;
981	    }
982	    /* if we ran out, then insert into new list */
983	    if (j == ndirs)
984		newList[nnew++] = currentList[i];
985	}
986	if (nnew == ncurrent) {
987	    fprintf(stderr,
988		    "%s:  warning, no entries deleted from font path.\n",
989		    progName);
990	}
991	XSetFontPath(dpy, newList, (int) nnew);
992	free((char *)newList);
993    }
994
995    free(directories);
996    if (directoryList)
997	free((char *)directoryList);
998    if (currentList)
999	XFreeFontPath(currentList);
1000
1001    return;
1002}
1003
1004static void
1005set_led(Display *dpy, int led, int led_mode)
1006{
1007    XKeyboardControl values;
1008
1009    values.led_mode = led_mode;
1010    if (led != ALL) {
1011	values.led = led;
1012	XChangeKeyboardControl(dpy, KBLed | KBLedMode, &values);
1013    } else {
1014	XChangeKeyboardControl(dpy, KBLedMode, &values);
1015    }
1016    return;
1017}
1018
1019static void
1020xkbset_led(Display *dpy, const char *led, int led_mode)
1021{
1022#ifndef XKB
1023    error("  xset was not built with XKB Extension support\n");
1024#else
1025    int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion;
1026    int xkbopcode, xkbevent, xkberror;
1027    Atom ledatom;
1028
1029    if (XkbQueryExtension(dpy, &xkbopcode, &xkbevent, &xkberror,
1030			  &xkbmajor, &xkbminor)) {
1031	ledatom = XInternAtom(dpy, led, True);
1032	if ((ledatom != None) &&
1033	    XkbGetNamedIndicator(dpy, ledatom, NULL, NULL, NULL, NULL)) {
1034	    if (XkbSetNamedIndicator(dpy, ledatom, True,
1035				     led_mode, False, NULL) == False) {
1036		printf("Failed to set led named %s %s\n",
1037		       led, led_mode ? "on" : "off");
1038	    }
1039	} else {
1040	    fprintf(stderr,"%s: Invalid led name: %s\n", progName, led);
1041	}
1042    } else {
1043	printf("  Server does not have the XKB Extension\n");
1044    }
1045#endif
1046    return;
1047}
1048
1049static void
1050set_mouse(Display *dpy, int acc_num, int acc_denom, int threshold)
1051{
1052    int do_accel = True, do_threshold = True;
1053
1054    if (acc_num == DONT_CHANGE)	       /* what an incredible crock... */
1055	do_accel = False;
1056    if (threshold == DONT_CHANGE)
1057	do_threshold = False;
1058    if (acc_num < 0)		       /* shouldn't happen */
1059	acc_num = SERVER_DEFAULT;
1060    if (acc_denom <= 0)		       /* prevent divide by zero */
1061	acc_denom = SERVER_DEFAULT;
1062    if (threshold < 0)
1063	threshold = SERVER_DEFAULT;
1064    XChangePointerControl(dpy, do_accel, do_threshold, acc_num,
1065			  acc_denom, threshold);
1066    return;
1067}
1068
1069static void
1070set_saver(Display *dpy, int mask, int value)
1071{
1072    int timeout, interval, prefer_blank, allow_exp;
1073
1074    XGetScreenSaver(dpy, &timeout, &interval, &prefer_blank, &allow_exp);
1075    if (mask == TIMEOUT)
1076	timeout = value;
1077    if (mask == INTERVAL)
1078	interval = value;
1079    if (mask == PREFER_BLANK)
1080	prefer_blank = value;
1081    if (mask == ALLOW_EXP)
1082	allow_exp = value;
1083    if (mask == ALL) {
1084	timeout = SERVER_DEFAULT;
1085	interval = SERVER_DEFAULT;
1086	prefer_blank = DefaultBlanking;
1087	allow_exp = DefaultExposures;
1088    }
1089    XSetScreenSaver(dpy, timeout, interval, prefer_blank, allow_exp);
1090    if (mask == ALL && value == DEFAULT_TIMEOUT) {
1091	XGetScreenSaver(dpy, &timeout, &interval, &prefer_blank, &allow_exp);
1092	if (!timeout)
1093	    XSetScreenSaver(dpy, -DEFAULT_TIMEOUT, interval, prefer_blank,
1094			    allow_exp);
1095    }
1096    return;
1097}
1098
1099static void
1100set_repeat(Display *dpy, int key, int auto_repeat_mode)
1101{
1102    XKeyboardControl values;
1103
1104    values.auto_repeat_mode = auto_repeat_mode;
1105    if (key != ALL) {
1106	values.key = key;
1107	XChangeKeyboardControl(dpy, KBKey | KBAutoRepeatMode, &values);
1108    } else {
1109	XChangeKeyboardControl(dpy, KBAutoRepeatMode, &values);
1110    }
1111    return;
1112}
1113
1114#ifdef XF86MISC
1115static void
1116set_repeatrate(Display *dpy, int delay, int rate)
1117{
1118    XF86MiscKbdSettings values;
1119
1120    XF86MiscGetKbdSettings(dpy, &values);
1121    values.delay = delay;
1122    values.rate = rate;
1123    XF86MiscSetKbdSettings(dpy, &values);
1124    return;
1125}
1126#endif
1127
1128#ifdef XKB
1129static void
1130xkbset_repeatrate(Display *dpy, int delay, int interval)
1131{
1132    XkbDescPtr xkb = XkbAllocKeyboard();
1133
1134    if (!xkb)
1135	return;
1136    XkbGetControls(dpy, XkbRepeatKeysMask, xkb);
1137    xkb->ctrls->repeat_delay = delay;
1138    xkb->ctrls->repeat_interval = interval;
1139    XkbSetControls(dpy, XkbRepeatKeysMask, xkb);
1140    XkbFreeKeyboard(xkb, 0, True);
1141}
1142#endif
1143
1144static void
1145set_pixels(Display *dpy, unsigned long *pixels, caddr_t * colors,
1146    int numpixels)
1147{
1148    XColor def;
1149    int scr = DefaultScreen(dpy);
1150    Visual *visual = DefaultVisual(dpy, scr);
1151    Colormap cmap = DefaultColormap(dpy, scr);
1152    unsigned long max_cells = (unsigned long) DisplayCells(dpy, scr);
1153    XVisualInfo viproto, *vip;
1154    int nvisuals = 0;
1155    const char *visual_type = NULL;
1156    int i;
1157
1158    viproto.visualid = XVisualIDFromVisual(visual);
1159    vip = XGetVisualInfo(dpy, VisualIDMask, &viproto, &nvisuals);
1160    if (!vip) {
1161	fprintf(stderr, "%s: Can't get visual for visualID 0x%x\n",
1162		progName, (unsigned int)viproto.visualid);
1163	return;
1164    }
1165
1166    switch (vip->class) {
1167    case GrayScale:
1168    case PseudoColor:
1169	break;
1170    case TrueColor:
1171	visual_type = "TrueColor";
1172	/* fall through */
1173    case DirectColor:
1174	max_cells *= max_cells * max_cells;
1175	break;
1176    case StaticGray:
1177	visual_type = "StaticGray";
1178	break;
1179    case StaticColor:
1180	visual_type = "StaticColor";
1181	break;
1182    default:
1183	fprintf(stderr, "%s:  unknown visual class type %d\n",
1184		progName, vip->class);
1185	numpixels = 0;
1186    }
1187
1188    if (visual_type) {
1189	fprintf(stderr,
1190		"%s:  cannot set pixel values in read-only %s visuals\n",
1191		progName, visual_type);
1192    } else {
1193	for (i = 0; i < numpixels; i++) {
1194	    def.pixel = pixels[i];
1195	    if (def.pixel >= max_cells)
1196		fprintf(stderr,
1197			"%s:  pixel value %ld out of colormap range 0 through %ld\n",
1198			progName, def.pixel, max_cells - 1);
1199	    else {
1200		if (XParseColor(dpy, cmap, colors[i], &def))
1201		    XStoreColor(dpy, cmap, &def);
1202		else
1203		    fprintf(stderr, "%s:  invalid color \"%s\"\n", progName,
1204			    colors[i]);
1205	    }
1206	}
1207    }
1208
1209    XFree((char *)vip);
1210
1211    return;
1212}
1213
1214static void
1215set_lock(Display *dpy, Bool onoff)
1216{
1217    XModifierKeymap *mods;
1218
1219    mods = XGetModifierMapping(dpy);
1220
1221    if (onoff)
1222	mods =
1223	    XInsertModifiermapEntry(mods, (KeyCode) XK_Caps_Lock,
1224				    LockMapIndex);
1225    else
1226	mods =
1227	    XDeleteModifiermapEntry(mods, (KeyCode) XK_Caps_Lock,
1228				    LockMapIndex);
1229    XSetModifierMapping(dpy, mods);
1230    XFreeModifiermap(mods);
1231    return;
1232}
1233
1234#ifdef FONTCACHE
1235static Status
1236set_font_cache(Display *dpy, long himark, long lowmark, long balance)
1237{
1238    FontCacheSettings cs;
1239    Status status;
1240
1241    cs.himark = himark * 1024;
1242    cs.lowmark = lowmark * 1024;
1243    cs.balance = balance;
1244    status = FontCacheChangeCacheSettings(dpy, &cs);
1245
1246    return status;
1247}
1248#endif
1249
1250static const char *
1251on_or_off(int val, int onval, const char *onstr,
1252    int offval, const char *offstr, char buf[], size_t bufsize)
1253{
1254    if (val == onval)
1255	return onstr;
1256    else if (val == offval)
1257	return offstr;
1258
1259    buf[0] = '\0';
1260    snprintf(buf, bufsize, "<%d>", val);
1261    return buf;
1262}
1263
1264/*  This is the information-getting function for telling the user what the
1265 *  current "xsettings" are.
1266 */
1267static void
1268query(Display *dpy)
1269{
1270    int scr = DefaultScreen(dpy);
1271    XKeyboardState values;
1272    int acc_num, acc_denom, threshold;
1273    int timeout, interval, prefer_blank, allow_exp;
1274
1275#ifdef XF86MISC
1276    XF86MiscKbdSettings kbdinfo;
1277#endif
1278#ifdef XKB
1279    XkbDescPtr xkb;
1280    int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion;
1281    int xkbopcode, xkbevent, xkberror;
1282#endif
1283    char **font_path;
1284    int npaths;
1285    int i, j;
1286    char buf[20];		       /* big enough for 16 bit number */
1287
1288    XGetKeyboardControl(dpy, &values);
1289    XGetPointerControl(dpy, &acc_num, &acc_denom, &threshold);
1290    XGetScreenSaver(dpy, &timeout, &interval, &prefer_blank, &allow_exp);
1291    font_path = XGetFontPath(dpy, &npaths);
1292
1293    printf("Keyboard Control:\n");
1294    printf
1295	("  auto repeat:  %s    key click percent:  %d    LED mask:  %08lx\n",
1296	 on_or_off(values.global_auto_repeat, AutoRepeatModeOn, "on",
1297		   AutoRepeatModeOff, "off", buf, sizeof(buf)),
1298	 values.key_click_percent, values.led_mask);
1299#ifdef XKB
1300    if (XkbQueryExtension(dpy, &xkbopcode, &xkbevent, &xkberror, &xkbmajor,
1301			  &xkbminor)
1302	&& (xkb = XkbAllocKeyboard()) != NULL) {
1303	if (XkbGetNames(dpy, XkbIndicatorNamesMask, xkb) == Success) {
1304	    Atom iatoms[XkbNumIndicators];
1305	    char *iatomnames[XkbNumIndicators];
1306	    Bool istates[XkbNumIndicators];
1307	    int inds[XkbNumIndicators];
1308	    int activecount = 0;
1309	    int maxnamelen = 0;
1310	    int columnwidth;
1311	    int linewidth;
1312
1313	    printf("  XKB indicators:\n");
1314
1315	    for (i = 0, j = 0; i < XkbNumIndicators; i++) {
1316		if (xkb->names->indicators[i] != None) {
1317		    iatoms[j++] =  xkb->names->indicators[i];
1318		}
1319	    }
1320
1321	    if (XGetAtomNames(dpy, iatoms, j, iatomnames)) {
1322		for (i = 0; i < j; i++) {
1323		    if (XkbGetNamedIndicator(dpy, iatoms[i], &inds[i],
1324					     &istates[i], NULL, NULL)) {
1325			int namelen = (int) strlen(iatomnames[i]);
1326			if (namelen > maxnamelen) {
1327			    maxnamelen = namelen;
1328			}
1329			activecount++;
1330		    } else {
1331			inds[i] = -1;
1332		    }
1333		}
1334	    }
1335
1336	    if (activecount == 0) {
1337		printf("    None\n");
1338	    } else {
1339
1340#define XKB_IND_FORMAT_CHARS 13 /* size of other chars in '    DD: X: off' */
1341#define MAX_LINE_WIDTH	     76
1342
1343		columnwidth = maxnamelen + XKB_IND_FORMAT_CHARS;
1344		if (columnwidth > MAX_LINE_WIDTH) {
1345		    columnwidth = MAX_LINE_WIDTH;
1346		}
1347
1348		for (i = 0, linewidth = 0; i < activecount ; i++) {
1349		    if (inds[i] != -1) {
1350			int spaces = columnwidth - XKB_IND_FORMAT_CHARS
1351			    - (int) strlen(iatomnames[i]);
1352
1353			if (spaces < 0)
1354			    spaces = 0;
1355
1356			linewidth += printf("    %02d: %s: %*s",
1357					    inds[i], iatomnames[i],
1358					    spaces + 3,
1359					    on_or_off(istates[i],
1360						      True,  "on ",
1361						      False, "off",
1362						      buf, sizeof(buf)));
1363		    }
1364		    if (linewidth > (MAX_LINE_WIDTH - columnwidth)) {
1365			printf("\n");
1366			linewidth = 0;
1367		    }
1368		}
1369		if (linewidth > 0) {
1370		    printf("\n");
1371		}
1372	    }
1373	}
1374	if (XkbGetControls(dpy, XkbRepeatKeysMask, xkb) == Success) {
1375	    printf("  auto repeat delay:  %d    repeat rate:  %d\n",
1376		   xkb->ctrls->repeat_delay,
1377		   1000 / xkb->ctrls->repeat_interval);
1378	}
1379    }
1380#ifdef XF86MISC
1381    else
1382#endif
1383#endif
1384#ifdef XF86MISC
1385    {
1386	int dummy;
1387
1388	if (XF86MiscQueryExtension(dpy, &dummy, &dummy) &&
1389	    XF86MiscGetKbdSettings(dpy, &kbdinfo))
1390	    printf("  auto repeat delay:  %d    repeat rate:  %d\n",
1391	           kbdinfo.delay, kbdinfo.rate);
1392    }
1393#endif
1394    printf("  auto repeating keys:  ");
1395    for (i = 0; i < 4; i++) {
1396	if (i)
1397	    printf("                        ");
1398	for (j = 0; j < 8; j++) {
1399	    printf("%02x", (unsigned char)values.auto_repeats[i * 8 + j]);
1400	}
1401	printf("\n");
1402    }
1403    printf("  bell percent:  %d    bell pitch:  %d    bell duration:  %d\n",
1404	   values.bell_percent, values.bell_pitch, values.bell_duration);
1405
1406    printf("Pointer Control:\n");
1407    printf("  acceleration:  %d/%d    threshold:  %d\n",
1408	   acc_num, acc_denom, threshold);
1409
1410    printf("Screen Saver:\n");
1411    printf("  prefer blanking:  %s    ",
1412	   on_or_off(prefer_blank, PreferBlanking, "yes",
1413		     DontPreferBlanking, "no", buf, sizeof(buf)));
1414    printf("allow exposures:  %s\n",
1415	   on_or_off(allow_exp, AllowExposures, "yes",
1416		     DontAllowExposures, "no", buf, sizeof(buf)));
1417    printf("  timeout:  %d    cycle:  %d\n", timeout, interval);
1418
1419    printf("Colors:\n");
1420    printf("  default colormap:  0x%lx    BlackPixel:  0x%lx    WhitePixel:  0x%lx\n",
1421	   DefaultColormap(dpy, scr), BlackPixel(dpy, scr), WhitePixel(dpy,
1422								       scr));
1423
1424    printf("Font Path:\n");
1425    if (npaths) {
1426	printf("  %s", *font_path++);
1427	for (--npaths; npaths; npaths--)
1428	    printf(",%s", *font_path++);
1429	printf("\n");
1430    } else {
1431	printf("  (empty)\n");
1432    }
1433
1434#ifdef MITMISC
1435    {
1436	int dummy;
1437
1438	if (XMITMiscQueryExtension(dpy, &dummy, &dummy)) {
1439	    if (XMITMiscGetBugMode(dpy))
1440		printf("Bug Mode: compatibility mode is enabled\n");
1441	    else
1442		printf("Bug Mode: compatibility mode is disabled\n");
1443	}
1444    }
1445#endif
1446#ifdef DPMSExtension
1447    {
1448
1449	int dummy;
1450	CARD16 standby, suspend, off;
1451	BOOL onoff;
1452	CARD16 state;
1453
1454	printf("DPMS (Energy Star):\n");
1455	if (DPMSQueryExtension(dpy, &dummy, &dummy)) {
1456	    if (DPMSCapable(dpy)) {
1457		DPMSGetTimeouts(dpy, &standby, &suspend, &off);
1458		printf("  Standby: %d    Suspend: %d    Off: %d\n",
1459		       standby, suspend, off);
1460		DPMSInfo(dpy, &state, &onoff);
1461		if (onoff) {
1462		    printf("  DPMS is Enabled\n");
1463		    switch (state) {
1464		    case DPMSModeOn:
1465			printf("  Monitor is On\n");
1466			break;
1467		    case DPMSModeStandby:
1468			printf("  Monitor is in Standby\n");
1469			break;
1470		    case DPMSModeSuspend:
1471			printf("  Monitor is in Suspend\n");
1472			break;
1473		    case DPMSModeOff:
1474			printf("  Monitor is Off\n");
1475			break;
1476		    default:
1477			printf("  Unrecognized response from server\n");
1478		    }
1479		} else
1480		    printf("  DPMS is Disabled\n");
1481	    } else
1482		printf("  Display is not capable of DPMS\n");
1483	} else {
1484	    printf("  Server does not have the DPMS Extension\n");
1485	}
1486    }
1487#endif
1488#ifdef FONTCACHE
1489    {
1490	int dummy;
1491	FontCacheSettings cs;
1492	int himark, lowmark, balance;
1493
1494	printf("Font cache:\n");
1495	if (FontCacheQueryExtension(dpy, &dummy, &dummy)) {
1496	    if (FontCacheGetCacheSettings(dpy, &cs)) {
1497		himark = cs.himark / 1024;
1498		lowmark = cs.lowmark / 1024;
1499		balance = cs.balance;
1500		printf("  hi-mark (KB): %d  low-mark (KB): %d  balance (%%): %d\n",
1501		       himark, lowmark, balance);
1502	    }
1503	} else {
1504	    printf("  Server does not have the FontCache Extension\n");
1505	}
1506    }
1507#endif
1508#ifdef XF86MISC
1509    {
1510	int dummy;
1511	int maj, min;
1512	XF86MiscFilePaths paths;
1513
1514	if (XF86MiscQueryExtension(dpy, &dummy, &dummy) &&
1515	    XF86MiscQueryVersion(dpy, &maj, &min) &&
1516	    ((maj > 0) || (maj == 0 && min >= 7)) &&
1517	    XF86MiscGetFilePaths(dpy, &paths)) {
1518	    printf("File paths:\n");
1519	    printf("  Config file:  %s\n", paths.configfile);
1520	    printf("  Modules path: %s\n", paths.modulepath);
1521	    printf("  Log file:     %s\n", paths.logfile);
1522	}
1523    }
1524#endif
1525
1526    return;
1527}
1528
1529#ifdef FONTCACHE
1530/*
1531 *  query_cache_status()
1532 *
1533 *  This is the information-getting function for telling the user what the
1534 *  current settings and statistics are.
1535 */
1536static void
1537query_cache_status(Display *dpy)
1538{
1539    int dummy;
1540    FontCacheSettings cs;
1541    FontCacheStatistics cstats;
1542    int himark, lowmark, balance;
1543
1544    if (FontCacheQueryExtension(dpy, &dummy, &dummy)) {
1545	if (FontCacheGetCacheSettings(dpy, &cs)) {
1546	    printf("font cache settings:\n");
1547	    himark = cs.himark / 1024;
1548	    lowmark = cs.lowmark / 1024;
1549	    balance = cs.balance;
1550	    printf("  hi-mark (KB): %d  low-mark (KB): %d  balance (%%): %d\n",
1551		   himark, lowmark, balance);
1552	}
1553	if (FontCacheGetCacheStatistics(dpy, &cstats)) {
1554	    printf("font cache statistics:\n");
1555	    printf("   cache purged: %ld\n", cstats.purge_runs);
1556	    printf("   cache status: %ld\n", cstats.purge_stat);
1557	    printf("  cache balance: %ld\n", cstats.balance);
1558	    printf("font cache entry statistics:\n");
1559	    printf("      hits: %ld\n", cstats.f.hits);
1560	    printf("  misshits: %ld\n", cstats.f.misshits);
1561	    printf("    purged: %ld\n", cstats.f.purged);
1562	    printf("     usage: %ld\n", cstats.f.usage);
1563	    printf("large bitmap cache entry statistics:\n");
1564	    printf("      hits: %ld\n", cstats.v.hits);
1565	    printf("  misshits: %ld\n", cstats.v.misshits);
1566	    printf("    purged: %ld\n", cstats.v.purged);
1567	    printf("     usage: %ld\n", cstats.v.usage);
1568	}
1569    } else {
1570	printf("Server does not have the FontCache Extension\n");
1571    }
1572}
1573#endif
1574
1575/*  This is the usage function */
1576
1577static void
1578usage(const char *fmt, ...)
1579{
1580    va_list ap;
1581
1582    if (fmt) {
1583	fprintf(stderr, "%s:  ", progName);
1584	va_start(ap, fmt);
1585	vfprintf(stderr, fmt, ap);
1586	va_end(ap);
1587	fprintf(stderr, "\n\n");
1588
1589    }
1590
1591    fprintf(stderr, "usage:  %s [-display host:dpy] option ...\n%s", progName,
1592            "    To turn bell off:\n"
1593            "\t-b                b off               b 0\n"
1594            "    To set bell volume, pitch and duration:\n"
1595            "\t b [vol [pitch [dur]]]          b on\n"
1596#ifdef MITMISC
1597            "    To disable bug compatibility mode:\n"
1598            "\t-bc\n"
1599            "    To enable bug compatibility mode:\n"
1600            "\tbc\n"
1601#endif
1602            "    To turn keyclick off:\n"
1603            "\t-c                c off               c 0\n"
1604            "    To set keyclick volume:\n"
1605            "\t c [0-100]        c on\n"
1606#ifdef DPMSExtension
1607            "    To control Energy Star (DPMS) features:\n"
1608            "\t-dpms      Energy Star features off\n"
1609            "\t+dpms      Energy Star features on\n"
1610            "\t dpms [standby [suspend [off]]]     \n"
1611            "\t      force standby \n"
1612            "\t      force suspend \n"
1613            "\t      force off \n"
1614            "\t      force on \n"
1615            "\t      (also implicitly enables DPMS features) \n"
1616            "\t      a timeout value of zero disables the mode \n"
1617#endif
1618#ifdef FONTCACHE
1619            "    To control font cache:\n"
1620            "\t fc [hi-mark [low-mark [balance]]]\n"
1621            "\t    both mark values specified in KB\n"
1622            "\t    balance value specified in percent (10 - 90)\n"
1623            "    Show font cache statistics:\n"
1624            "\t fc s\n"
1625#endif
1626            "    To set the font path:\n"
1627            "\t fp= path[,path...]\n"
1628            "    To restore the default font path:\n"
1629            "\t fp default\n"
1630            "    To have the server reread font databases:\n"
1631            "\t fp rehash\n"
1632            "    To remove elements from font path:\n"
1633            "\t-fp path[,path...]  fp- path[,path...]\n"
1634            "    To prepend or append elements to font path:\n"
1635            "\t+fp path[,path...]  fp+ path[,path...]\n"
1636            "    To set LED states off or on:\n"
1637            "\t-led [1-32]         led off\n"
1638            "\t led [1-32]         led on\n"
1639#ifdef XKB
1640            "\t-led named 'name'   led off\n"
1641            "\t led named 'name'   led on\n"
1642#endif
1643            "    To set mouse acceleration and threshold:\n"
1644            "\t m [acc_mult[/acc_div] [thr]]    m default\n"
1645            "    To set pixel colors:\n"
1646            "\t p pixel_value color_name\n"
1647            "    To turn auto-repeat off or on:\n"
1648            "\t-r [keycode]        r off\n"
1649            "\t r [keycode]        r on\n"
1650#if defined(XF86MISC) || defined(XKB)
1651            "\t r rate [delay [rate]]\n"
1652#endif
1653            "    For screen-saver control:\n"
1654            "\t s [timeout [cycle]]  s default    s on\n"
1655            "\t s blank              s noblank    s off\n"
1656            "\t s expose             s noexpose\n"
1657            "\t s activate           s reset\n"
1658            "    For status information:  q\n"
1659            "    To print version: -version\n"
1660        );
1661    exit(EXIT_SUCCESS);
1662}
1663
1664static void
1665error(const char *message)
1666{
1667    fprintf(stderr, "%s: %s\n", progName, message);
1668    exit(EXIT_FAILURE);
1669}
1670
1671static int
1672local_xerror(Display *dpy, XErrorEvent *rep)
1673{
1674    if (rep->request_code == X_SetFontPath && rep->error_code == BadValue) {
1675	fprintf(stderr,
1676		"%s:  bad font path element (#%ld), possible causes are:\n",
1677		progName, rep->resourceid);
1678	fprintf(stderr,
1679                "    Directory does not exist or has wrong permissions\n"
1680                "    Directory missing fonts.dir\n"
1681                "    Incorrect font server address or syntax\n");
1682    } else if (rep->request_code == X_StoreColors) {
1683	switch (rep->error_code) {
1684	  case BadAccess:
1685	    fprintf(stderr,
1686		    "%s:  pixel not allocated read/write\n", progName);
1687	    break;
1688	  case BadValue:
1689	    fprintf(stderr,
1690		    "%s:  cannot store in pixel 0x%lx, invalid pixel number\n",
1691		    progName, rep->resourceid);
1692	    break;
1693	  default:
1694	    XmuPrintDefaultErrorMessage(dpy, rep, stderr);
1695	}
1696    } else
1697	XmuPrintDefaultErrorMessage(dpy, rep, stderr);
1698
1699    error_status = -1;
1700
1701    return (0);
1702}
1703