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