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