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