Commit | Line | Data |
---|---|---|
984263bc | 1 | /*- |
f6e8a0a1 | 2 | * Copyright (c) 1994-1996 Søren Schmidt |
984263bc MD |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer, | |
10 | * in this position and unchanged. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. The name of the author may not be used to endorse or promote products | |
4d9022e3 | 15 | * derived from this software without specific prior written permission |
984263bc MD |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
1de703da MD |
27 | * |
28 | * $FreeBSD: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.32.2.7 2002/09/15 22:31:50 dd Exp $ | |
984263bc MD |
29 | */ |
30 | ||
b9fdfcf1 | 31 | #include <machine/console.h> |
6a0d37df | 32 | |
b9fdfcf1 CP |
33 | #include <sys/consio.h> |
34 | #include <sys/errno.h> | |
35 | #include <sys/types.h> | |
36 | #include <sys/stat.h> | |
37 | ||
984263bc MD |
38 | #include <ctype.h> |
39 | #include <err.h> | |
40 | #include <limits.h> | |
41 | #include <stdio.h> | |
42 | #include <stdlib.h> | |
43 | #include <string.h> | |
44 | #include <unistd.h> | |
b9fdfcf1 | 45 | |
984263bc MD |
46 | #include "path.h" |
47 | #include "decode.h" | |
48 | ||
984263bc | 49 | |
f56cbf1f | 50 | #define DATASIZE(x) ((x).w * (x).h * 256 / 8) |
6a0d37df | 51 | |
f56cbf1f MD |
52 | #define DUMP_RAW 0 |
53 | #define DUMP_TXT 1 | |
6a0d37df | 54 | |
f56cbf1f | 55 | #define DUMP_FMT_REV 1 |
984263bc | 56 | |
984263bc | 57 | |
6a0d37df | 58 | char legal_colors[16][16] = { |
f56cbf1f MD |
59 | "black", "blue", "green", "cyan", |
60 | "red", "magenta", "brown", "white", | |
61 | "grey", "lightblue", "lightgreen", "lightcyan", | |
62 | "lightred", "lightmagenta", "yellow", "lightwhite" | |
984263bc | 63 | }; |
984263bc | 64 | |
6a0d37df | 65 | struct { |
f56cbf1f MD |
66 | int active_vty; |
67 | vid_info_t console_info; | |
68 | unsigned char screen_map[256]; | |
69 | int video_mode_number; | |
70 | struct video_info video_mode_info; | |
6a0d37df MD |
71 | } cur_info; |
72 | ||
73 | int hex = 0; | |
74 | int number; | |
d0a4041b SW |
75 | int g_cols; |
76 | int g_rows; | |
6a0d37df MD |
77 | int font_height; |
78 | int colors_changed; | |
79 | int video_mode_changed; | |
f56cbf1f MD |
80 | int normal_fore_color, normal_back_color; |
81 | int revers_fore_color, revers_back_color; | |
6a0d37df MD |
82 | char letter; |
83 | struct vid_info info; | |
84 | struct video_info new_mode_info; | |
85 | ||
86 | ||
87 | /* | |
88 | * Initialize revert data. | |
89 | * | |
90 | * NOTE: the following parameters are not yet saved/restored: | |
91 | * | |
92 | * screen saver timeout | |
93 | * cursor type | |
94 | * mouse character and mouse show/hide state | |
95 | * vty switching on/off state | |
96 | * history buffer size | |
97 | * history contents | |
98 | * font maps | |
99 | */ | |
100 | ||
f56cbf1f MD |
101 | static void |
102 | init(void) | |
6a0d37df | 103 | { |
f56cbf1f MD |
104 | if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) == -1) |
105 | errc(1, errno, "getting active vty"); | |
106 | ||
107 | cur_info.console_info.size = sizeof(cur_info.console_info); | |
6a0d37df | 108 | |
f56cbf1f MD |
109 | if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1) |
110 | errc(1, errno, "getting console information"); | |
6a0d37df | 111 | |
f56cbf1f MD |
112 | if (ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1) |
113 | errc(1, errno, "getting screen map"); | |
6a0d37df | 114 | |
f56cbf1f MD |
115 | if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1) |
116 | errc(1, errno, "getting video mode number"); | |
6a0d37df | 117 | |
f56cbf1f | 118 | cur_info.video_mode_info.vi_mode = cur_info.video_mode_number; |
6a0d37df | 119 | |
f56cbf1f MD |
120 | if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1) |
121 | errc(1, errno, "getting video mode parameters"); | |
6a0d37df | 122 | |
f56cbf1f MD |
123 | normal_fore_color = cur_info.console_info.mv_norm.fore; |
124 | normal_back_color = cur_info.console_info.mv_norm.back; | |
125 | revers_fore_color = cur_info.console_info.mv_rev.fore; | |
126 | revers_back_color = cur_info.console_info.mv_rev.back; | |
6a0d37df MD |
127 | } |
128 | ||
129 | ||
130 | /* | |
131 | * If something goes wrong along the way we call revert() to go back to the | |
132 | * console state we came from (which is assumed to be working). | |
133 | * | |
134 | * NOTE: please also read the comments of init(). | |
135 | */ | |
136 | ||
f56cbf1f MD |
137 | static void |
138 | revert(void) | |
6a0d37df | 139 | { |
f56cbf1f | 140 | int size[3]; |
6a0d37df | 141 | |
f56cbf1f | 142 | ioctl(0, VT_ACTIVATE, (caddr_t) (long) cur_info.active_vty); |
6a0d37df | 143 | |
f56cbf1f MD |
144 | fprintf(stderr, "\e[=%dA", cur_info.console_info.mv_ovscan); |
145 | fprintf(stderr, "\e[=%dF", cur_info.console_info.mv_norm.fore); | |
146 | fprintf(stderr, "\e[=%dG", cur_info.console_info.mv_norm.back); | |
147 | fprintf(stderr, "\e[=%dH", cur_info.console_info.mv_rev.fore); | |
148 | fprintf(stderr, "\e[=%dI", cur_info.console_info.mv_rev.back); | |
6a0d37df | 149 | |
f56cbf1f | 150 | ioctl(0, PIO_SCRNMAP, &cur_info.screen_map); |
bb2c2021 | 151 | ioctl(0, CONS_SET, &cur_info.video_mode_number); |
6a0d37df | 152 | |
f56cbf1f MD |
153 | if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) { |
154 | size[0] = cur_info.video_mode_info.vi_width / 8; | |
155 | size[1] = cur_info.video_mode_info.vi_height / | |
156 | cur_info.console_info.font_size; | |
157 | size[2] = cur_info.console_info.font_size; | |
6a0d37df | 158 | |
f56cbf1f MD |
159 | ioctl(0, KDRASTER, size); |
160 | } | |
6a0d37df MD |
161 | } |
162 | ||
163 | ||
164 | /* | |
165 | * Print a short usage string describing all options, then exit. | |
166 | */ | |
984263bc MD |
167 | |
168 | static void | |
b9fdfcf1 | 169 | usage(void) |
984263bc | 170 | { |
f56cbf1f MD |
171 | fprintf(stderr, |
172 | "usage: vidcontrol [-CdLPpx] [-b color] [-c appearance]" | |
173 | " [-f [size] file]\n" | |
174 | " [-g geometry] [-h size] [-i adapter | mode]" | |
175 | " [-l screen_map]\n" | |
176 | " [-M char] [-m on | off] [-r foreground" | |
177 | " background]\n" | |
178 | " [-S on | off] [-s number] [-t N | off]" | |
179 | " [mode]\n" | |
180 | " [foreground [background]] [show]\n"); | |
181 | ||
182 | exit(1); | |
984263bc MD |
183 | } |
184 | ||
6a0d37df MD |
185 | |
186 | /* | |
187 | * Retrieve the next argument from the command line (for options that require | |
188 | * more than one argument). | |
189 | */ | |
190 | ||
f56cbf1f | 191 | static char * |
984263bc MD |
192 | nextarg(int ac, char **av, int *indp, int oc, int strict) |
193 | { | |
f56cbf1f MD |
194 | if (*indp < ac) |
195 | return(av[(*indp)++]); | |
196 | ||
197 | if (strict != 0) { | |
198 | revert(); | |
199 | errx(1, "option requires two arguments -- %c", oc); | |
200 | } | |
201 | ||
202 | return(NULL); | |
984263bc MD |
203 | } |
204 | ||
6a0d37df MD |
205 | |
206 | /* | |
207 | * Guess which file to open. Try to open each combination of a specified set | |
208 | * of file name components. | |
209 | */ | |
210 | ||
f56cbf1f MD |
211 | static FILE * |
212 | openguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name) | |
984263bc | 213 | { |
f56cbf1f MD |
214 | FILE *f; |
215 | int i, j, k, l; | |
6a0d37df | 216 | |
f56cbf1f MD |
217 | for (i = 0; a[i] != NULL; i++) { |
218 | for (j = 0; b[j] != NULL; j++) { | |
219 | for (k = 0; c[k] != NULL; k++) { | |
220 | for (l = 0; d[l] != NULL; l++) { | |
221 | asprintf(name, "%s%s%s%s", | |
222 | a[i], b[j], c[k], d[l]); | |
6a0d37df | 223 | |
f56cbf1f | 224 | f = fopen(*name, "r"); |
6a0d37df | 225 | |
f56cbf1f MD |
226 | if (f != NULL) |
227 | return (f); | |
6a0d37df | 228 | |
f56cbf1f MD |
229 | free(*name); |
230 | } | |
231 | } | |
232 | } | |
233 | } | |
6a0d37df | 234 | |
f56cbf1f | 235 | return (NULL); |
984263bc MD |
236 | } |
237 | ||
6a0d37df MD |
238 | |
239 | /* | |
240 | * Load a screenmap from a file and set it. | |
241 | */ | |
242 | ||
f56cbf1f | 243 | static void |
984263bc MD |
244 | load_scrnmap(char *filename) |
245 | { | |
f56cbf1f MD |
246 | FILE *fd; |
247 | int size; | |
248 | char *name; | |
249 | scrmap_t scrnmap; | |
250 | const char *a[] = {"", SCRNMAP_PATH, NULL}; | |
251 | const char *b[] = {filename, NULL}; | |
252 | const char *c[] = {"", ".scm", NULL}; | |
253 | const char *d[] = {"", NULL}; | |
254 | ||
255 | fd = openguess(a, b, c, d, &name); | |
256 | ||
257 | if (fd == NULL) { | |
258 | revert(); | |
259 | errx(1, "screenmap file not found"); | |
260 | } | |
261 | ||
262 | size = sizeof(scrnmap); | |
263 | ||
264 | if (decode(fd, (char *)&scrnmap, size) != size) { | |
265 | rewind(fd); | |
266 | ||
267 | if (fread(&scrnmap, 1, size, fd) != (size_t)size) { | |
268 | fclose(fd); | |
269 | revert(); | |
270 | errx(1, "bad screenmap file"); | |
271 | } | |
272 | } | |
273 | ||
274 | if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { | |
275 | revert(); | |
276 | errc(1, errno, "loading screenmap"); | |
277 | } | |
278 | ||
279 | fclose(fd); | |
984263bc MD |
280 | } |
281 | ||
6a0d37df MD |
282 | |
283 | /* | |
284 | * Set the default screenmap. | |
285 | */ | |
286 | ||
f56cbf1f | 287 | static void |
b9fdfcf1 | 288 | load_default_scrnmap(void) |
984263bc | 289 | { |
f56cbf1f MD |
290 | scrmap_t scrnmap; |
291 | int i; | |
6a0d37df | 292 | |
f56cbf1f MD |
293 | for (i = 0; i < 256; i++) |
294 | *((char*)&scrnmap + i) = i; | |
984263bc | 295 | |
f56cbf1f MD |
296 | if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { |
297 | revert(); | |
298 | errc(1, errno, "loading default screenmap"); | |
299 | } | |
984263bc MD |
300 | } |
301 | ||
6a0d37df MD |
302 | |
303 | /* | |
304 | * Print the current screenmap to stdout. | |
305 | */ | |
306 | ||
f56cbf1f | 307 | static void |
b9fdfcf1 | 308 | print_scrnmap(void) |
984263bc | 309 | { |
f56cbf1f MD |
310 | unsigned char map[256]; |
311 | size_t i; | |
984263bc | 312 | |
f56cbf1f MD |
313 | if (ioctl(0, GIO_SCRNMAP, &map) == -1) { |
314 | revert(); | |
315 | errc(1, errno, "getting screenmap"); | |
316 | } | |
984263bc | 317 | |
f56cbf1f MD |
318 | for (i=0; i<sizeof(map); i++) { |
319 | if (i > 0 && i % 16 == 0) | |
320 | fprintf(stdout, "\n"); | |
6a0d37df | 321 | |
3641b7ca | 322 | if (hex != 0) |
f56cbf1f MD |
323 | fprintf(stdout, " %02x", map[i]); |
324 | else | |
325 | fprintf(stdout, " %03d", map[i]); | |
326 | } | |
6a0d37df | 327 | |
f56cbf1f | 328 | fprintf(stdout, "\n"); |
984263bc MD |
329 | } |
330 | ||
6a0d37df MD |
331 | |
332 | /* | |
333 | * Determine a file's size. | |
334 | */ | |
335 | ||
f56cbf1f | 336 | static int |
984263bc MD |
337 | fsize(FILE *file) |
338 | { | |
f56cbf1f | 339 | struct stat sb; |
984263bc | 340 | |
f56cbf1f MD |
341 | if (fstat(fileno(file), &sb) == 0) |
342 | return sb.st_size; | |
343 | else | |
344 | return -1; | |
984263bc MD |
345 | } |
346 | ||
6a0d37df MD |
347 | |
348 | /* | |
349 | * Load a font from file and set it. | |
350 | */ | |
984263bc | 351 | |
f56cbf1f | 352 | static void |
984263bc MD |
353 | load_font(char *type, char *filename) |
354 | { | |
f56cbf1f MD |
355 | FILE *fd; |
356 | int h, i, size, w; | |
357 | unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ | |
358 | char *name, *fontmap, size_sufx[6]; | |
359 | const char *a[] = {"", FONT_PATH, NULL}; | |
360 | const char *b[] = {filename, NULL}; | |
361 | const char *c[] = {"", size_sufx, NULL}; | |
362 | const char *d[] = {"", ".fnt", NULL}; | |
363 | vid_info_t vinfo; | |
364 | ||
365 | struct sizeinfo { | |
366 | int w; | |
367 | int h; | |
368 | unsigned long io; | |
369 | } sizes[] = {{8, 16, PIO_FONT8x16}, | |
370 | {8, 14, PIO_FONT8x14}, | |
371 | {8, 8, PIO_FONT8x8}, | |
372 | {0, 0, 0}}; | |
373 | ||
374 | vinfo.size = sizeof(vinfo); | |
375 | ||
376 | if (ioctl(0, CONS_GETINFO, &vinfo) == -1) { | |
377 | revert(); | |
378 | errc(1, errno, "obtaining current video mode parameters"); | |
984263bc MD |
379 | } |
380 | ||
27d8554b | 381 | snprintf(size_sufx, sizeof(size_sufx), "-8x%hu", vinfo.font_size); |
f56cbf1f MD |
382 | |
383 | fd = openguess(a, b, c, d, &name); | |
384 | ||
385 | if (fd == NULL) { | |
386 | revert(); | |
387 | errx(1, "%s: can't load font file", filename); | |
388 | } | |
389 | ||
390 | if (type != NULL) { | |
391 | size = 0; | |
392 | if (sscanf(type, "%dx%d", &w, &h) == 2) { | |
393 | for (i = 0; sizes[i].w != 0; i++) { | |
394 | if (sizes[i].w == w && sizes[i].h == h) { | |
395 | size = DATASIZE(sizes[i]); | |
396 | io = sizes[i].io; | |
397 | font_height = sizes[i].h; | |
398 | } | |
399 | } | |
400 | } | |
401 | if (size == 0) { | |
402 | fclose(fd); | |
403 | revert(); | |
404 | errx(1, "%s: bad font size specification", type); | |
405 | } | |
406 | } else { | |
407 | /* Apply heuristics */ | |
408 | ||
409 | int j; | |
410 | int dsize[2]; | |
411 | ||
412 | size = DATASIZE(sizes[0]); | |
413 | fontmap = (char*) malloc(size); | |
414 | dsize[0] = decode(fd, fontmap, size); | |
415 | dsize[1] = fsize(fd); | |
416 | free(fontmap); | |
417 | ||
418 | size = 0; | |
419 | for (j = 0; j < 2; j++) { | |
420 | for (i = 0; sizes[i].w != 0; i++) { | |
421 | if (DATASIZE(sizes[i]) == dsize[j]) { | |
422 | size = dsize[j]; | |
423 | io = sizes[i].io; | |
424 | font_height = sizes[i].h; | |
425 | j = 2; /* XXX */ | |
426 | break; | |
427 | } | |
428 | } | |
429 | } | |
430 | ||
431 | if (size == 0) { | |
432 | fclose(fd); | |
433 | revert(); | |
434 | errx(1, "%s: can't guess font size", filename); | |
435 | } | |
436 | ||
437 | rewind(fd); | |
438 | } | |
439 | ||
440 | fontmap = (char*) malloc(size); | |
441 | ||
442 | if (decode(fd, fontmap, size) != size) { | |
443 | rewind(fd); | |
444 | if (fsize(fd) != size || | |
445 | fread(fontmap, 1, size, fd) != (size_t)size) { | |
446 | fclose(fd); | |
447 | free(fontmap); | |
448 | revert(); | |
449 | errx(1, "%s: bad font file", filename); | |
450 | } | |
451 | } | |
452 | ||
453 | if (ioctl(0, io, fontmap) == -1) { | |
454 | revert(); | |
455 | errc(1, errno, "loading font"); | |
456 | } | |
457 | ||
458 | fclose(fd); | |
459 | free(fontmap); | |
984263bc MD |
460 | } |
461 | ||
6a0d37df MD |
462 | |
463 | /* | |
464 | * Set the timeout for the screensaver. | |
465 | */ | |
466 | ||
f56cbf1f | 467 | static void |
984263bc MD |
468 | set_screensaver_timeout(char *arg) |
469 | { | |
f56cbf1f | 470 | int nsec; |
6a0d37df | 471 | |
f56cbf1f MD |
472 | if (!strcmp(arg, "off")) { |
473 | nsec = 0; | |
474 | } else { | |
475 | nsec = atoi(arg); | |
6a0d37df | 476 | |
f56cbf1f MD |
477 | if ((*arg == '\0') || (nsec < 1)) { |
478 | revert(); | |
479 | errx(1, "argument must be a positive number"); | |
480 | } | |
481 | } | |
6a0d37df | 482 | |
f56cbf1f MD |
483 | if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) { |
484 | revert(); | |
485 | errc(1, errno, "setting screensaver period"); | |
486 | } | |
984263bc MD |
487 | } |
488 | ||
6a0d37df MD |
489 | |
490 | /* | |
491 | * Set the cursor's shape/type. | |
492 | */ | |
493 | ||
f56cbf1f | 494 | static void |
6a0d37df | 495 | set_cursor_type(char *appearance) |
984263bc | 496 | { |
f56cbf1f MD |
497 | int type; |
498 | ||
499 | if (!strcmp(appearance, "normal")) | |
500 | type = 0; | |
501 | else if (!strcmp(appearance, "blink")) | |
502 | type = 1; | |
503 | else if (!strcmp(appearance, "destructive")) | |
504 | type = 3; | |
505 | else { | |
506 | revert(); | |
507 | errx(1, "argument to -c must be normal, blink or destructive"); | |
508 | } | |
509 | ||
510 | if (ioctl(0, CONS_CURSORTYPE, &type) == -1) { | |
511 | revert(); | |
512 | errc(1, errno, "setting cursor type"); | |
513 | } | |
984263bc MD |
514 | } |
515 | ||
6a0d37df MD |
516 | |
517 | /* | |
518 | * Set the video mode. | |
519 | */ | |
520 | ||
f56cbf1f MD |
521 | static void |
522 | video_mode(int argc, char **argv, int *mode_index) | |
984263bc | 523 | { |
f56cbf1f MD |
524 | static struct { |
525 | const char *name; | |
f56cbf1f | 526 | unsigned long mode_num; |
bb2c2021 SW |
527 | } modes[] = {{ "80x25", M_VGA_C80x25 }, |
528 | { "80x30", M_VGA_C80x30 }, | |
529 | { "80x43", M_ENH_C80x43 }, | |
530 | { "80x50", M_VGA_C80x50 }, | |
531 | { "80x60", M_VGA_C80x60 }, | |
bb2c2021 SW |
532 | { "VGA_40x25", M_VGA_C40x25 }, |
533 | { "VGA_80x25", M_VGA_C80x25 }, | |
534 | { "VGA_80x30", M_VGA_C80x30 }, | |
535 | { "VGA_80x50", M_VGA_C80x50 }, | |
536 | { "VGA_80x60", M_VGA_C80x60 }, | |
984263bc | 537 | #ifdef SW_VGA_C90x25 |
bb2c2021 SW |
538 | { "VGA_90x25", M_VGA_C90x25 }, |
539 | { "VGA_90x30", M_VGA_C90x30 }, | |
540 | { "VGA_90x43", M_VGA_C90x43 }, | |
541 | { "VGA_90x50", M_VGA_C90x50 }, | |
542 | { "VGA_90x60", M_VGA_C90x60 }, | |
984263bc | 543 | #endif |
bb2c2021 SW |
544 | { "VGA_320x200", M_CG320 }, |
545 | { "EGA_80x25", M_ENH_C80x25 }, | |
546 | { "EGA_80x43", M_ENH_C80x43 }, | |
3641b7ca | 547 | { NULL, 0 }, |
f56cbf1f MD |
548 | }; |
549 | ||
550 | int new_mode_num = 0; | |
f56cbf1f MD |
551 | int size[3]; |
552 | int i; | |
553 | ||
554 | /* | |
555 | * Parse the video mode argument... | |
556 | */ | |
557 | ||
558 | if (*mode_index < argc) { | |
559 | if (!strncmp(argv[*mode_index], "MODE_", 5)) { | |
222a27c4 | 560 | if (!isdigit(argv[*mode_index][5])) |
f56cbf1f MD |
561 | errx(1, "invalid video mode number"); |
562 | ||
563 | new_mode_num = atoi(&argv[*mode_index][5]); | |
564 | } else { | |
565 | for (i = 0; modes[i].name != NULL; ++i) { | |
566 | if (!strcmp(argv[*mode_index], modes[i].name)) { | |
f56cbf1f MD |
567 | new_mode_num = modes[i].mode_num; |
568 | break; | |
569 | } | |
570 | } | |
571 | ||
572 | if (modes[i].name == NULL) | |
573 | errx(1, "invalid video mode name"); | |
574 | } | |
575 | ||
576 | /* | |
577 | * Collect enough information about the new video mode... | |
578 | */ | |
579 | ||
580 | new_mode_info.vi_mode = new_mode_num; | |
581 | ||
582 | if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) { | |
583 | revert(); | |
584 | errc(1, errno, "obtaining new video mode parameters"); | |
585 | } | |
586 | ||
f56cbf1f MD |
587 | /* |
588 | * Try setting the new mode. | |
589 | */ | |
590 | ||
bb2c2021 | 591 | if (ioctl(0, CONS_SET, &new_mode_num) == -1) { |
f56cbf1f MD |
592 | revert(); |
593 | errc(1, errno, "setting video mode"); | |
594 | } | |
595 | ||
596 | /* | |
597 | * For raster modes it's not enough to just set the mode. | |
598 | * We also need to explicitly set the raster mode. | |
599 | */ | |
600 | ||
601 | if (new_mode_info.vi_flags & V_INFO_GRAPHICS) { | |
602 | /* font size */ | |
603 | ||
604 | if (font_height == 0) | |
605 | font_height = cur_info.console_info.font_size; | |
606 | ||
607 | size[2] = font_height; | |
608 | ||
609 | /* adjust columns */ | |
610 | ||
d0a4041b SW |
611 | if ((g_cols * 8 > new_mode_info.vi_width) || |
612 | (g_cols <= 0)) { | |
f56cbf1f MD |
613 | size[0] = new_mode_info.vi_width / 8; |
614 | } else { | |
d0a4041b | 615 | size[0] = g_cols; |
f56cbf1f MD |
616 | } |
617 | ||
618 | /* adjust rows */ | |
619 | ||
d0a4041b SW |
620 | if ((g_rows * font_height > new_mode_info.vi_height) || |
621 | (g_rows <= 0)) { | |
f56cbf1f MD |
622 | size[1] = new_mode_info.vi_height / |
623 | font_height; | |
624 | } else { | |
d0a4041b | 625 | size[1] = g_rows; |
f56cbf1f MD |
626 | } |
627 | ||
628 | /* set raster mode */ | |
629 | ||
630 | if (ioctl(0, KDRASTER, size)) { | |
631 | revert(); | |
632 | errc(1, errno, "activating raster display"); | |
633 | } | |
634 | } | |
635 | ||
636 | video_mode_changed = 1; | |
637 | ||
638 | (*mode_index)++; | |
639 | } | |
984263bc MD |
640 | } |
641 | ||
6a0d37df MD |
642 | |
643 | /* | |
644 | * Return the number for a specified color name. | |
645 | */ | |
646 | ||
f56cbf1f | 647 | static int |
984263bc MD |
648 | get_color_number(char *color) |
649 | { | |
f56cbf1f | 650 | int i; |
984263bc | 651 | |
f56cbf1f MD |
652 | for (i=0; i<16; i++) { |
653 | if (!strcmp(color, legal_colors[i])) | |
654 | return i; | |
655 | } | |
656 | return -1; | |
984263bc MD |
657 | } |
658 | ||
6a0d37df MD |
659 | |
660 | /* | |
661 | * Get normal text and background colors. | |
662 | */ | |
663 | ||
f56cbf1f MD |
664 | static void |
665 | get_normal_colors(int argc, char **argv, int *color_index) | |
984263bc | 666 | { |
f56cbf1f | 667 | int color; |
6a0d37df | 668 | |
f56cbf1f MD |
669 | if (*color_index < argc && |
670 | (color = get_color_number(argv[*color_index])) != -1) { | |
671 | (*color_index)++; | |
672 | normal_fore_color = color; | |
673 | colors_changed = 1; | |
6a0d37df | 674 | |
f56cbf1f MD |
675 | if (*color_index < argc && |
676 | (color = get_color_number(argv[*color_index])) != -1) { | |
677 | (*color_index)++; | |
678 | normal_back_color = color; | |
679 | } | |
680 | } | |
984263bc MD |
681 | } |
682 | ||
6a0d37df MD |
683 | |
684 | /* | |
685 | * Get reverse text and background colors. | |
686 | */ | |
687 | ||
f56cbf1f MD |
688 | static void |
689 | get_reverse_colors(int argc, char **argv, int *color_index) | |
984263bc | 690 | { |
f56cbf1f | 691 | int color; |
6a0d37df | 692 | |
f56cbf1f MD |
693 | if ((color = get_color_number(argv[*(color_index)-1])) != -1) { |
694 | revers_fore_color = color; | |
695 | colors_changed = 1; | |
696 | ||
697 | if (*color_index < argc && | |
698 | (color = get_color_number(argv[*color_index])) != -1) { | |
699 | (*color_index)++; | |
700 | revers_back_color = color; | |
701 | } | |
702 | } | |
984263bc MD |
703 | } |
704 | ||
6a0d37df MD |
705 | |
706 | /* | |
707 | * Set normal and reverse foreground and background colors. | |
708 | */ | |
709 | ||
f56cbf1f MD |
710 | static void |
711 | set_colors(void) | |
6a0d37df | 712 | { |
f56cbf1f MD |
713 | fprintf(stderr, "\e[=%dF", normal_fore_color); |
714 | fprintf(stderr, "\e[=%dG", normal_back_color); | |
715 | fprintf(stderr, "\e[=%dH", revers_fore_color); | |
716 | fprintf(stderr, "\e[=%dI", revers_back_color); | |
6a0d37df MD |
717 | } |
718 | ||
719 | ||
720 | /* | |
721 | * Switch to virtual terminal #arg. | |
722 | */ | |
723 | ||
f56cbf1f | 724 | static void |
984263bc MD |
725 | set_console(char *arg) |
726 | { | |
f56cbf1f MD |
727 | int n; |
728 | ||
729 | if(!arg || strspn(arg,"0123456789") != strlen(arg)) { | |
730 | revert(); | |
731 | errx(1, "bad console number"); | |
732 | } | |
733 | ||
734 | n = atoi(arg); | |
735 | ||
736 | if (n < 1 || n > 16) { | |
737 | revert(); | |
738 | errx(1, "console number out of range"); | |
739 | } else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) { | |
740 | revert(); | |
741 | errc(1, errno, "switching vty"); | |
742 | } | |
6a0d37df | 743 | } |
984263bc | 744 | |
984263bc | 745 | |
6a0d37df MD |
746 | /* |
747 | * Sets the border color. | |
748 | */ | |
984263bc | 749 | |
f56cbf1f | 750 | static void |
984263bc MD |
751 | set_border_color(char *arg) |
752 | { | |
f56cbf1f | 753 | int color; |
984263bc | 754 | |
f56cbf1f MD |
755 | if ((color = get_color_number(arg)) != -1) |
756 | fprintf(stderr, "\e[=%dA", color); | |
757 | else | |
758 | usage(); | |
984263bc MD |
759 | } |
760 | ||
6a0d37df | 761 | |
f56cbf1f | 762 | static void |
984263bc MD |
763 | set_mouse_char(char *arg) |
764 | { | |
f56cbf1f MD |
765 | struct mouse_info mouse; |
766 | long l; | |
984263bc | 767 | |
f56cbf1f | 768 | l = strtol(arg, NULL, 0); |
6a0d37df | 769 | |
f56cbf1f MD |
770 | if ((l < 0) || (l > UCHAR_MAX)) { |
771 | revert(); | |
772 | errx(1, "argument to -M must be 0 through %d", UCHAR_MAX); | |
773 | } | |
6a0d37df | 774 | |
f56cbf1f MD |
775 | mouse.operation = MOUSE_MOUSECHAR; |
776 | mouse.u.mouse_char = (int)l; | |
6a0d37df | 777 | |
f56cbf1f MD |
778 | if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { |
779 | revert(); | |
780 | errc(1, errno, "setting mouse character"); | |
781 | } | |
984263bc MD |
782 | } |
783 | ||
6a0d37df MD |
784 | |
785 | /* | |
786 | * Show/hide the mouse. | |
787 | */ | |
788 | ||
f56cbf1f | 789 | static void |
984263bc MD |
790 | set_mouse(char *arg) |
791 | { | |
f56cbf1f MD |
792 | struct mouse_info mouse; |
793 | ||
794 | if (!strcmp(arg, "on")) { | |
795 | mouse.operation = MOUSE_SHOW; | |
796 | } else if (!strcmp(arg, "off")) { | |
797 | mouse.operation = MOUSE_HIDE; | |
798 | } else { | |
799 | revert(); | |
800 | errx(1, "argument to -m must be either on or off"); | |
801 | } | |
7782d597 | 802 | ioctl(0, CONS_MOUSECTL, &mouse); |
984263bc MD |
803 | } |
804 | ||
6a0d37df | 805 | |
f56cbf1f | 806 | static void |
984263bc MD |
807 | set_lockswitch(char *arg) |
808 | { | |
f56cbf1f MD |
809 | int data; |
810 | ||
811 | if (!strcmp(arg, "off")) { | |
812 | data = 0x01; | |
813 | } else if (!strcmp(arg, "on")) { | |
814 | data = 0x02; | |
815 | } else { | |
816 | revert(); | |
817 | errx(1, "argument to -S must be either on or off"); | |
818 | } | |
819 | ||
820 | if (ioctl(0, VT_LOCKSWITCH, &data) == -1) { | |
821 | revert(); | |
822 | errc(1, errno, "turning %s vty switching", | |
823 | data == 0x01 ? "off" : "on"); | |
824 | } | |
984263bc MD |
825 | } |
826 | ||
6a0d37df MD |
827 | |
828 | /* | |
829 | * Return the adapter name for a specified type. | |
830 | */ | |
831 | ||
f56cbf1f MD |
832 | static const char * |
833 | adapter_name(int type) | |
984263bc | 834 | { |
f56cbf1f MD |
835 | static struct { |
836 | int type; | |
837 | const char *name; | |
838 | } names[] = {{ KD_MONO, "MDA" }, | |
839 | { KD_HERCULES, "Hercules" }, | |
840 | { KD_CGA, "CGA" }, | |
841 | { KD_EGA, "EGA" }, | |
842 | { KD_VGA, "VGA" }, | |
f56cbf1f MD |
843 | { KD_TGA, "TGA" }, |
844 | { -1, "Unknown" }, | |
845 | }; | |
846 | ||
847 | int i; | |
848 | ||
849 | for (i = 0; names[i].type != -1; ++i) { | |
850 | if (names[i].type == type) | |
851 | break; | |
852 | } | |
853 | ||
854 | return names[i].name; | |
984263bc MD |
855 | } |
856 | ||
6a0d37df MD |
857 | |
858 | /* | |
859 | * Show graphics adapter information. | |
860 | */ | |
861 | ||
f56cbf1f | 862 | static void |
984263bc MD |
863 | show_adapter_info(void) |
864 | { | |
f56cbf1f MD |
865 | struct video_adapter_info ad; |
866 | ||
867 | ad.va_index = 0; | |
868 | ||
869 | if (ioctl(0, CONS_ADPINFO, &ad) == -1) { | |
870 | revert(); | |
871 | errc(1, errno, "obtaining adapter information"); | |
872 | } | |
873 | ||
874 | printf("fb%d:\n", ad.va_index); | |
d0a4041b | 875 | printf(" %.*s%d, type:%s (%d), flags:0x%x\n", |
f56cbf1f | 876 | (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, |
f56cbf1f MD |
877 | adapter_name(ad.va_type), ad.va_type, ad.va_flags); |
878 | printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", | |
879 | ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); | |
0fbd9725 | 880 | printf(" frame buffer window:0x%x, buffer size:0x%zx\n", |
f56cbf1f | 881 | ad.va_window, ad.va_buffer_size); |
0fbd9725 | 882 | printf(" window size:0x%zx, origin:0x%x\n", |
f56cbf1f MD |
883 | ad.va_window_size, ad.va_window_orig); |
884 | printf(" display start address (%d, %d), scan line width:%d\n", | |
885 | ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); | |
886 | printf(" reserved:0x%x\n", ad.va_unused0); | |
6a0d37df | 887 | } |
984263bc | 888 | |
984263bc | 889 | |
6a0d37df MD |
890 | /* |
891 | * Show video mode information. | |
892 | */ | |
984263bc | 893 | |
f56cbf1f | 894 | static void |
984263bc MD |
895 | show_mode_info(void) |
896 | { | |
f56cbf1f MD |
897 | struct video_info vinfo; |
898 | char buf[80]; | |
899 | int mode; | |
900 | int c; | |
901 | ||
902 | printf(" mode# flags type size " | |
903 | "font window linear buffer\n"); | |
904 | printf("---------------------------------------" | |
905 | "---------------------------------------\n"); | |
906 | ||
d0a4041b | 907 | for (mode = 0; mode <= M_MCA_MODE; ++mode) { |
f56cbf1f MD |
908 | vinfo.vi_mode = mode; |
909 | ||
910 | if (ioctl(0, CONS_MODEINFO, &vinfo)) | |
911 | continue; | |
912 | if (vinfo.vi_mode != mode) | |
913 | continue; | |
914 | ||
915 | printf("%3d (0x%03x)", mode, mode); | |
916 | printf(" 0x%08x", vinfo.vi_flags); | |
917 | ||
918 | if (vinfo.vi_flags & V_INFO_GRAPHICS) { | |
919 | c = 'G'; | |
920 | ||
921 | snprintf(buf, sizeof(buf), "%dx%dx%d %d", | |
922 | vinfo.vi_width, vinfo.vi_height, | |
923 | vinfo.vi_depth, vinfo.vi_planes); | |
924 | } else { | |
925 | c = 'T'; | |
926 | ||
927 | snprintf(buf, sizeof(buf), "%dx%d", | |
928 | vinfo.vi_width, vinfo.vi_height); | |
929 | } | |
930 | ||
931 | printf(" %c %-15s", c, buf); | |
932 | snprintf(buf, sizeof(buf), "%dx%d", | |
933 | vinfo.vi_cwidth, vinfo.vi_cheight); | |
934 | printf(" %-5s", buf); | |
935 | printf(" 0x%05x %2dk %2dk", | |
936 | vinfo.vi_window, (int)vinfo.vi_window_size / 1024, | |
937 | (int)vinfo.vi_window_gran/1024); | |
938 | printf(" 0x%08x %dk\n", | |
939 | vinfo.vi_buffer, (int)vinfo.vi_buffer_size / 1024); | |
940 | } | |
984263bc MD |
941 | } |
942 | ||
6a0d37df | 943 | |
f56cbf1f | 944 | static void |
984263bc MD |
945 | show_info(char *arg) |
946 | { | |
f56cbf1f MD |
947 | if (!strcmp(arg, "adapter")) { |
948 | show_adapter_info(); | |
949 | } else if (!strcmp(arg, "mode")) { | |
950 | show_mode_info(); | |
951 | } else { | |
952 | revert(); | |
953 | errx(1, "argument to -i must be either adapter or mode"); | |
954 | } | |
984263bc MD |
955 | } |
956 | ||
6a0d37df | 957 | |
f56cbf1f | 958 | static void |
b9fdfcf1 | 959 | test_frame(void) |
984263bc | 960 | { |
f56cbf1f | 961 | int i; |
6a0d37df | 962 | |
f56cbf1f | 963 | fprintf(stdout, "\e[=0G\n\n"); |
6a0d37df | 964 | |
f56cbf1f MD |
965 | for (i = 0; i < 8; i++) { |
966 | fprintf(stdout, "\e[=15F\e[=0G %2d \e[=%dF%-16s" | |
967 | "\e[=15F\e[=0G %2d \e[=%dF%-16s " | |
968 | "\e[=15F %2d \e[=%dGBACKGROUND\e[=0G\n", | |
969 | i, i, legal_colors[i], i+8, i+8, | |
970 | legal_colors[i+8], i, i); | |
971 | } | |
6a0d37df | 972 | |
f56cbf1f MD |
973 | fprintf(stdout, "\e[=%dF\e[=%dG\e[=%dH\e[=%dI\n", |
974 | info.mv_norm.fore, info.mv_norm.back, | |
975 | info.mv_rev.fore, info.mv_rev.back); | |
984263bc MD |
976 | } |
977 | ||
6a0d37df | 978 | |
984263bc MD |
979 | /* |
980 | * Snapshot the video memory of that terminal, using the CONS_SCRSHOT | |
981 | * ioctl, and writes the results to stdout either in the special | |
982 | * binary format (see manual page for details), or in the plain | |
983 | * text format. | |
984 | */ | |
6a0d37df | 985 | |
f56cbf1f | 986 | static void |
984263bc MD |
987 | dump_screen(int mode) |
988 | { | |
f56cbf1f MD |
989 | scrshot_t shot; |
990 | vid_info_t vinfo; | |
984263bc | 991 | |
f56cbf1f | 992 | vinfo.size = sizeof(vinfo); |
984263bc | 993 | |
f56cbf1f MD |
994 | if (ioctl(0, CONS_GETINFO, &vinfo) == -1) { |
995 | revert(); | |
996 | errc(1, errno, "obtaining current video mode parameters"); | |
997 | } | |
984263bc | 998 | |
f56cbf1f | 999 | shot.buf = alloca(vinfo.mv_csz * vinfo.mv_rsz * sizeof(u_int16_t)); |
6a0d37df | 1000 | |
f56cbf1f MD |
1001 | if (shot.buf == NULL) { |
1002 | revert(); | |
1003 | errx(1, "failed to allocate memory for dump"); | |
1004 | } | |
6a0d37df | 1005 | |
f56cbf1f MD |
1006 | shot.xsize = vinfo.mv_csz; |
1007 | shot.ysize = vinfo.mv_rsz; | |
6a0d37df | 1008 | |
f56cbf1f MD |
1009 | if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { |
1010 | revert(); | |
1011 | errc(1, errno, "dumping screen"); | |
1012 | } | |
984263bc | 1013 | |
f56cbf1f MD |
1014 | if (mode == DUMP_RAW) { |
1015 | printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, | |
1016 | shot.xsize, shot.ysize); | |
6a0d37df | 1017 | |
f56cbf1f | 1018 | fflush(stdout); |
6a0d37df | 1019 | |
f56cbf1f MD |
1020 | write(STDOUT_FILENO, shot.buf, |
1021 | shot.xsize * shot.ysize * sizeof(u_int16_t)); | |
1022 | } else { | |
1023 | char *line; | |
1024 | int x, y; | |
1025 | u_int16_t ch; | |
6a0d37df | 1026 | |
f56cbf1f | 1027 | line = alloca(shot.xsize + 1); |
6a0d37df | 1028 | |
f56cbf1f MD |
1029 | if (line == NULL) { |
1030 | revert(); | |
1031 | errx(1, "failed to allocate memory for line buffer"); | |
1032 | } | |
6a0d37df | 1033 | |
f56cbf1f MD |
1034 | for (y = 0; y < shot.ysize; y++) { |
1035 | for (x = 0; x < shot.xsize; x++) { | |
1036 | ch = shot.buf[x + (y * shot.xsize)]; | |
1037 | ch &= 0xff; | |
6a0d37df | 1038 | |
f56cbf1f MD |
1039 | if (isprint(ch) == 0) |
1040 | ch = ' '; | |
6a0d37df | 1041 | |
f56cbf1f MD |
1042 | line[x] = (char)ch; |
1043 | } | |
6a0d37df | 1044 | |
f56cbf1f | 1045 | /* Trim trailing spaces */ |
6a0d37df | 1046 | |
f56cbf1f MD |
1047 | do { |
1048 | line[x--] = '\0'; | |
1049 | } while (line[x] == ' ' && x != 0); | |
6a0d37df | 1050 | |
f56cbf1f MD |
1051 | puts(line); |
1052 | } | |
6a0d37df | 1053 | |
f56cbf1f MD |
1054 | fflush(stdout); |
1055 | } | |
984263bc MD |
1056 | } |
1057 | ||
6a0d37df MD |
1058 | |
1059 | /* | |
1060 | * Set the console history buffer size. | |
1061 | */ | |
1062 | ||
f56cbf1f | 1063 | static void |
984263bc MD |
1064 | set_history(char *opt) |
1065 | { | |
f56cbf1f | 1066 | int size; |
984263bc | 1067 | |
f56cbf1f | 1068 | size = atoi(opt); |
6a0d37df | 1069 | |
f56cbf1f MD |
1070 | if ((*opt == '\0') || size < 0) { |
1071 | revert(); | |
1072 | errx(1, "argument must be a positive number"); | |
1073 | } | |
6a0d37df | 1074 | |
f56cbf1f MD |
1075 | if (ioctl(0, CONS_HISTORY, &size) == -1) { |
1076 | revert(); | |
1077 | errc(1, errno, "setting history buffer size"); | |
1078 | } | |
984263bc MD |
1079 | } |
1080 | ||
6a0d37df MD |
1081 | |
1082 | /* | |
1083 | * Clear the console history buffer. | |
1084 | */ | |
1085 | ||
f56cbf1f | 1086 | static void |
b9fdfcf1 | 1087 | clear_history(void) |
984263bc | 1088 | { |
f56cbf1f MD |
1089 | if (ioctl(0, CONS_CLRHIST) == -1) { |
1090 | revert(); | |
1091 | errc(1, errno, "clearing history buffer"); | |
1092 | } | |
984263bc MD |
1093 | } |
1094 | ||
6a0d37df | 1095 | |
984263bc MD |
1096 | int |
1097 | main(int argc, char **argv) | |
1098 | { | |
f56cbf1f MD |
1099 | char *font, *type; |
1100 | int opt; | |
1101 | ||
1102 | if (argc == 1) | |
1103 | usage(); | |
1104 | ||
1105 | init(); | |
1106 | ||
1107 | info.size = sizeof(info); | |
1108 | ||
1109 | if (ioctl(0, CONS_GETINFO, &info) == -1) | |
1110 | err(1, "must be on a virtual console"); | |
1111 | ||
1112 | while((opt = getopt(argc, argv, "b:Cc:df:g:h:i:l:LM:m:pPr:S:s:t:x")) != -1) { | |
1113 | switch(opt) { | |
1114 | case 'b': | |
1115 | set_border_color(optarg); | |
1116 | break; | |
1117 | case 'C': | |
1118 | clear_history(); | |
1119 | break; | |
1120 | case 'c': | |
1121 | set_cursor_type(optarg); | |
1122 | break; | |
1123 | case 'd': | |
1124 | print_scrnmap(); | |
1125 | break; | |
1126 | case 'f': | |
1127 | type = optarg; | |
1128 | font = nextarg(argc, argv, &optind, 'f', 0); | |
1129 | ||
1130 | if (font == NULL) { | |
1131 | type = NULL; | |
1132 | font = optarg; | |
1133 | } | |
1134 | ||
1135 | load_font(type, font); | |
1136 | break; | |
1137 | case 'g': | |
d0a4041b | 1138 | if (sscanf(optarg, "%dx%d", &g_cols, &g_rows) != 2) { |
f56cbf1f MD |
1139 | revert(); |
1140 | warnx("incorrect geometry: %s", optarg); | |
1141 | usage(); | |
1142 | } | |
1143 | break; | |
1144 | case 'h': | |
1145 | set_history(optarg); | |
1146 | break; | |
1147 | case 'i': | |
1148 | show_info(optarg); | |
1149 | break; | |
1150 | case 'l': | |
1151 | load_scrnmap(optarg); | |
1152 | break; | |
1153 | case 'L': | |
1154 | load_default_scrnmap(); | |
1155 | break; | |
1156 | case 'M': | |
1157 | set_mouse_char(optarg); | |
1158 | break; | |
1159 | case 'm': | |
1160 | set_mouse(optarg); | |
1161 | break; | |
1162 | case 'p': | |
1163 | dump_screen(DUMP_RAW); | |
1164 | break; | |
1165 | case 'P': | |
1166 | dump_screen(DUMP_TXT); | |
1167 | break; | |
1168 | case 'r': | |
1169 | get_reverse_colors(argc, argv, &optind); | |
1170 | break; | |
1171 | case 'S': | |
1172 | set_lockswitch(optarg); | |
1173 | break; | |
1174 | case 's': | |
1175 | set_console(optarg); | |
1176 | break; | |
1177 | case 't': | |
1178 | set_screensaver_timeout(optarg); | |
1179 | break; | |
1180 | case 'x': | |
1181 | hex = 1; | |
1182 | break; | |
1183 | default: | |
1184 | usage(); | |
1185 | } | |
1186 | } | |
1187 | ||
1188 | if (optind < argc && !strcmp(argv[optind], "show")) { | |
1189 | test_frame(); | |
1190 | optind++; | |
984263bc | 1191 | } |
984263bc | 1192 | |
f56cbf1f MD |
1193 | video_mode(argc, argv, &optind); |
1194 | ||
1195 | get_normal_colors(argc, argv, &optind); | |
1196 | ||
1197 | if (colors_changed || video_mode_changed) { | |
1198 | if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) { | |
1199 | if ((normal_back_color < 8) && (revers_back_color < 8)) { | |
1200 | set_colors(); | |
1201 | } else { | |
1202 | revert(); | |
1203 | errx(1, "bg color for text modes must be < 8"); | |
1204 | } | |
1205 | } else { | |
1206 | set_colors(); | |
1207 | } | |
1208 | } | |
1209 | ||
1210 | if ((optind != argc) || (argc == 1)) | |
1211 | usage(); | |
1212 | ||
1213 | return 0; | |
6a0d37df | 1214 | } |