2 * Copyright (c) 1994-1996 Søren Schmidt
5 * Portions of this software are based in part on the work of
6 * Sascha Wildner <saw@online.de> contributed to The DragonFly Project
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer,
13 * in this position and unchanged.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $DragonFly: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.10 2005/03/02 06:08:29 joerg Exp $
35 static const char rcsid
[] =
47 #include <sys/consio.h>
48 #include <sys/errno.h>
49 #include <sys/types.h>
55 #define DATASIZE(x) ((x).w * (x).h * 256 / 8)
57 /* Screen dump modes */
58 #define DUMP_FMT_RAW 1
59 #define DUMP_FMT_TXT 2
60 /* Screen dump options */
63 /* Screen dump file format revision */
64 #define DUMP_FMT_REV 1
66 char legal_colors
[16][16] = {
67 "black", "blue", "green", "cyan",
68 "red", "magenta", "brown", "white",
69 "grey", "lightblue", "lightgreen", "lightcyan",
70 "lightred", "lightmagenta", "yellow", "lightwhite"
75 vid_info_t console_info
;
76 unsigned char screen_map
[256];
77 int video_mode_number
;
78 struct video_info video_mode_info
;
87 int video_mode_changed
;
88 int normal_fore_color
, normal_back_color
;
89 int revers_fore_color
, revers_back_color
;
92 struct video_info new_mode_info
;
96 * Initialize revert data.
98 * NOTE: the following parameters are not yet saved/restored:
100 * screen saver timeout
102 * mouse character and mouse show/hide state
103 * vty switching on/off state
104 * history buffer size
112 if (ioctl(0, VT_GETACTIVE
, &cur_info
.active_vty
) == -1)
113 errc(1, errno
, "getting active vty");
115 cur_info
.console_info
.size
= sizeof(cur_info
.console_info
);
117 if (ioctl(0, CONS_GETINFO
, &cur_info
.console_info
) == -1)
118 errc(1, errno
, "getting console information");
120 if (ioctl(0, GIO_SCRNMAP
, &cur_info
.screen_map
) == -1)
121 errc(1, errno
, "getting screen map");
123 if (ioctl(0, CONS_GET
, &cur_info
.video_mode_number
) == -1)
124 errc(1, errno
, "getting video mode number");
126 cur_info
.video_mode_info
.vi_mode
= cur_info
.video_mode_number
;
128 if (ioctl(0, CONS_MODEINFO
, &cur_info
.video_mode_info
) == -1)
129 errc(1, errno
, "getting video mode parameters");
131 normal_fore_color
= cur_info
.console_info
.mv_norm
.fore
;
132 normal_back_color
= cur_info
.console_info
.mv_norm
.back
;
133 revers_fore_color
= cur_info
.console_info
.mv_rev
.fore
;
134 revers_back_color
= cur_info
.console_info
.mv_rev
.back
;
139 * If something goes wrong along the way we call revert() to go back to the
140 * console state we came from (which is assumed to be working).
142 * NOTE: please also read the comments of init().
150 ioctl(0, VT_ACTIVATE
, cur_info
.active_vty
);
152 fprintf(stderr
, "\033[=%dA", cur_info
.console_info
.mv_ovscan
);
153 fprintf(stderr
, "\033[=%dF", cur_info
.console_info
.mv_norm
.fore
);
154 fprintf(stderr
, "\033[=%dG", cur_info
.console_info
.mv_norm
.back
);
155 fprintf(stderr
, "\033[=%dH", cur_info
.console_info
.mv_rev
.fore
);
156 fprintf(stderr
, "\033[=%dI", cur_info
.console_info
.mv_rev
.back
);
158 ioctl(0, PIO_SCRNMAP
, &cur_info
.screen_map
);
160 if (cur_info
.video_mode_number
>= M_VESA_BASE
)
161 ioctl(0, _IO('V', cur_info
.video_mode_number
- M_VESA_BASE
),
164 ioctl(0, _IO('S', cur_info
.video_mode_number
), NULL
);
166 if (cur_info
.video_mode_info
.vi_flags
& V_INFO_GRAPHICS
) {
167 size
[0] = cur_info
.video_mode_info
.vi_width
/ 8;
168 size
[1] = cur_info
.video_mode_info
.vi_height
/
169 cur_info
.console_info
.font_size
;
170 size
[2] = cur_info
.console_info
.font_size
;
172 ioctl(0, KDRASTER
, size
);
178 * Print a short usage string describing all options, then exit.
184 fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n",
185 "usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]",
186 " [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]",
187 " [-M char] [-m on | off] [-r foreground background]",
188 " [-S on | off] [-s number] [-t N | off] [mode]",
189 " [foreground [background]] [show]");
195 * Retrieve the next argument from the command line (for options that require
196 * more than one argument).
200 nextarg(int ac
, char **av
, int *indp
, int oc
, int strict
)
203 return(av
[(*indp
)++]);
207 errx(1, "option requires two arguments -- %c", oc
);
215 * Guess which file to open. Try to open each combination of a specified set
216 * of file name components.
220 openguess(const char *a
[], const char *b
[], const char *c
[], const char *d
[], char **name
)
225 for (i
= 0; a
[i
] != NULL
; i
++) {
226 for (j
= 0; b
[j
] != NULL
; j
++) {
227 for (k
= 0; c
[k
] != NULL
; k
++) {
228 for (l
= 0; d
[l
] != NULL
; l
++) {
229 asprintf(name
, "%s%s%s%s",
230 a
[i
], b
[j
], c
[k
], d
[l
]);
232 f
= fopen(*name
, "r");
247 * Load a screenmap from a file and set it.
251 load_scrnmap(const char *filename
)
257 const char *a
[] = {"", SCRNMAP_PATH
, NULL
};
258 const char *b
[] = {filename
, NULL
};
259 const char *c
[] = {"", ".scm", NULL
};
260 const char *d
[] = {"", NULL
};
262 fd
= openguess(a
, b
, c
, d
, &name
);
266 errx(1, "screenmap file not found");
269 size
= sizeof(scrnmap
);
271 if (decode(fd
, (char *)&scrnmap
, size
) != size
) {
274 if (fread(&scrnmap
, 1, size
, fd
) != (size_t)size
) {
275 warnx("bad screenmap file");
278 errx(1, "bad screenmap file");
282 if (ioctl(0, PIO_SCRNMAP
, &scrnmap
) == -1) {
284 errc(1, errno
, "loading screenmap");
292 * Set the default screenmap.
296 load_default_scrnmap(void)
301 for (i
=0; i
<256; i
++)
302 *((char*)&scrnmap
+ i
) = i
;
304 if (ioctl(0, PIO_SCRNMAP
, &scrnmap
) == -1) {
306 errc(1, errno
, "loading default screenmap");
312 * Print the current screenmap to stdout.
318 unsigned char map
[256];
321 if (ioctl(0, GIO_SCRNMAP
, &map
) == -1) {
323 errc(1, errno
, "getting screenmap");
325 for (i
=0; i
<sizeof(map
); i
++) {
326 if (i
!= 0 && i
% 16 == 0)
327 fprintf(stdout
, "\n");
330 fprintf(stdout
, " %02x", map
[i
]);
332 fprintf(stdout
, " %03d", map
[i
]);
334 fprintf(stdout
, "\n");
340 * Determine a file's size.
348 if (fstat(fileno(file
), &sb
) == 0)
356 * Load a font from file and set it.
360 load_font(const char *type
, const char *filename
)
364 unsigned long io
= 0; /* silence stupid gcc(1) in the Wall mode */
365 char *name
, *fontmap
, size_sufx
[6];
366 const char *a
[] = {"", FONT_PATH
, NULL
};
367 const char *b
[] = {filename
, NULL
};
368 const char *c
[] = {"", size_sufx
, NULL
};
369 const char *d
[] = {"", ".fnt", NULL
};
376 } sizes
[] = {{8, 16, PIO_FONT8x16
},
377 {8, 14, PIO_FONT8x14
},
381 _info
.size
= sizeof(_info
);
382 if (ioctl(0, CONS_GETINFO
, &_info
) == -1) {
384 warn("failed to obtain current video mode parameters");
388 snprintf(size_sufx
, sizeof(size_sufx
), "-8x%d", _info
.font_size
);
389 fd
= openguess(a
, b
, c
, d
, &name
);
393 errx(1, "%s: can't load font file", filename
);
398 if (sscanf(type
, "%dx%d", &w
, &h
) == 2) {
399 for (i
= 0; sizes
[i
].w
!= 0; i
++) {
400 if (sizes
[i
].w
== w
&& sizes
[i
].h
== h
) {
401 size
= DATASIZE(sizes
[i
]);
403 font_height
= sizes
[i
].h
;
410 errx(1, "%s: bad font size specification", type
);
413 /* Apply heuristics */
418 size
= DATASIZE(sizes
[0]);
419 fontmap
= (char*) malloc(size
);
420 dsize
[0] = decode(fd
, fontmap
, size
);
421 dsize
[1] = fsize(fd
);
425 for (j
= 0; j
< 2; j
++) {
426 for (i
= 0; sizes
[i
].w
!= 0; i
++) {
427 if (DATASIZE(sizes
[i
]) == dsize
[j
]) {
430 font_height
= sizes
[i
].h
;
440 errx(1, "%s: can't guess font size", filename
);
446 fontmap
= (char*) malloc(size
);
448 if (decode(fd
, fontmap
, size
) != size
) {
450 if (fsize(fd
) != size
||
451 fread(fontmap
, 1, size
, fd
) != (size_t)size
) {
452 warnx("%s: bad font file", filename
);
456 errx(1, "%s: bad font file", filename
);
460 if (ioctl(0, io
, fontmap
) == -1) {
462 errc(1, errno
, "loading font");
471 * Set the timeout for the screensaver.
475 set_screensaver_timeout(char *arg
)
479 if (!strcmp(arg
, "off")) {
484 if ((*arg
== '\0') || (nsec
< 1)) {
486 errx(1, "argument must be a positive number");
490 if (ioctl(0, CONS_BLANKTIME
, &nsec
) == -1) {
492 errc(1, errno
, "setting screensaver period");
498 * Set the cursor's shape/type.
502 set_cursor_type(char *appearence
)
506 if (!strcmp(appearence
, "normal"))
508 else if (!strcmp(appearence
, "blink"))
510 else if (!strcmp(appearence
, "destructive"))
514 errx(1, "argument to -c must be normal, blink or destructive");
517 if (ioctl(0, CONS_CURSORTYPE
, &type
) == -1) {
519 errc(1, errno
, "setting cursor type");
525 * Set the video mode.
529 video_mode(int argc
, char **argv
, int *mode_index
)
534 unsigned long mode_num
;
536 { "80x25", SW_TEXT_80x25
, M_TEXT_80x25
},
537 { "80x30", SW_TEXT_80x30
, M_TEXT_80x30
},
538 { "80x43", SW_TEXT_80x43
, M_TEXT_80x43
},
539 { "80x50", SW_TEXT_80x50
, M_TEXT_80x50
},
540 { "80x60", SW_TEXT_80x60
, M_TEXT_80x60
},
541 { "132x25", SW_TEXT_132x25
, M_TEXT_132x25
},
542 { "132x30", SW_TEXT_132x30
, M_TEXT_132x30
},
543 { "132x43", SW_TEXT_132x43
, M_TEXT_132x43
},
544 { "132x50", SW_TEXT_132x50
, M_TEXT_132x50
},
545 { "132x60", SW_TEXT_132x60
, M_TEXT_132x60
},
546 { "VGA_40x25", SW_VGA_C40x25
, M_VGA_C40x25
},
547 { "VGA_80x25", SW_VGA_C80x25
, M_VGA_C80x25
},
548 { "VGA_80x30", SW_VGA_C80x30
, M_VGA_C80x30
},
549 { "VGA_80x50", SW_VGA_C80x50
, M_VGA_C80x50
},
550 { "VGA_80x60", SW_VGA_C80x60
, M_VGA_C80x60
},
552 { "VGA_90x25", SW_VGA_C90x25
, M_VGA_C90x25
},
553 { "VGA_90x30", SW_VGA_C90x30
, M_VGA_C90x30
},
554 { "VGA_90x43", SW_VGA_C90x43
, M_VGA_C90x43
},
555 { "VGA_90x50", SW_VGA_C90x50
, M_VGA_C90x50
},
556 { "VGA_90x60", SW_VGA_C90x60
, M_VGA_C90x60
},
558 { "VGA_320x200", SW_VGA_CG320
, M_CG320
},
559 { "EGA_80x25", SW_ENH_C80x25
, M_ENH_C80x25
},
560 { "EGA_80x43", SW_ENH_C80x43
, M_ENH_C80x43
},
561 { "VESA_132x25", SW_VESA_C132x25
,M_VESA_C132x25
},
562 { "VESA_132x43", SW_VESA_C132x43
,M_VESA_C132x43
},
563 { "VESA_132x50", SW_VESA_C132x50
,M_VESA_C132x50
},
564 { "VESA_132x60", SW_VESA_C132x60
,M_VESA_C132x60
},
565 { "VESA_800x600", SW_VESA_800x600
,M_VESA_800x600
},
569 int new_mode_num
= 0;
570 unsigned long mode
= 0;
576 if (ioctl(0, CONS_GET
, &cur_mode
) < 0)
577 err(1, "cannot get the current video mode");
580 * Parse the video mode argument...
583 if (*mode_index
< argc
) {
584 if (!strncmp(argv
[*mode_index
], "MODE_", 5)) {
585 if (!isdigit(argv
[*mode_index
][5]))
586 errx(1, "invalid video mode number");
588 new_mode_num
= atoi(&argv
[*mode_index
][5]);
590 for (i
= 0; modes
[i
].name
!= NULL
; ++i
) {
591 if (!strcmp(argv
[*mode_index
], modes
[i
].name
)) {
592 mode
= modes
[i
].mode
;
593 new_mode_num
= modes
[i
].mode_num
;
598 if (modes
[i
].name
== NULL
)
600 if (ioctl(0, mode
, NULL
) < 0) {
601 warn("cannot set videomode");
607 * Collect enough information about the new video mode...
610 new_mode_info
.vi_mode
= new_mode_num
;
612 if (ioctl(0, CONS_MODEINFO
, &new_mode_info
) == -1) {
614 errc(1, errno
, "obtaining new video mode parameters");
618 if (new_mode_num
>= M_VESA_BASE
)
619 mode
= _IO('V', new_mode_num
- M_VESA_BASE
);
621 mode
= _IO('S', new_mode_num
);
625 * Try setting the new mode.
628 if (ioctl(0, mode
, NULL
) == -1) {
630 errc(1, errno
, "setting video mode");
634 * For raster modes it's not enough to just set the mode.
635 * We also need to explicitly set the raster mode.
638 if (new_mode_info
.vi_flags
& V_INFO_GRAPHICS
) {
641 if (font_height
== 0)
642 font_height
= cur_info
.console_info
.font_size
;
644 size
[2] = font_height
;
648 if ((vesa_cols
* 8 > new_mode_info
.vi_width
) ||
650 size
[0] = new_mode_info
.vi_width
/ 8;
657 if ((vesa_rows
* font_height
> new_mode_info
.vi_height
) ||
659 size
[1] = new_mode_info
.vi_height
/
665 /* set raster mode */
667 if (ioctl(0, KDRASTER
, size
)) {
669 if (cur_mode
>= M_VESA_BASE
)
671 _IO('V', cur_mode
- M_VESA_BASE
),
674 ioctl(0, _IO('S', cur_mode
), NULL
);
676 warnc(ioerr
, "cannot activate raster display");
681 video_mode_changed
= 1;
690 * Return the number for a specified color name.
694 get_color_number(char *color
)
698 for (i
=0; i
<16; i
++) {
699 if (!strcmp(color
, legal_colors
[i
]))
707 * Get normal text and background colors.
711 get_normal_colors(int argc
, char **argv
, int *_index
)
715 if (*_index
< argc
&& (color
= get_color_number(argv
[*_index
])) != -1) {
717 fprintf(stderr
, "\033[=%dF", color
);
718 normal_fore_color
=color
;
721 && (color
= get_color_number(argv
[*_index
])) != -1
724 fprintf(stderr
, "\033[=%dG", color
);
725 normal_back_color
=color
;
732 * Get reverse text and background colors.
736 get_reverse_colors(int argc
, char **argv
, int *_index
)
740 if ((color
= get_color_number(argv
[*(_index
)-1])) != -1) {
741 fprintf(stderr
, "\033[=%dH", color
);
742 revers_fore_color
=color
;
745 && (color
= get_color_number(argv
[*_index
])) != -1
748 fprintf(stderr
, "\033[=%dI", color
);
749 revers_back_color
=color
;
756 * Set normal and reverse foreground and background colors.
762 fprintf(stderr
, "\033[=%dF", normal_fore_color
);
763 fprintf(stderr
, "\033[=%dG", normal_back_color
);
764 fprintf(stderr
, "\033[=%dH", revers_fore_color
);
765 fprintf(stderr
, "\033[=%dI", revers_back_color
);
770 * Switch to virtual terminal #arg.
774 set_console(char *arg
)
778 if(!arg
|| strspn(arg
,"0123456789") != strlen(arg
)) {
780 errx(1, "bad console number");
785 if (n
< 1 || n
> 16) {
787 errx(1, "console number out of range");
788 } else if (ioctl(0, VT_ACTIVATE
, n
) == -1) {
790 errc(1, errno
, "switching vty");
796 * Sets the border color.
800 set_border_color(char *arg
)
804 if ((color
= get_color_number(arg
)) != -1) {
805 fprintf(stderr
, "\033[=%dA", color
);
812 set_mouse_char(char *arg
)
814 struct mouse_info mouse
;
817 l
= strtol(arg
, NULL
, 0);
819 if ((l
< 0) || (l
> UCHAR_MAX
- 3)) {
821 warnx("argument to -M must be 0 through %d", UCHAR_MAX
- 3);
825 mouse
.operation
= MOUSE_MOUSECHAR
;
826 mouse
.u
.mouse_char
= (int)l
;
828 if (ioctl(0, CONS_MOUSECTL
, &mouse
) == -1) {
830 errc(1, errno
, "setting mouse character");
836 * Show/hide the mouse.
842 struct mouse_info mouse
;
844 if (!strcmp(arg
, "on")) {
845 mouse
.operation
= MOUSE_SHOW
;
846 } else if (!strcmp(arg
, "off")) {
847 mouse
.operation
= MOUSE_HIDE
;
850 errx(1, "argument to -m must be either on or off");
853 if (ioctl(0, CONS_MOUSECTL
, &mouse
) == -1) {
855 errc(1, errno
, "%sing the mouse",
856 mouse
.operation
== MOUSE_SHOW
? "show" : "hid");
862 set_lockswitch(char *arg
)
866 if (!strcmp(arg
, "off")) {
868 } else if (!strcmp(arg
, "on")) {
872 errx(1, "argument to -S must be either on or off");
875 if (ioctl(0, VT_LOCKSWITCH
, &data
) == -1) {
877 errc(1, errno
, "turning %s vty switching",
878 data
== 0x01 ? "off" : "on");
884 * Return the adapter name for a specified type.
888 *adapter_name(int type
)
895 { KD_HERCULES
, "Hercules" },
899 { KD_PC98
, "PC-98xx" },
906 for (i
= 0; names
[i
].type
!= -1; ++i
)
907 if (names
[i
].type
== type
)
909 return names
[i
].name
;
914 * Show graphics adapter information.
918 show_adapter_info(void)
920 struct video_adapter_info ad
;
924 if (ioctl(0, CONS_ADPINFO
, &ad
) == -1) {
926 errc(1, errno
, "obtaining adapter information");
929 printf("fb%d:\n", ad
.va_index
);
930 printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n",
931 (int)sizeof(ad
.va_name
), ad
.va_name
, ad
.va_unit
,
932 (ad
.va_flags
& V_ADP_VESA
) ? "VESA " : "",
933 adapter_name(ad
.va_type
), ad
.va_type
, ad
.va_flags
);
934 printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n",
935 ad
.va_initial_mode
, ad
.va_mode
, ad
.va_initial_bios_mode
);
936 printf(" frame buffer window:0x%zx, buffer size:0x%zx\n",
937 ad
.va_window
, ad
.va_buffer_size
);
938 printf(" window size:0x%zx, origin:0x%x\n",
939 ad
.va_window_size
, ad
.va_window_orig
);
940 printf(" display start address (%d, %d), scan line width:%d\n",
941 ad
.va_disp_start
.x
, ad
.va_disp_start
.y
, ad
.va_line_width
);
942 printf(" reserved:0x%zx\n", ad
.va_unused0
);
947 * Show video mode information.
953 struct video_info _info
;
958 printf(" mode# flags type size "
959 "font window linear buffer\n");
960 printf("---------------------------------------"
961 "---------------------------------------\n");
963 for (mode
= 0; mode
< M_VESA_MODE_MAX
; ++mode
) {
964 _info
.vi_mode
= mode
;
965 if (ioctl(0, CONS_MODEINFO
, &_info
))
967 if (_info
.vi_mode
!= mode
)
970 printf("%3d (0x%03x)", mode
, mode
);
971 printf(" 0x%08x", _info
.vi_flags
);
972 if (_info
.vi_flags
& V_INFO_GRAPHICS
) {
975 snprintf(buf
, sizeof(buf
), "%dx%dx%d %d",
976 _info
.vi_width
, _info
.vi_height
,
977 _info
.vi_depth
, _info
.vi_planes
);
981 snprintf(buf
, sizeof(buf
), "%dx%d",
982 _info
.vi_width
, _info
.vi_height
);
985 printf(" %c %-15s", c
, buf
);
986 snprintf(buf
, sizeof(buf
), "%dx%d",
987 _info
.vi_cwidth
, _info
.vi_cheight
);
988 printf(" %-5s", buf
);
989 printf(" 0x%05zx %2dk %2dk",
990 _info
.vi_window
, (int)_info
.vi_window_size
/1024,
991 (int)_info
.vi_window_gran
/1024);
992 printf(" 0x%08zx %dk\n",
993 _info
.vi_buffer
, (int)_info
.vi_buffer_size
/1024);
1001 if (!strcmp(arg
, "adapter")) {
1002 show_adapter_info();
1003 } else if (!strcmp(arg
, "mode")) {
1007 errx(1, "argument to -i must be either adapter or mode");
1015 int i
, cur_mode
, fore
;
1019 if (ioctl(0, CONS_GET
, &cur_mode
) < 0)
1020 err(1, "must be on a virtual console");
1028 fprintf(stdout
, "\033[=0G\n\n");
1029 for (i
=0; i
<8; i
++) {
1030 fprintf(stdout
, "\033[=%dF\033[=0G %2d \033[=%dF%-16s"
1031 "\033[=%dF\033[=0G %2d \033[=%dF%-16s "
1032 "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n",
1033 fore
, i
, i
, legal_colors
[i
],
1034 fore
, i
+8, i
+8, legal_colors
[i
+8],
1037 fprintf(stdout
, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n",
1038 info
.mv_norm
.fore
, info
.mv_norm
.back
,
1039 info
.mv_rev
.fore
, info
.mv_rev
.back
);
1044 * Snapshot the video memory of that terminal, using the CONS_SCRSHOT
1045 * ioctl, and writes the results to stdout either in the special
1046 * binary format (see manual page for details), or in the plain
1051 dump_screen(int mode
, int opt
)
1056 _info
.size
= sizeof(_info
);
1058 if (ioctl(0, CONS_GETINFO
, &_info
) == -1) {
1060 errc(1, errno
, "obtaining current video mode parameters");
1064 shot
.x
= shot
.y
= 0;
1065 shot
.xsize
= _info
.mv_csz
;
1066 shot
.ysize
= _info
.mv_rsz
;
1067 if (opt
== DUMP_ALL
)
1068 shot
.ysize
+= _info
.mv_hsz
;
1070 shot
.buf
= alloca(shot
.xsize
* shot
.ysize
* sizeof(u_int16_t
));
1071 if (shot
.buf
== NULL
) {
1073 errx(1, "failed to allocate memory for dump");
1076 if (ioctl(0, CONS_SCRSHOT
, &shot
) == -1) {
1078 errc(1, errno
, "dumping screen");
1081 if (mode
== DUMP_FMT_RAW
) {
1082 printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV
, 2,
1083 shot
.xsize
, shot
.ysize
);
1087 write(STDOUT_FILENO
, shot
.buf
,
1088 shot
.xsize
* shot
.ysize
* sizeof(u_int16_t
));
1094 line
= alloca(shot
.xsize
+ 1);
1098 errx(1, "failed to allocate memory for line buffer");
1101 for (y
= 0; y
< shot
.ysize
; y
++) {
1102 for (x
= 0; x
< shot
.xsize
; x
++) {
1103 ch
= shot
.buf
[x
+ (y
* shot
.xsize
)];
1106 if (isprint(ch
) == 0)
1112 /* Trim trailing spaces */
1116 } while (line
[x
] == ' ' && x
!= 0);
1127 * Set the console history buffer size.
1131 set_history(char *opt
)
1137 if ((*opt
== '\0') || size
< 0) {
1139 errx(1, "argument must be a positive number");
1142 if (ioctl(0, CONS_HISTORY
, &size
) == -1) {
1144 errc(1, errno
, "setting history buffer size");
1150 * Clear the console history buffer.
1156 if (ioctl(0, CONS_CLRHIST
) == -1) {
1158 errc(1, errno
, "clearing history buffer");
1164 main(int argc
, char **argv
)
1167 int dumpmod
, dumpopt
, opt
;
1172 info
.size
= sizeof(info
);
1174 if (ioctl(0, CONS_GETINFO
, &info
) == -1)
1175 err(1, "must be on a virtual console");
1178 while((opt
= getopt(argc
, argv
, "b:Cc:df:g:h:Hi:l:LM:m:pPr:S:s:t:x")) != -1)
1181 set_border_color(optarg
);
1187 set_cursor_type(optarg
);
1194 font
= nextarg(argc
, argv
, &optind
, 'f', 0);
1201 load_font(type
, font
);
1204 if (sscanf(optarg
, "%dx%d",
1205 &vesa_cols
, &vesa_rows
) != 2) {
1207 warnx("incorrect geometry: %s", optarg
);
1212 set_history(optarg
);
1221 load_scrnmap(optarg
);
1224 load_default_scrnmap();
1227 set_mouse_char(optarg
);
1233 dumpmod
= DUMP_FMT_RAW
;
1236 dumpmod
= DUMP_FMT_TXT
;
1239 get_reverse_colors(argc
, argv
, &optind
);
1242 set_lockswitch(optarg
);
1245 set_console(optarg
);
1248 set_screensaver_timeout(optarg
);
1258 dump_screen(dumpmod
, dumpopt
);
1259 reterr
= video_mode(argc
, argv
, &optind
);
1260 get_normal_colors(argc
, argv
, &optind
);
1262 if (optind
< argc
&& !strcmp(argv
[optind
], "show")) {
1267 video_mode(argc
, argv
, &optind
);
1269 get_normal_colors(argc
, argv
, &optind
);
1271 if (colors_changed
|| video_mode_changed
) {
1272 if (!(new_mode_info
.vi_flags
& V_INFO_GRAPHICS
)) {
1273 if ((normal_back_color
< 8) && (revers_back_color
< 8)) {
1277 errx(1, "bg color for text modes must be < 8");
1284 if ((optind
!= argc
) || (argc
== 1))