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