xref: /freebsd/usr.sbin/vidcontrol/vidcontrol.c (revision eba230afba4932f02a1ca44efc797cf7499a5cb0)
17363955dSSøren Schmidt /*-
21de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
31de7b4b8SPedro F. Giffuni  *
4f76b3199SUlrich Spörlein  * Copyright (c) 1994-1996 Søren Schmidt
57363955dSSøren Schmidt  * All rights reserved.
67363955dSSøren Schmidt  *
7f1121206SXin LI  * Portions of this software are based in part on the work of
8f1121206SXin LI  * Sascha Wildner <saw@online.de> contributed to The DragonFly Project
9f1121206SXin LI  *
107363955dSSøren Schmidt  * Redistribution and use in source and binary forms, with or without
117363955dSSøren Schmidt  * modification, are permitted provided that the following conditions
127363955dSSøren Schmidt  * are met:
137363955dSSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
14a926a37bSSøren Schmidt  *    notice, this list of conditions and the following disclaimer,
15a926a37bSSøren Schmidt  *    in this position and unchanged.
167363955dSSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
177363955dSSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
187363955dSSøren Schmidt  *    documentation and/or other materials provided with the distribution.
197363955dSSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
2021dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
217363955dSSøren Schmidt  *
227363955dSSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
237363955dSSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
247363955dSSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
257363955dSSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
267363955dSSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
277363955dSSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
287363955dSSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
297363955dSSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
307363955dSSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
317363955dSSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32f1121206SXin LI  *
33f1121206SXin LI  * $DragonFly: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.10 2005/03/02 06:08:29 joerg Exp $
347363955dSSøren Schmidt  */
357363955dSSøren Schmidt 
367363955dSSøren Schmidt #include <ctype.h>
379396247eSPhilippe Charnier #include <err.h>
38e2f29c6eSKazutaka YOKOTA #include <limits.h>
397363955dSSøren Schmidt #include <stdio.h>
40bfc214e3SBrian Somers #include <stdlib.h>
41bfc214e3SBrian Somers #include <string.h>
429396247eSPhilippe Charnier #include <unistd.h>
4300d25f51SPoul-Henning Kamp #include <sys/fbio.h>
4400d25f51SPoul-Henning Kamp #include <sys/consio.h>
4530bf10efSAleksandr Rybalko #include <sys/endian.h>
467363955dSSøren Schmidt #include <sys/errno.h>
4730bf10efSAleksandr Rybalko #include <sys/param.h>
485e0db936SMaxim Sobolev #include <sys/types.h>
495e0db936SMaxim Sobolev #include <sys/stat.h>
5030bf10efSAleksandr Rybalko #include <sys/sysctl.h>
517363955dSSøren Schmidt #include "path.h"
52bfc214e3SBrian Somers #include "decode.h"
537363955dSSøren Schmidt 
54f1121206SXin LI 
55f1121206SXin LI #define	DATASIZE(x)	((x).w * (x).h * 256 / 8)
56acdb2839SMaxim Sobolev 
57c449db6aSMaxim Sobolev /* Screen dump modes */
58c449db6aSMaxim Sobolev #define DUMP_FMT_RAW	1
59c449db6aSMaxim Sobolev #define DUMP_FMT_TXT	2
60c449db6aSMaxim Sobolev /* Screen dump options */
61c449db6aSMaxim Sobolev #define DUMP_FBF	0
62c449db6aSMaxim Sobolev #define DUMP_ALL	1
63c449db6aSMaxim Sobolev /* Screen dump file format revision */
64d02ca551SMaxim Sobolev #define DUMP_FMT_REV	1
65d02ca551SMaxim Sobolev 
663be02c20SEd Schouten static const char *legal_colors[16] = {
677363955dSSøren Schmidt 	"black", "blue", "green", "cyan",
687363955dSSøren Schmidt 	"red", "magenta", "brown", "white",
697363955dSSøren Schmidt 	"grey", "lightblue", "lightgreen", "lightcyan",
707363955dSSøren Schmidt 	"lightred", "lightmagenta", "yellow", "lightwhite"
717363955dSSøren Schmidt };
72f1121206SXin LI 
73bf70beceSEd Schouten static struct {
74f1121206SXin LI 	int			active_vty;
75f1121206SXin LI 	vid_info_t		console_info;
76f1121206SXin LI 	unsigned char		screen_map[256];
77f1121206SXin LI 	int			video_mode_number;
78f1121206SXin LI 	struct video_info	video_mode_info;
79f1121206SXin LI } cur_info;
80f1121206SXin LI 
813be02c20SEd Schouten static int	hex = 0;
823be02c20SEd Schouten static int	vesa_cols;
833be02c20SEd Schouten static int	vesa_rows;
843be02c20SEd Schouten static int	font_height;
8530bf10efSAleksandr Rybalko static int	vt4_mode = 0;
862b881cf4SBruce Evans static int	video_mode_changed;
873be02c20SEd Schouten static struct	video_info new_mode_info;
887363955dSSøren Schmidt 
897363955dSSøren Schmidt 
90f1121206SXin LI /*
91f1121206SXin LI  * Initialize revert data.
92f1121206SXin LI  *
93f1121206SXin LI  * NOTE: the following parameters are not yet saved/restored:
94f1121206SXin LI  *
95f1121206SXin LI  *   screen saver timeout
96f1121206SXin LI  *   cursor type
97f1121206SXin LI  *   mouse character and mouse show/hide state
98f1121206SXin LI  *   vty switching on/off state
99f1121206SXin LI  *   history buffer size
100f1121206SXin LI  *   history contents
101f1121206SXin LI  *   font maps
102f1121206SXin LI  */
103f1121206SXin LI 
104f1121206SXin LI static void
init(void)105f1121206SXin LI init(void)
106f1121206SXin LI {
107f1121206SXin LI 	if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) == -1)
1082b881cf4SBruce Evans 		err(1, "getting active vty");
109f1121206SXin LI 
110f1121206SXin LI 	cur_info.console_info.size = sizeof(cur_info.console_info);
111f1121206SXin LI 	if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1)
1122b881cf4SBruce Evans 		err(1, "getting console information");
113f1121206SXin LI 
11430bf10efSAleksandr Rybalko 	/* vt(4) use unicode, so no screen mapping required. */
11530bf10efSAleksandr Rybalko 	if (vt4_mode == 0 &&
11630bf10efSAleksandr Rybalko 	    ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1)
1172b881cf4SBruce Evans 		err(1, "getting screen map");
118f1121206SXin LI 
119f1121206SXin LI 	if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1)
1202b881cf4SBruce Evans 		err(1, "getting video mode number");
121f1121206SXin LI 
122f1121206SXin LI 	cur_info.video_mode_info.vi_mode = cur_info.video_mode_number;
123f1121206SXin LI 
124f1121206SXin LI 	if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1)
1252b881cf4SBruce Evans 		err(1, "getting video mode parameters");
126f1121206SXin LI }
127f1121206SXin LI 
128f1121206SXin LI 
129f1121206SXin LI /*
130f1121206SXin LI  * If something goes wrong along the way we call revert() to go back to the
131f1121206SXin LI  * console state we came from (which is assumed to be working).
132f1121206SXin LI  *
133f1121206SXin LI  * NOTE: please also read the comments of init().
134f1121206SXin LI  */
135f1121206SXin LI 
136f1121206SXin LI static void
revert(void)137f1121206SXin LI revert(void)
138f1121206SXin LI {
1392b881cf4SBruce Evans 	int save_errno, size[3];
1402b881cf4SBruce Evans 
1412b881cf4SBruce Evans 	save_errno = errno;
142f1121206SXin LI 
143eb0fa6f5SRuslan Ermilov 	ioctl(0, VT_ACTIVATE, cur_info.active_vty);
144f1121206SXin LI 
14503096857SBruce Evans 	ioctl(0, KDSBORDER, cur_info.console_info.mv_ovscan);
146f1121206SXin LI 	fprintf(stderr, "\033[=%dH", cur_info.console_info.mv_rev.fore);
147f1121206SXin LI 	fprintf(stderr, "\033[=%dI", cur_info.console_info.mv_rev.back);
148f1121206SXin LI 
14930bf10efSAleksandr Rybalko 	if (vt4_mode == 0)
150f1121206SXin LI 		ioctl(0, PIO_SCRNMAP, &cur_info.screen_map);
151f1121206SXin LI 
1522b881cf4SBruce Evans 	if (video_mode_changed) {
153f1121206SXin LI 		if (cur_info.video_mode_number >= M_VESA_BASE)
1542b881cf4SBruce Evans 			ioctl(0,
1552b881cf4SBruce Evans 			    _IO('V', cur_info.video_mode_number - M_VESA_BASE),
156f1121206SXin LI 			    NULL);
157f1121206SXin LI 		else
158f1121206SXin LI 			ioctl(0, _IO('S', cur_info.video_mode_number), NULL);
159f1121206SXin LI 		if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) {
160b96ab410SBruce Evans 			size[0] = cur_info.console_info.mv_csz;
161b96ab410SBruce Evans 			size[1] = cur_info.console_info.mv_rsz;
162f1121206SXin LI 			size[2] = cur_info.console_info.font_size;
163f1121206SXin LI 			ioctl(0, KDRASTER, size);
164f1121206SXin LI 		}
1652b881cf4SBruce Evans 	}
1661b8c842eSBruce Evans 
1671b8c842eSBruce Evans 	/* Restore some colors last since mode setting forgets some. */
1681b8c842eSBruce Evans 	fprintf(stderr, "\033[=%dF", cur_info.console_info.mv_norm.fore);
1691b8c842eSBruce Evans 	fprintf(stderr, "\033[=%dG", cur_info.console_info.mv_norm.back);
1702b881cf4SBruce Evans 
1712b881cf4SBruce Evans 	errno = save_errno;
172f1121206SXin LI }
173f1121206SXin LI 
174f1121206SXin LI 
175f1121206SXin LI /*
176f1121206SXin LI  * Print a short usage string describing all options, then exit.
177f1121206SXin LI  */
178f1121206SXin LI 
1799396247eSPhilippe Charnier static void
usage(void)1809a03b27dSXin LI usage(void)
18117ee9d00SSøren Schmidt {
18230bf10efSAleksandr Rybalko 	if (vt4_mode)
183eb4fa1adSBruce Evans 		fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
184*c71ae91fSEd Maste "usage: vidcontrol [-Cx] [-b color] [-c appearance] [-f [[size] file]]",
185449d10e5SEdward Tomasz Napierala "                  [-g geometry] [-h size] [-i active | adapter | mode]",
186eb4fa1adSBruce Evans "                  [-M char] [-m on | off]",
187eb4fa1adSBruce Evans "                  [-r foreground background] [-S on | off] [-s number]",
188eb4fa1adSBruce Evans "                  [-T xterm | cons25] [-t N | off] [mode]",
189eb4fa1adSBruce Evans "                  [foreground [background]] [show]");
19030bf10efSAleksandr Rybalko 	else
191eb4fa1adSBruce Evans 		fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
192d09131e0SBruce Evans "usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-E emulator]",
193d09131e0SBruce Evans "                  [-f [[size] file]] [-g geometry] [-h size]",
194d09131e0SBruce Evans "                  [-i active | adapter | mode] [-l screen_map] [-M char]",
195d09131e0SBruce Evans "                  [-m on | off] [-r foreground background] [-S on | off]",
196d09131e0SBruce Evans "                  [-s number] [-T xterm | cons25] [-t N | off] [mode]",
19792dedf1bSBruce Evans "                  [foreground [background]] [show]");
1989396247eSPhilippe Charnier 	exit(1);
19917ee9d00SSøren Schmidt }
20017ee9d00SSøren Schmidt 
20130bf10efSAleksandr Rybalko /* Detect presence of vt(4). */
20230bf10efSAleksandr Rybalko static int
is_vt4(void)20330bf10efSAleksandr Rybalko is_vt4(void)
20430bf10efSAleksandr Rybalko {
2056c79f788SEd Maste 	char vty_name[4] = "";
2066c79f788SEd Maste 	size_t len = sizeof(vty_name);
20730bf10efSAleksandr Rybalko 
2086c79f788SEd Maste 	if (sysctlbyname("kern.vty", vty_name, &len, NULL, 0) != 0)
20930bf10efSAleksandr Rybalko 		return (0);
2106c79f788SEd Maste 	return (strcmp(vty_name, "vt") == 0);
21130bf10efSAleksandr Rybalko }
212f1121206SXin LI 
213f1121206SXin LI /*
214f1121206SXin LI  * Retrieve the next argument from the command line (for options that require
215f1121206SXin LI  * more than one argument).
216f1121206SXin LI  */
217f1121206SXin LI 
2189a03b27dSXin LI static char *
nextarg(int ac,char ** av,int * indp,int oc,int strict)2195e0db936SMaxim Sobolev nextarg(int ac, char **av, int *indp, int oc, int strict)
2207363955dSSøren Schmidt {
2217363955dSSøren Schmidt 	if (*indp < ac)
2227363955dSSøren Schmidt 		return(av[(*indp)++]);
223f1121206SXin LI 
224f1121206SXin LI 	if (strict != 0) {
225f1121206SXin LI 		revert();
2269396247eSPhilippe Charnier 		errx(1, "option requires two arguments -- %c", oc);
227f1121206SXin LI 	}
228f1121206SXin LI 
2295e0db936SMaxim Sobolev 	return(NULL);
2307363955dSSøren Schmidt }
2317363955dSSøren Schmidt 
232f1121206SXin LI 
233f1121206SXin LI /*
234f1121206SXin LI  * Guess which file to open. Try to open each combination of a specified set
235f1121206SXin LI  * of file name components.
236f1121206SXin LI  */
237f1121206SXin LI 
2389a03b27dSXin LI static FILE *
openguess(const char * a[],const char * b[],const char * c[],const char * d[],char ** name)2399a03b27dSXin LI openguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name)
2407363955dSSøren Schmidt {
2413646fbdaSMaxim Sobolev 	FILE *f;
2423646fbdaSMaxim Sobolev 	int i, j, k, l;
2437363955dSSøren Schmidt 
2443646fbdaSMaxim Sobolev 	for (i = 0; a[i] != NULL; i++) {
2453646fbdaSMaxim Sobolev 		for (j = 0; b[j] != NULL; j++) {
2463646fbdaSMaxim Sobolev 			for (k = 0; c[k] != NULL; k++) {
2473646fbdaSMaxim Sobolev 				for (l = 0; d[l] != NULL; l++) {
248f1121206SXin LI 					asprintf(name, "%s%s%s%s",
249f1121206SXin LI 						 a[i], b[j], c[k], d[l]);
250f1121206SXin LI 
2513646fbdaSMaxim Sobolev 					f = fopen(*name, "r");
252f1121206SXin LI 
2533646fbdaSMaxim Sobolev 					if (f != NULL)
2543646fbdaSMaxim Sobolev 						return (f);
255f1121206SXin LI 
2563646fbdaSMaxim Sobolev 					free(*name);
25739b235efSBill Fumerola 				}
2583646fbdaSMaxim Sobolev 			}
2593646fbdaSMaxim Sobolev 		}
2603646fbdaSMaxim Sobolev 	}
2617363955dSSøren Schmidt 	return (NULL);
2627363955dSSøren Schmidt }
2637363955dSSøren Schmidt 
264f1121206SXin LI 
265f1121206SXin LI /*
266f1121206SXin LI  * Load a screenmap from a file and set it.
267f1121206SXin LI  */
268f1121206SXin LI 
2699a03b27dSXin LI static void
load_scrnmap(const char * filename)2709a03b27dSXin LI load_scrnmap(const char *filename)
2717363955dSSøren Schmidt {
2723646fbdaSMaxim Sobolev 	FILE *fd;
2733646fbdaSMaxim Sobolev 	int size;
2747363955dSSøren Schmidt 	char *name;
2757363955dSSøren Schmidt 	scrmap_t scrnmap;
2769a03b27dSXin LI 	const char *a[] = {"", SCRNMAP_PATH, NULL};
2779a03b27dSXin LI 	const char *b[] = {filename, NULL};
2789a03b27dSXin LI 	const char *c[] = {"", ".scm", NULL};
2799a03b27dSXin LI 	const char *d[] = {"", NULL};
2807363955dSSøren Schmidt 
2813646fbdaSMaxim Sobolev 	fd = openguess(a, b, c, d, &name);
282f1121206SXin LI 
2837363955dSSøren Schmidt 	if (fd == NULL) {
284f1121206SXin LI 		revert();
285f1121206SXin LI 		errx(1, "screenmap file not found");
2867363955dSSøren Schmidt 	}
287f1121206SXin LI 
2887363955dSSøren Schmidt 	size = sizeof(scrnmap);
289f1121206SXin LI 
2905e0db936SMaxim Sobolev 	if (decode(fd, (char *)&scrnmap, size) != size) {
2917363955dSSøren Schmidt 		rewind(fd);
292f1121206SXin LI 
293f1121206SXin LI 		if (fread(&scrnmap, 1, size, fd) != (size_t)size) {
294bfc214e3SBrian Somers 			fclose(fd);
295f1121206SXin LI 			revert();
296f1121206SXin LI 			errx(1, "bad screenmap file");
2977363955dSSøren Schmidt 		}
2987363955dSSøren Schmidt 	}
299f1121206SXin LI 
300f1121206SXin LI 	if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) {
301f1121206SXin LI 		revert();
3022b881cf4SBruce Evans 		err(1, "loading screenmap");
303f1121206SXin LI 	}
304f1121206SXin LI 
305bfc214e3SBrian Somers 	fclose(fd);
3067363955dSSøren Schmidt }
3077363955dSSøren Schmidt 
308f1121206SXin LI 
309f1121206SXin LI /*
310f1121206SXin LI  * Set the default screenmap.
311f1121206SXin LI  */
312f1121206SXin LI 
3139a03b27dSXin LI static void
load_default_scrnmap(void)3149a03b27dSXin LI load_default_scrnmap(void)
3157363955dSSøren Schmidt {
3167363955dSSøren Schmidt 	scrmap_t scrnmap;
31717ee9d00SSøren Schmidt 	int i;
3187363955dSSøren Schmidt 
3197363955dSSøren Schmidt 	for (i=0; i<256; i++)
3207363955dSSøren Schmidt 		*((char*)&scrnmap + i) = i;
321f1121206SXin LI 
322f1121206SXin LI 	if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) {
323f1121206SXin LI 		revert();
3242b881cf4SBruce Evans 		err(1, "loading default screenmap");
3257363955dSSøren Schmidt 	}
326f1121206SXin LI }
327f1121206SXin LI 
328f1121206SXin LI 
329f1121206SXin LI /*
330f1121206SXin LI  * Print the current screenmap to stdout.
331f1121206SXin LI  */
3327363955dSSøren Schmidt 
3339a03b27dSXin LI static void
print_scrnmap(void)3349a03b27dSXin LI print_scrnmap(void)
3357363955dSSøren Schmidt {
3367363955dSSøren Schmidt 	unsigned char map[256];
3379a03b27dSXin LI 	size_t i;
3387363955dSSøren Schmidt 
339f1121206SXin LI 	if (ioctl(0, GIO_SCRNMAP, &map) == -1) {
340f1121206SXin LI 		revert();
3412b881cf4SBruce Evans 		err(1, "getting screenmap");
3427363955dSSøren Schmidt 	}
3437363955dSSøren Schmidt 	for (i=0; i<sizeof(map); i++) {
3449a03b27dSXin LI 		if (i != 0 && i % 16 == 0)
3457363955dSSøren Schmidt 			fprintf(stdout, "\n");
346f1121206SXin LI 
347f1121206SXin LI 		if (hex != 0)
3487363955dSSøren Schmidt 			fprintf(stdout, " %02x", map[i]);
3497363955dSSøren Schmidt 		else
3507363955dSSøren Schmidt 			fprintf(stdout, " %03d", map[i]);
3517363955dSSøren Schmidt 	}
3527363955dSSøren Schmidt 	fprintf(stdout, "\n");
3537363955dSSøren Schmidt 
3547363955dSSøren Schmidt }
3557363955dSSøren Schmidt 
356f1121206SXin LI 
357f1121206SXin LI /*
358f1121206SXin LI  * Determine a file's size.
359f1121206SXin LI  */
360f1121206SXin LI 
3619a03b27dSXin LI static int
fsize(FILE * file)3625e0db936SMaxim Sobolev fsize(FILE *file)
3635e0db936SMaxim Sobolev {
3645e0db936SMaxim Sobolev 	struct stat sb;
3655e0db936SMaxim Sobolev 
3665e0db936SMaxim Sobolev 	if (fstat(fileno(file), &sb) == 0)
3675e0db936SMaxim Sobolev 		return sb.st_size;
3685e0db936SMaxim Sobolev 	else
3695e0db936SMaxim Sobolev 		return -1;
3705e0db936SMaxim Sobolev }
3715e0db936SMaxim Sobolev 
37230bf10efSAleksandr Rybalko static vfnt_map_t *
load_vt4mappingtable(unsigned int nmappings,FILE * f)37330bf10efSAleksandr Rybalko load_vt4mappingtable(unsigned int nmappings, FILE *f)
37430bf10efSAleksandr Rybalko {
37530bf10efSAleksandr Rybalko 	vfnt_map_t *t;
37630bf10efSAleksandr Rybalko 	unsigned int i;
37730bf10efSAleksandr Rybalko 
37830bf10efSAleksandr Rybalko 	if (nmappings == 0)
37930bf10efSAleksandr Rybalko 		return (NULL);
38030bf10efSAleksandr Rybalko 
381becf2d11SEd Maste 	if ((t = calloc(nmappings, sizeof(*t))) == NULL) {
382becf2d11SEd Maste 		warn("calloc");
383aba6e414SEd Maste 		return (NULL);
384aba6e414SEd Maste 	}
38530bf10efSAleksandr Rybalko 
38630bf10efSAleksandr Rybalko 	if (fread(t, sizeof *t * nmappings, 1, f) != 1) {
387aba6e414SEd Maste 		warn("read mappings");
388aba6e414SEd Maste 		free(t);
389aba6e414SEd Maste 		return (NULL);
39030bf10efSAleksandr Rybalko 	}
39130bf10efSAleksandr Rybalko 
39230bf10efSAleksandr Rybalko 	for (i = 0; i < nmappings; i++) {
393e7fd9688SToomas Soome 		t[i].vfm_src = be32toh(t[i].vfm_src);
394e7fd9688SToomas Soome 		t[i].vfm_dst = be16toh(t[i].vfm_dst);
395e7fd9688SToomas Soome 		t[i].vfm_len = be16toh(t[i].vfm_len);
39630bf10efSAleksandr Rybalko 	}
39730bf10efSAleksandr Rybalko 
39830bf10efSAleksandr Rybalko 	return (t);
39930bf10efSAleksandr Rybalko }
40030bf10efSAleksandr Rybalko 
401069f1c25SJean-Sébastien Pédron /*
402069f1c25SJean-Sébastien Pédron  * Set the default vt font.
403069f1c25SJean-Sébastien Pédron  */
404069f1c25SJean-Sébastien Pédron 
405069f1c25SJean-Sébastien Pédron static void
load_default_vt4font(void)406069f1c25SJean-Sébastien Pédron load_default_vt4font(void)
407069f1c25SJean-Sébastien Pédron {
408069f1c25SJean-Sébastien Pédron 	if (ioctl(0, PIO_VFONT_DEFAULT) == -1) {
409069f1c25SJean-Sébastien Pédron 		revert();
4102b881cf4SBruce Evans 		err(1, "loading default vt font");
411069f1c25SJean-Sébastien Pédron 	}
412069f1c25SJean-Sébastien Pédron }
413069f1c25SJean-Sébastien Pédron 
414aba6e414SEd Maste static void
load_vt4font(FILE * f)41530bf10efSAleksandr Rybalko load_vt4font(FILE *f)
41630bf10efSAleksandr Rybalko {
417e7fd9688SToomas Soome 	struct font_header fh;
41830bf10efSAleksandr Rybalko 	static vfnt_t vfnt;
41930bf10efSAleksandr Rybalko 	size_t glyphsize;
42030bf10efSAleksandr Rybalko 	unsigned int i;
42130bf10efSAleksandr Rybalko 
42230bf10efSAleksandr Rybalko 	if (fread(&fh, sizeof fh, 1, f) != 1) {
423aba6e414SEd Maste 		warn("read file_header");
424aba6e414SEd Maste 		return;
42530bf10efSAleksandr Rybalko 	}
42630bf10efSAleksandr Rybalko 
427e7fd9688SToomas Soome 	if (memcmp(fh.fh_magic, "VFNT0002", 8) != 0) {
428aba6e414SEd Maste 		warnx("bad magic in font file\n");
429aba6e414SEd Maste 		return;
43030bf10efSAleksandr Rybalko 	}
43130bf10efSAleksandr Rybalko 
43230bf10efSAleksandr Rybalko 	for (i = 0; i < VFNT_MAPS; i++)
433e7fd9688SToomas Soome 		vfnt.map_count[i] = be32toh(fh.fh_map_count[i]);
434e7fd9688SToomas Soome 	vfnt.glyph_count = be32toh(fh.fh_glyph_count);
435e7fd9688SToomas Soome 	vfnt.width = fh.fh_width;
436e7fd9688SToomas Soome 	vfnt.height = fh.fh_height;
43730bf10efSAleksandr Rybalko 
43830bf10efSAleksandr Rybalko 	glyphsize = howmany(vfnt.width, 8) * vfnt.height * vfnt.glyph_count;
439aba6e414SEd Maste 	if ((vfnt.glyphs = malloc(glyphsize)) == NULL) {
440aba6e414SEd Maste 		warn("malloc");
441aba6e414SEd Maste 		return;
442aba6e414SEd Maste 	}
44330bf10efSAleksandr Rybalko 
44430bf10efSAleksandr Rybalko 	if (fread(vfnt.glyphs, glyphsize, 1, f) != 1) {
445aba6e414SEd Maste 		warn("read glyphs");
446aba6e414SEd Maste 		free(vfnt.glyphs);
447aba6e414SEd Maste 		return;
44830bf10efSAleksandr Rybalko 	}
44930bf10efSAleksandr Rybalko 
45030bf10efSAleksandr Rybalko 	for (i = 0; i < VFNT_MAPS; i++)
45130bf10efSAleksandr Rybalko 		vfnt.map[i] = load_vt4mappingtable(vfnt.map_count[i], f);
45230bf10efSAleksandr Rybalko 
453aba6e414SEd Maste 	if (ioctl(STDIN_FILENO, PIO_VFONT, &vfnt) == -1)
454aba6e414SEd Maste 		warn("PIO_VFONT");
455aba6e414SEd Maste 
456aba6e414SEd Maste 	for (i = 0; i < VFNT_MAPS; i++)
457aba6e414SEd Maste 		free(vfnt.map[i]);
458aba6e414SEd Maste 	free(vfnt.glyphs);
45930bf10efSAleksandr Rybalko }
460f1121206SXin LI 
461f1121206SXin LI /*
462f1121206SXin LI  * Load a font from file and set it.
463f1121206SXin LI  */
4645e0db936SMaxim Sobolev 
4659a03b27dSXin LI static void
load_font(const char * type,const char * filename)4669a03b27dSXin LI load_font(const char *type, const char *filename)
4677363955dSSøren Schmidt {
4683646fbdaSMaxim Sobolev 	FILE	*fd;
4695e0db936SMaxim Sobolev 	int	h, i, size, w;
4705e0db936SMaxim Sobolev 	unsigned long io = 0;	/* silence stupid gcc(1) in the Wall mode */
4713646fbdaSMaxim Sobolev 	char	*name, *fontmap, size_sufx[6];
4729a03b27dSXin LI 	const char	*a[] = {"", FONT_PATH, NULL};
47330bf10efSAleksandr Rybalko 	const char	*vt4a[] = {"", VT_FONT_PATH, NULL};
4749a03b27dSXin LI 	const char	*b[] = {filename, NULL};
4759a03b27dSXin LI 	const char	*c[] = {"", size_sufx, NULL};
4769a03b27dSXin LI 	const char	*d[] = {"", ".fnt", NULL};
4778f92a81bSBruce Evans 	vid_info_t info;
4787363955dSSøren Schmidt 
4795e0db936SMaxim Sobolev 	struct sizeinfo {
4805e0db936SMaxim Sobolev 		int w;
4815e0db936SMaxim Sobolev 		int h;
4825e0db936SMaxim Sobolev 		unsigned long io;
4835e0db936SMaxim Sobolev 	} sizes[] = {{8, 16, PIO_FONT8x16},
4845e0db936SMaxim Sobolev 		     {8, 14, PIO_FONT8x14},
4855e0db936SMaxim Sobolev 		     {8,  8,  PIO_FONT8x8},
4865e0db936SMaxim Sobolev 		     {0,  0,            0}};
4875e0db936SMaxim Sobolev 
48830bf10efSAleksandr Rybalko 	if (vt4_mode) {
48930bf10efSAleksandr Rybalko 		size_sufx[0] = '\0';
49030bf10efSAleksandr Rybalko 	} else {
4918f92a81bSBruce Evans 		info.size = sizeof(info);
4928f92a81bSBruce Evans 		if (ioctl(0, CONS_GETINFO, &info) == -1) {
493f1121206SXin LI 			revert();
4948f92a81bSBruce Evans 			err(1, "getting console information");
4957363955dSSøren Schmidt 		}
496f1121206SXin LI 
4978f92a81bSBruce Evans 		snprintf(size_sufx, sizeof(size_sufx), "-8x%d", info.font_size);
49830bf10efSAleksandr Rybalko 	}
49930bf10efSAleksandr Rybalko 	fd = openguess((vt4_mode == 0) ? a : vt4a, b, c, d, &name);
500f1121206SXin LI 
5017363955dSSøren Schmidt 	if (fd == NULL) {
502f1121206SXin LI 		revert();
503f1121206SXin LI 		errx(1, "%s: can't load font file", filename);
5047363955dSSøren Schmidt 	}
505f1121206SXin LI 
50630bf10efSAleksandr Rybalko 	if (vt4_mode) {
507aba6e414SEd Maste 		load_vt4font(fd);
50830bf10efSAleksandr Rybalko 		fclose(fd);
50930bf10efSAleksandr Rybalko 		return;
51030bf10efSAleksandr Rybalko 	}
51130bf10efSAleksandr Rybalko 
5125e0db936SMaxim Sobolev 	if (type != NULL) {
5135e0db936SMaxim Sobolev 		size = 0;
514f1121206SXin LI 		if (sscanf(type, "%dx%d", &w, &h) == 2) {
515f1121206SXin LI 			for (i = 0; sizes[i].w != 0; i++) {
5165e0db936SMaxim Sobolev 				if (sizes[i].w == w && sizes[i].h == h) {
5175e0db936SMaxim Sobolev 					size = DATASIZE(sizes[i]);
5185e0db936SMaxim Sobolev 					io = sizes[i].io;
519f1121206SXin LI 					font_height = sizes[i].h;
5207363955dSSøren Schmidt 				}
521f1121206SXin LI 			}
522f1121206SXin LI 		}
5235e0db936SMaxim Sobolev 		if (size == 0) {
524bfc214e3SBrian Somers 			fclose(fd);
525f1121206SXin LI 			revert();
526f1121206SXin LI 			errx(1, "%s: bad font size specification", type);
5277363955dSSøren Schmidt 		}
5285e0db936SMaxim Sobolev 	} else {
5295e0db936SMaxim Sobolev 		/* Apply heuristics */
530f1121206SXin LI 
5315e0db936SMaxim Sobolev 		int j;
5325e0db936SMaxim Sobolev 		int dsize[2];
5335e0db936SMaxim Sobolev 
5345e0db936SMaxim Sobolev 		size = DATASIZE(sizes[0]);
5357363955dSSøren Schmidt 		fontmap = (char*) malloc(size);
5365e0db936SMaxim Sobolev 		dsize[0] = decode(fd, fontmap, size);
5375e0db936SMaxim Sobolev 		dsize[1] = fsize(fd);
5385e0db936SMaxim Sobolev 		free(fontmap);
5395e0db936SMaxim Sobolev 
5405e0db936SMaxim Sobolev 		size = 0;
541f1121206SXin LI 		for (j = 0; j < 2; j++) {
542f1121206SXin LI 			for (i = 0; sizes[i].w != 0; i++) {
5435e0db936SMaxim Sobolev 				if (DATASIZE(sizes[i]) == dsize[j]) {
5445e0db936SMaxim Sobolev 					size = dsize[j];
5455e0db936SMaxim Sobolev 					io = sizes[i].io;
546f1121206SXin LI 					font_height = sizes[i].h;
5475e0db936SMaxim Sobolev 					j = 2;	/* XXX */
5485e0db936SMaxim Sobolev 					break;
5495e0db936SMaxim Sobolev 				}
550f1121206SXin LI 			}
551f1121206SXin LI 		}
5525e0db936SMaxim Sobolev 
5535e0db936SMaxim Sobolev 		if (size == 0) {
5545e0db936SMaxim Sobolev 			fclose(fd);
555f1121206SXin LI 			revert();
556f1121206SXin LI 			errx(1, "%s: can't guess font size", filename);
5575e0db936SMaxim Sobolev 		}
558f1121206SXin LI 
5597363955dSSøren Schmidt 		rewind(fd);
5605e0db936SMaxim Sobolev 	}
5615e0db936SMaxim Sobolev 
5625e0db936SMaxim Sobolev 	fontmap = (char*) malloc(size);
563f1121206SXin LI 
5645e0db936SMaxim Sobolev 	if (decode(fd, fontmap, size) != size) {
5655e0db936SMaxim Sobolev 		rewind(fd);
566f1121206SXin LI 		if (fsize(fd) != size ||
567f1121206SXin LI 		    fread(fontmap, 1, size, fd) != (size_t)size) {
568bfc214e3SBrian Somers 			fclose(fd);
5697363955dSSøren Schmidt 			free(fontmap);
570f1121206SXin LI 			revert();
571f1121206SXin LI 			errx(1, "%s: bad font file", filename);
5727363955dSSøren Schmidt 		}
5737363955dSSøren Schmidt 	}
574f1121206SXin LI 
575f1121206SXin LI 	if (ioctl(0, io, fontmap) == -1) {
576f1121206SXin LI 		revert();
5772b881cf4SBruce Evans 		err(1, "loading font");
578f1121206SXin LI 	}
579f1121206SXin LI 
580bfc214e3SBrian Somers 	fclose(fd);
5817363955dSSøren Schmidt 	free(fontmap);
5827363955dSSøren Schmidt }
5837363955dSSøren Schmidt 
584f1121206SXin LI 
585f1121206SXin LI /*
586f1121206SXin LI  * Set the timeout for the screensaver.
587f1121206SXin LI  */
588f1121206SXin LI 
5899a03b27dSXin LI static void
set_screensaver_timeout(char * arg)5907363955dSSøren Schmidt set_screensaver_timeout(char *arg)
5917363955dSSøren Schmidt {
5927363955dSSøren Schmidt 	int nsec;
5937363955dSSøren Schmidt 
594f1121206SXin LI 	if (!strcmp(arg, "off")) {
5957363955dSSøren Schmidt 		nsec = 0;
596f1121206SXin LI 	} else {
5977363955dSSøren Schmidt 		nsec = atoi(arg);
598f1121206SXin LI 
5997363955dSSøren Schmidt 		if ((*arg == '\0') || (nsec < 1)) {
600f1121206SXin LI 			revert();
601f1121206SXin LI 			errx(1, "argument must be a positive number");
6027363955dSSøren Schmidt 		}
6037363955dSSøren Schmidt 	}
604f1121206SXin LI 
605f1121206SXin LI 	if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) {
606f1121206SXin LI 		revert();
6072b881cf4SBruce Evans 		err(1, "setting screensaver period");
6087363955dSSøren Schmidt 	}
609f1121206SXin LI }
610f1121206SXin LI 
61192dedf1bSBruce Evans static void
parse_cursor_params(char * param,struct cshape * shape)61292dedf1bSBruce Evans parse_cursor_params(char *param, struct cshape *shape)
61392dedf1bSBruce Evans {
61492dedf1bSBruce Evans 	char *dupparam, *word;
61592dedf1bSBruce Evans 	int type;
61692dedf1bSBruce Evans 
61792dedf1bSBruce Evans 	param = dupparam = strdup(param);
61892dedf1bSBruce Evans 	type = shape->shape[0];
61992dedf1bSBruce Evans 	while ((word = strsep(&param, ",")) != NULL) {
620dd51fcebSBruce Evans 		if (strcmp(word, "normal") == 0)
62192dedf1bSBruce Evans 			type = 0;
62292dedf1bSBruce Evans 		else if (strcmp(word, "destructive") == 0)
62392dedf1bSBruce Evans 			type = CONS_BLINK_CURSOR | CONS_CHAR_CURSOR;
624dd51fcebSBruce Evans 		else if (strcmp(word, "blink") == 0)
625dd51fcebSBruce Evans 			type |= CONS_BLINK_CURSOR;
626dd51fcebSBruce Evans 		else if (strcmp(word, "noblink") == 0)
62792dedf1bSBruce Evans 			type &= ~CONS_BLINK_CURSOR;
628dd51fcebSBruce Evans 		else if (strcmp(word, "block") == 0)
62992dedf1bSBruce Evans 			type &= ~CONS_CHAR_CURSOR;
630dd51fcebSBruce Evans 		else if (strcmp(word, "noblock") == 0)
631dd51fcebSBruce Evans 			type |= CONS_CHAR_CURSOR;
63292dedf1bSBruce Evans 		else if (strcmp(word, "hidden") == 0)
63392dedf1bSBruce Evans 			type |= CONS_HIDDEN_CURSOR;
63492dedf1bSBruce Evans 		else if (strcmp(word, "nohidden") == 0)
63592dedf1bSBruce Evans 			type &= ~CONS_HIDDEN_CURSOR;
636dd51fcebSBruce Evans 		else if (strncmp(word, "base=", 5) == 0)
637dd51fcebSBruce Evans 			shape->shape[1] = strtol(word + 5, NULL, 0);
638dd51fcebSBruce Evans 		else if (strncmp(word, "height=", 7) == 0)
639dd51fcebSBruce Evans 			shape->shape[2] = strtol(word + 7, NULL, 0);
6409bc7c363SBruce Evans 		else if (strcmp(word, "charcolors") == 0)
6419bc7c363SBruce Evans 			type |= CONS_CHARCURSOR_COLORS;
6429bc7c363SBruce Evans 		else if (strcmp(word, "mousecolors") == 0)
6439bc7c363SBruce Evans 			type |= CONS_MOUSECURSOR_COLORS;
6449bc7c363SBruce Evans 		else if (strcmp(word, "default") == 0)
6459bc7c363SBruce Evans 			type |= CONS_DEFAULT_CURSOR;
6469bc7c363SBruce Evans 		else if (strcmp(word, "shapeonly") == 0)
6479bc7c363SBruce Evans 			type |= CONS_SHAPEONLY_CURSOR;
64892dedf1bSBruce Evans 		else if (strcmp(word, "local") == 0)
64992dedf1bSBruce Evans 			type |= CONS_LOCAL_CURSOR;
65092dedf1bSBruce Evans 		else if (strcmp(word, "reset") == 0)
65192dedf1bSBruce Evans 			type |= CONS_RESET_CURSOR;
6529bc7c363SBruce Evans 		else if (strcmp(word, "show") == 0)
6539bc7c363SBruce Evans 			printf("flags %#x, base %d, height %d\n",
6549bc7c363SBruce Evans 			    type, shape->shape[1], shape->shape[2]);
65592dedf1bSBruce Evans 		else {
65692dedf1bSBruce Evans 			revert();
65792dedf1bSBruce Evans 			errx(1,
65892dedf1bSBruce Evans 			    "invalid parameters for -c starting at '%s%s%s'",
65992dedf1bSBruce Evans 			    word, param != NULL ? "," : "",
66092dedf1bSBruce Evans 			    param != NULL ? param : "");
66192dedf1bSBruce Evans 		}
66292dedf1bSBruce Evans 	}
66392dedf1bSBruce Evans 	free(dupparam);
66492dedf1bSBruce Evans 	shape->shape[0] = type;
66592dedf1bSBruce Evans }
66692dedf1bSBruce Evans 
667f1121206SXin LI 
668f1121206SXin LI /*
669f1121206SXin LI  * Set the cursor's shape/type.
670f1121206SXin LI  */
6717363955dSSøren Schmidt 
6729a03b27dSXin LI static void
set_cursor_type(char * param)67392dedf1bSBruce Evans set_cursor_type(char *param)
6747363955dSSøren Schmidt {
67592dedf1bSBruce Evans 	struct cshape shape;
6767363955dSSøren Schmidt 
6779bc7c363SBruce Evans 	/* Dry run to determine color, default and local flags. */
67892dedf1bSBruce Evans 	shape.shape[0] = 0;
6799bc7c363SBruce Evans 	shape.shape[1] = -1;
6809bc7c363SBruce Evans 	shape.shape[2] = -1;
68192dedf1bSBruce Evans 	parse_cursor_params(param, &shape);
68292dedf1bSBruce Evans 
6839bc7c363SBruce Evans 	/* Get the relevant old setting. */
68492dedf1bSBruce Evans 	if (ioctl(0, CONS_GETCURSORSHAPE, &shape) != 0) {
685f1121206SXin LI 		revert();
68692dedf1bSBruce Evans 		err(1, "ioctl(CONS_GETCURSORSHAPE)");
6877363955dSSøren Schmidt 	}
6887363955dSSøren Schmidt 
68992dedf1bSBruce Evans 	parse_cursor_params(param, &shape);
69092dedf1bSBruce Evans 	if (ioctl(0, CONS_SETCURSORSHAPE, &shape) != 0) {
691f1121206SXin LI 		revert();
69292dedf1bSBruce Evans 		err(1, "ioctl(CONS_SETCURSORSHAPE)");
693f1121206SXin LI 	}
694f1121206SXin LI }
695f1121206SXin LI 
696f1121206SXin LI 
697f1121206SXin LI /*
698f1121206SXin LI  * Set the video mode.
699f1121206SXin LI  */
700f1121206SXin LI 
7011b8c842eSBruce Evans static void
video_mode(int argc,char ** argv,int * mode_index)702f1121206SXin LI video_mode(int argc, char **argv, int *mode_index)
7037363955dSSøren Schmidt {
704cb1d2924SKazutaka YOKOTA 	static struct {
7059a03b27dSXin LI 		const char *name;
706cb1d2924SKazutaka YOKOTA 		unsigned long mode;
707f1121206SXin LI 		unsigned long mode_num;
708cb1d2924SKazutaka YOKOTA 	} modes[] = {
709f1121206SXin LI 		{ "80x25",        SW_TEXT_80x25,   M_TEXT_80x25 },
710f1121206SXin LI 		{ "80x30",        SW_TEXT_80x30,   M_TEXT_80x30 },
711f1121206SXin LI 		{ "80x43",        SW_TEXT_80x43,   M_TEXT_80x43 },
712f1121206SXin LI 		{ "80x50",        SW_TEXT_80x50,   M_TEXT_80x50 },
713f1121206SXin LI 		{ "80x60",        SW_TEXT_80x60,   M_TEXT_80x60 },
714f1121206SXin LI 		{ "132x25",       SW_TEXT_132x25,  M_TEXT_132x25 },
715f1121206SXin LI 		{ "132x30",       SW_TEXT_132x30,  M_TEXT_132x30 },
716f1121206SXin LI 		{ "132x43",       SW_TEXT_132x43,  M_TEXT_132x43 },
717f1121206SXin LI 		{ "132x50",       SW_TEXT_132x50,  M_TEXT_132x50 },
718f1121206SXin LI 		{ "132x60",       SW_TEXT_132x60,  M_TEXT_132x60 },
719f1121206SXin LI 		{ "VGA_40x25",    SW_VGA_C40x25,   M_VGA_C40x25 },
720f1121206SXin LI 		{ "VGA_80x25",    SW_VGA_C80x25,   M_VGA_C80x25 },
721f1121206SXin LI 		{ "VGA_80x30",    SW_VGA_C80x30,   M_VGA_C80x30 },
722f1121206SXin LI 		{ "VGA_80x50",    SW_VGA_C80x50,   M_VGA_C80x50 },
723f1121206SXin LI 		{ "VGA_80x60",    SW_VGA_C80x60,   M_VGA_C80x60 },
724ac80d4b4SKazutaka YOKOTA #ifdef SW_VGA_C90x25
725f1121206SXin LI 		{ "VGA_90x25",    SW_VGA_C90x25,   M_VGA_C90x25 },
726f1121206SXin LI 		{ "VGA_90x30",    SW_VGA_C90x30,   M_VGA_C90x30 },
727f1121206SXin LI 		{ "VGA_90x43",    SW_VGA_C90x43,   M_VGA_C90x43 },
728f1121206SXin LI 		{ "VGA_90x50",    SW_VGA_C90x50,   M_VGA_C90x50 },
729f1121206SXin LI 		{ "VGA_90x60",    SW_VGA_C90x60,   M_VGA_C90x60 },
730ac80d4b4SKazutaka YOKOTA #endif
731f1121206SXin LI 		{ "VGA_320x200",	SW_VGA_CG320,	M_CG320 },
732f1121206SXin LI 		{ "EGA_80x25",		SW_ENH_C80x25,	M_ENH_C80x25 },
733f1121206SXin LI 		{ "EGA_80x43",		SW_ENH_C80x43,	M_ENH_C80x43 },
734f1121206SXin LI 		{ "VESA_132x25",	SW_VESA_C132x25,M_VESA_C132x25 },
735f1121206SXin LI 		{ "VESA_132x43",	SW_VESA_C132x43,M_VESA_C132x43 },
736f1121206SXin LI 		{ "VESA_132x50",	SW_VESA_C132x50,M_VESA_C132x50 },
737f1121206SXin LI 		{ "VESA_132x60",	SW_VESA_C132x60,M_VESA_C132x60 },
738f1121206SXin LI 		{ "VESA_800x600",	SW_VESA_800x600,M_VESA_800x600 },
739f1121206SXin LI 		{ NULL, 0, 0 },
740cb1d2924SKazutaka YOKOTA 	};
741f1121206SXin LI 
742f1121206SXin LI 	int new_mode_num = 0;
743bc9e0443SMatt Jacob 	unsigned long mode = 0;
744ac80d4b4SKazutaka YOKOTA 	int cur_mode;
7452b881cf4SBruce Evans 	int save_errno;
746a8445737SSøren Schmidt 	int size[3];
747cb1d2924SKazutaka YOKOTA 	int i;
7487363955dSSøren Schmidt 
749ac80d4b4SKazutaka YOKOTA 	if (ioctl(0, CONS_GET, &cur_mode) < 0)
750ac80d4b4SKazutaka YOKOTA 		err(1, "cannot get the current video mode");
751f1121206SXin LI 
752f1121206SXin LI 	/*
753f1121206SXin LI 	 * Parse the video mode argument...
754f1121206SXin LI 	 */
755f1121206SXin LI 
756f1121206SXin LI 	if (*mode_index < argc) {
757f1121206SXin LI 		if (!strncmp(argv[*mode_index], "MODE_", 5)) {
758f1121206SXin LI 			if (!isdigit(argv[*mode_index][5]))
759f1121206SXin LI 				errx(1, "invalid video mode number");
760f1121206SXin LI 
761f1121206SXin LI 			new_mode_num = atoi(&argv[*mode_index][5]);
762f1121206SXin LI 		} else {
763cb1d2924SKazutaka YOKOTA 			for (i = 0; modes[i].name != NULL; ++i) {
764f1121206SXin LI 				if (!strcmp(argv[*mode_index], modes[i].name)) {
765cb1d2924SKazutaka YOKOTA 					mode = modes[i].mode;
766f1121206SXin LI 					new_mode_num = modes[i].mode_num;
767cb1d2924SKazutaka YOKOTA 					break;
768cb1d2924SKazutaka YOKOTA 				}
769cb1d2924SKazutaka YOKOTA 			}
770f1121206SXin LI 
771cb1d2924SKazutaka YOKOTA 			if (modes[i].name == NULL)
7721b8c842eSBruce Evans 				return;
773a0503c27SEivind Eklund 			if (ioctl(0, mode, NULL) < 0) {
7741b8c842eSBruce Evans 				revert();
7752b881cf4SBruce Evans 				err(1, "cannot set videomode");
776a0503c27SEivind Eklund 			}
7772b881cf4SBruce Evans 			video_mode_changed = 1;
778f1121206SXin LI 		}
779f1121206SXin LI 
780f1121206SXin LI 		/*
781f1121206SXin LI 		 * Collect enough information about the new video mode...
782f1121206SXin LI 		 */
783f1121206SXin LI 
784f1121206SXin LI 		new_mode_info.vi_mode = new_mode_num;
785f1121206SXin LI 
786f1121206SXin LI 		if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) {
787f1121206SXin LI 			revert();
7882b881cf4SBruce Evans 			err(1, "obtaining new video mode parameters");
789f1121206SXin LI 		}
790f1121206SXin LI 
791f1121206SXin LI 		if (mode == 0) {
792f1121206SXin LI 			if (new_mode_num >= M_VESA_BASE)
793f1121206SXin LI 				mode = _IO('V', new_mode_num - M_VESA_BASE);
794f1121206SXin LI 			else
795f1121206SXin LI 				mode = _IO('S', new_mode_num);
796f1121206SXin LI 		}
797f1121206SXin LI 
798f1121206SXin LI 		/*
799f1121206SXin LI 		 * Try setting the new mode.
800f1121206SXin LI 		 */
801f1121206SXin LI 
802f1121206SXin LI 		if (ioctl(0, mode, NULL) == -1) {
803f1121206SXin LI 			revert();
8042b881cf4SBruce Evans 			err(1, "setting video mode");
805f1121206SXin LI 		}
8062b881cf4SBruce Evans 		video_mode_changed = 1;
807f1121206SXin LI 
808f1121206SXin LI 		/*
809f1121206SXin LI 		 * For raster modes it's not enough to just set the mode.
810f1121206SXin LI 		 * We also need to explicitly set the raster mode.
811f1121206SXin LI 		 */
812f1121206SXin LI 
813f1121206SXin LI 		if (new_mode_info.vi_flags & V_INFO_GRAPHICS) {
814f1121206SXin LI 			/* font size */
815f1121206SXin LI 
816f1121206SXin LI 			if (font_height == 0)
817f1121206SXin LI 				font_height = cur_info.console_info.font_size;
818f1121206SXin LI 
819f1121206SXin LI 			size[2] = font_height;
820f1121206SXin LI 
821f1121206SXin LI 			/* adjust columns */
822f1121206SXin LI 
823f1121206SXin LI 			if ((vesa_cols * 8 > new_mode_info.vi_width) ||
824f1121206SXin LI 			    (vesa_cols <= 0)) {
825f1121206SXin LI 				size[0] = new_mode_info.vi_width / 8;
826acdb2839SMaxim Sobolev 			} else {
827acdb2839SMaxim Sobolev 				size[0] = vesa_cols;
828acdb2839SMaxim Sobolev 			}
829f1121206SXin LI 
830f1121206SXin LI 			/* adjust rows */
831f1121206SXin LI 
832f1121206SXin LI 			if ((vesa_rows * font_height > new_mode_info.vi_height) ||
833acdb2839SMaxim Sobolev 			    (vesa_rows <= 0)) {
834f1121206SXin LI 				size[1] = new_mode_info.vi_height /
835f1121206SXin LI 					  font_height;
836acdb2839SMaxim Sobolev 			} else {
837acdb2839SMaxim Sobolev 				size[1] = vesa_rows;
838acdb2839SMaxim Sobolev 			}
839f1121206SXin LI 
840f1121206SXin LI 			/* set raster mode */
841f1121206SXin LI 
842ac80d4b4SKazutaka YOKOTA 			if (ioctl(0, KDRASTER, size)) {
8432b881cf4SBruce Evans 				save_errno = errno;
844ac80d4b4SKazutaka YOKOTA 				if (cur_mode >= M_VESA_BASE)
845e64c88b2SKazutaka YOKOTA 					ioctl(0,
846e64c88b2SKazutaka YOKOTA 					    _IO('V', cur_mode - M_VESA_BASE),
847e64c88b2SKazutaka YOKOTA 					    NULL);
848ac80d4b4SKazutaka YOKOTA 				else
849ac80d4b4SKazutaka YOKOTA 					ioctl(0, _IO('S', cur_mode), NULL);
850f1121206SXin LI 				revert();
8512b881cf4SBruce Evans 				errno = save_errno;
8522b881cf4SBruce Evans 				err(1, "cannot activate raster display");
853ac80d4b4SKazutaka YOKOTA 			}
854a8445737SSøren Schmidt 		}
855f1121206SXin LI 
8561b8c842eSBruce Evans 		/* Recover from mode setting forgetting colors. */
8571b8c842eSBruce Evans 		fprintf(stderr, "\033[=%dF",
8581b8c842eSBruce Evans 		    cur_info.console_info.mv_norm.fore);
8591b8c842eSBruce Evans 		fprintf(stderr, "\033[=%dG",
8601b8c842eSBruce Evans 		    cur_info.console_info.mv_norm.back);
861f1121206SXin LI 
862f1121206SXin LI 		(*mode_index)++;
8637363955dSSøren Schmidt 	}
8647363955dSSøren Schmidt }
8657363955dSSøren Schmidt 
866f1121206SXin LI 
867f1121206SXin LI /*
868f1121206SXin LI  * Return the number for a specified color name.
869f1121206SXin LI  */
870f1121206SXin LI 
8719a03b27dSXin LI static int
get_color_number(char * color)8727363955dSSøren Schmidt get_color_number(char *color)
8737363955dSSøren Schmidt {
8747363955dSSøren Schmidt 	int i;
8757363955dSSøren Schmidt 
876f1121206SXin LI 	for (i=0; i<16; i++) {
8777363955dSSøren Schmidt 		if (!strcmp(color, legal_colors[i]))
8787363955dSSøren Schmidt 			return i;
879f1121206SXin LI 	}
8807363955dSSøren Schmidt 	return -1;
8817363955dSSøren Schmidt }
8827363955dSSøren Schmidt 
883f1121206SXin LI 
884f1121206SXin LI /*
8851b8c842eSBruce Evans  * Set normal text and background colors.
886f1121206SXin LI  */
887f1121206SXin LI 
8889a03b27dSXin LI static void
set_normal_colors(int argc,char ** argv,int * _index)8891b8c842eSBruce Evans set_normal_colors(int argc, char **argv, int *_index)
8907363955dSSøren Schmidt {
8917363955dSSøren Schmidt 	int color;
8927363955dSSøren Schmidt 
8939a03b27dSXin LI 	if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) {
8949a03b27dSXin LI 		(*_index)++;
8955ad9a2d7SYoshihiro Takahashi 		fprintf(stderr, "\033[=%dF", color);
8969a03b27dSXin LI 		if (*_index < argc
89712dd1cd3SBruce Evans 		    && (color = get_color_number(argv[*_index])) != -1) {
8989a03b27dSXin LI 			(*_index)++;
8995ad9a2d7SYoshihiro Takahashi 			fprintf(stderr, "\033[=%dG", color);
9007363955dSSøren Schmidt 		}
9017363955dSSøren Schmidt 	}
9027363955dSSøren Schmidt }
9037363955dSSøren Schmidt 
904f1121206SXin LI 
905f1121206SXin LI /*
9061b8c842eSBruce Evans  * Set reverse text and background colors.
907f1121206SXin LI  */
908f1121206SXin LI 
9099a03b27dSXin LI static void
set_reverse_colors(int argc,char ** argv,int * _index)9101b8c842eSBruce Evans set_reverse_colors(int argc, char **argv, int *_index)
9117363955dSSøren Schmidt {
9127363955dSSøren Schmidt 	int color;
9137363955dSSøren Schmidt 
9149a03b27dSXin LI 	if ((color = get_color_number(argv[*(_index)-1])) != -1) {
9155ad9a2d7SYoshihiro Takahashi 		fprintf(stderr, "\033[=%dH", color);
9169a03b27dSXin LI 		if (*_index < argc
91712dd1cd3SBruce Evans 		    && (color = get_color_number(argv[*_index])) != -1) {
9189a03b27dSXin LI 			(*_index)++;
9195ad9a2d7SYoshihiro Takahashi 			fprintf(stderr, "\033[=%dI", color);
9207363955dSSøren Schmidt 		}
9217363955dSSøren Schmidt 	}
9227363955dSSøren Schmidt }
9237363955dSSøren Schmidt 
924f1121206SXin LI 
925f1121206SXin LI /*
926f1121206SXin LI  * Switch to virtual terminal #arg.
927f1121206SXin LI  */
928f1121206SXin LI 
9299a03b27dSXin LI static void
set_console(char * arg)930bfc214e3SBrian Somers set_console(char *arg)
931bfc214e3SBrian Somers {
932bfc214e3SBrian Somers 	int n;
933bfc214e3SBrian Somers 
934bfc214e3SBrian Somers 	if(!arg || strspn(arg,"0123456789") != strlen(arg)) {
935f1121206SXin LI 		revert();
936f1121206SXin LI 		errx(1, "bad console number");
937bfc214e3SBrian Somers 	}
938bfc214e3SBrian Somers 
939bfc214e3SBrian Somers 	n = atoi(arg);
940f1121206SXin LI 
941a0d3b21cSKazutaka YOKOTA 	if (n < 1 || n > 16) {
942f1121206SXin LI 		revert();
943f1121206SXin LI 		errx(1, "console number out of range");
944eb0fa6f5SRuslan Ermilov 	} else if (ioctl(0, VT_ACTIVATE, n) == -1) {
945f1121206SXin LI 		revert();
9462b881cf4SBruce Evans 		err(1, "switching vty");
947bfc214e3SBrian Somers 	}
948f1121206SXin LI }
949f1121206SXin LI 
950f1121206SXin LI 
951f1121206SXin LI /*
952f1121206SXin LI  * Sets the border color.
953f1121206SXin LI  */
954bfc214e3SBrian Somers 
9559a03b27dSXin LI static void
set_border_color(char * arg)9567363955dSSøren Schmidt set_border_color(char *arg)
9577363955dSSøren Schmidt {
9587363955dSSøren Schmidt 	int color;
9597363955dSSøren Schmidt 
96003096857SBruce Evans 	color = get_color_number(arg);
96103096857SBruce Evans 	if (color == -1) {
96203096857SBruce Evans 		revert();
96303096857SBruce Evans 		errx(1, "invalid color '%s'", arg);
9647363955dSSøren Schmidt 	}
96503096857SBruce Evans 	if (ioctl(0, KDSBORDER, color) != 0) {
96603096857SBruce Evans 		revert();
96703096857SBruce Evans 		err(1, "ioctl(KD_SBORDER)");
96803096857SBruce Evans 	}
9697363955dSSøren Schmidt }
9707363955dSSøren Schmidt 
9719a03b27dSXin LI static void
set_mouse_char(char * arg)972e2f29c6eSKazutaka YOKOTA set_mouse_char(char *arg)
973e2f29c6eSKazutaka YOKOTA {
974e2f29c6eSKazutaka YOKOTA 	struct mouse_info mouse;
975e2f29c6eSKazutaka YOKOTA 	long l;
976e2f29c6eSKazutaka YOKOTA 
977e2f29c6eSKazutaka YOKOTA 	l = strtol(arg, NULL, 0);
978f1121206SXin LI 
979e4ef2fa2SAndrey A. Chernov 	if ((l < 0) || (l > UCHAR_MAX - 3)) {
980f1121206SXin LI 		revert();
981e4ef2fa2SAndrey A. Chernov 		warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3);
982e2f29c6eSKazutaka YOKOTA 		return;
983e2f29c6eSKazutaka YOKOTA 	}
984f1121206SXin LI 
985e2f29c6eSKazutaka YOKOTA 	mouse.operation = MOUSE_MOUSECHAR;
986e2f29c6eSKazutaka YOKOTA 	mouse.u.mouse_char = (int)l;
987f1121206SXin LI 
988f1121206SXin LI 	if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) {
989f1121206SXin LI 		revert();
9902b881cf4SBruce Evans 		err(1, "setting mouse character");
991e2f29c6eSKazutaka YOKOTA 	}
992f1121206SXin LI }
993f1121206SXin LI 
994f1121206SXin LI 
995f1121206SXin LI /*
996f1121206SXin LI  * Show/hide the mouse.
997f1121206SXin LI  */
998e2f29c6eSKazutaka YOKOTA 
9999a03b27dSXin LI static void
set_mouse(char * arg)1000bfa09c9cSSøren Schmidt set_mouse(char *arg)
1001bfa09c9cSSøren Schmidt {
1002bfa09c9cSSøren Schmidt 	struct mouse_info mouse;
1003bfa09c9cSSøren Schmidt 
1004f1121206SXin LI 	if (!strcmp(arg, "on")) {
1005bfa09c9cSSøren Schmidt 		mouse.operation = MOUSE_SHOW;
1006f1121206SXin LI 	} else if (!strcmp(arg, "off")) {
1007bfa09c9cSSøren Schmidt 		mouse.operation = MOUSE_HIDE;
1008f1121206SXin LI 	} else {
1009f1121206SXin LI 		revert();
1010f1121206SXin LI 		errx(1, "argument to -m must be either on or off");
1011bfa09c9cSSøren Schmidt 	}
1012f1121206SXin LI 
1013f1121206SXin LI 	if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) {
1014f1121206SXin LI 		revert();
10152b881cf4SBruce Evans 		err(1, "%sing the mouse",
1016f1121206SXin LI 		     mouse.operation == MOUSE_SHOW ? "show" : "hid");
1017bfa09c9cSSøren Schmidt 	}
1018f1121206SXin LI }
1019f1121206SXin LI 
1020bfa09c9cSSøren Schmidt 
10219a03b27dSXin LI static void
set_lockswitch(char * arg)1022b471ed9eSDima Dorfman set_lockswitch(char *arg)
1023b471ed9eSDima Dorfman {
1024b471ed9eSDima Dorfman 	int data;
1025b471ed9eSDima Dorfman 
1026f1121206SXin LI 	if (!strcmp(arg, "off")) {
1027b471ed9eSDima Dorfman 		data = 0x01;
1028f1121206SXin LI 	} else if (!strcmp(arg, "on")) {
1029b471ed9eSDima Dorfman 		data = 0x02;
1030f1121206SXin LI 	} else {
1031f1121206SXin LI 		revert();
1032f1121206SXin LI 		errx(1, "argument to -S must be either on or off");
1033b471ed9eSDima Dorfman 	}
1034f1121206SXin LI 
1035f1121206SXin LI 	if (ioctl(0, VT_LOCKSWITCH, &data) == -1) {
1036f1121206SXin LI 		revert();
10372b881cf4SBruce Evans 		err(1, "turning %s vty switching",
1038f1121206SXin LI 		     data == 0x01 ? "off" : "on");
1039b471ed9eSDima Dorfman 	}
1040f1121206SXin LI }
1041f1121206SXin LI 
1042f1121206SXin LI 
1043f1121206SXin LI /*
1044f1121206SXin LI  * Return the adapter name for a specified type.
1045f1121206SXin LI  */
1046b471ed9eSDima Dorfman 
10479a03b27dSXin LI static const char
adapter_name(int type)1048a8445737SSøren Schmidt *adapter_name(int type)
1049a8445737SSøren Schmidt {
1050a8445737SSøren Schmidt     static struct {
1051a8445737SSøren Schmidt 	int type;
10529a03b27dSXin LI 	const char *name;
1053a8445737SSøren Schmidt     } names[] = {
1054a8445737SSøren Schmidt 	{ KD_MONO,	"MDA" },
1055a8445737SSøren Schmidt 	{ KD_HERCULES,	"Hercules" },
1056a8445737SSøren Schmidt 	{ KD_CGA,	"CGA" },
1057a8445737SSøren Schmidt 	{ KD_EGA,	"EGA" },
1058a8445737SSøren Schmidt 	{ KD_VGA,	"VGA" },
1059ac80d4b4SKazutaka YOKOTA 	{ KD_TGA,	"TGA" },
1060a8445737SSøren Schmidt 	{ -1,		"Unknown" },
1061a8445737SSøren Schmidt     };
1062f1121206SXin LI 
1063a8445737SSøren Schmidt     int i;
1064a8445737SSøren Schmidt 
1065a8445737SSøren Schmidt     for (i = 0; names[i].type != -1; ++i)
1066a8445737SSøren Schmidt 	if (names[i].type == type)
1067a8445737SSøren Schmidt 	    break;
1068a8445737SSøren Schmidt     return names[i].name;
1069a8445737SSøren Schmidt }
1070a8445737SSøren Schmidt 
1071f1121206SXin LI 
1072f1121206SXin LI /*
1073449d10e5SEdward Tomasz Napierala  * Show active VTY, ie current console number.
1074449d10e5SEdward Tomasz Napierala  */
1075449d10e5SEdward Tomasz Napierala 
1076449d10e5SEdward Tomasz Napierala static void
show_active_info(void)1077449d10e5SEdward Tomasz Napierala show_active_info(void)
1078449d10e5SEdward Tomasz Napierala {
1079449d10e5SEdward Tomasz Napierala 
1080449d10e5SEdward Tomasz Napierala 	printf("%d\n", cur_info.active_vty);
1081449d10e5SEdward Tomasz Napierala }
1082449d10e5SEdward Tomasz Napierala 
1083449d10e5SEdward Tomasz Napierala 
1084449d10e5SEdward Tomasz Napierala /*
1085f1121206SXin LI  * Show graphics adapter information.
1086f1121206SXin LI  */
1087f1121206SXin LI 
10889a03b27dSXin LI static void
show_adapter_info(void)1089a8445737SSøren Schmidt show_adapter_info(void)
1090a8445737SSøren Schmidt {
1091c67e8bd3SKazutaka YOKOTA 	struct video_adapter_info ad;
1092a8445737SSøren Schmidt 
1093a8445737SSøren Schmidt 	ad.va_index = 0;
1094f1121206SXin LI 
1095f1121206SXin LI 	if (ioctl(0, CONS_ADPINFO, &ad) == -1) {
1096f1121206SXin LI 		revert();
10972b881cf4SBruce Evans 		err(1, "obtaining adapter information");
1098a8445737SSøren Schmidt 	}
1099a8445737SSøren Schmidt 
1100c67e8bd3SKazutaka YOKOTA 	printf("fb%d:\n", ad.va_index);
1101c67e8bd3SKazutaka YOKOTA 	printf("    %.*s%d, type:%s%s (%d), flags:0x%x\n",
1102c67e8bd3SKazutaka YOKOTA 	       (int)sizeof(ad.va_name), ad.va_name, ad.va_unit,
1103a8445737SSøren Schmidt 	       (ad.va_flags & V_ADP_VESA) ? "VESA " : "",
1104c67e8bd3SKazutaka YOKOTA 	       adapter_name(ad.va_type), ad.va_type, ad.va_flags);
1105a8445737SSøren Schmidt 	printf("    initial mode:%d, current mode:%d, BIOS mode:%d\n",
1106a8445737SSøren Schmidt 	       ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode);
11079a03b27dSXin LI 	printf("    frame buffer window:0x%zx, buffer size:0x%zx\n",
1108ac80d4b4SKazutaka YOKOTA 	       ad.va_window, ad.va_buffer_size);
11099a03b27dSXin LI 	printf("    window size:0x%zx, origin:0x%x\n",
1110ac80d4b4SKazutaka YOKOTA 	       ad.va_window_size, ad.va_window_orig);
1111ac80d4b4SKazutaka YOKOTA 	printf("    display start address (%d, %d), scan line width:%d\n",
1112ac80d4b4SKazutaka YOKOTA 	       ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width);
11139a03b27dSXin LI 	printf("    reserved:0x%zx\n", ad.va_unused0);
1114a8445737SSøren Schmidt }
1115a8445737SSøren Schmidt 
1116f1121206SXin LI 
1117f1121206SXin LI /*
1118f1121206SXin LI  * Show video mode information.
1119f1121206SXin LI  */
1120f1121206SXin LI 
11219a03b27dSXin LI static void
show_mode_info(void)1122a8445737SSøren Schmidt show_mode_info(void)
1123a8445737SSøren Schmidt {
1124a8445737SSøren Schmidt 	char buf[80];
11258f92a81bSBruce Evans 	struct video_info info;
1126a8445737SSøren Schmidt 	int c;
1127f46f4ae1SJung-uk Kim 	int mm;
1128f46f4ae1SJung-uk Kim 	int mode;
1129a8445737SSøren Schmidt 
1130a8445737SSøren Schmidt 	printf("    mode#     flags   type    size       "
1131a8445737SSøren Schmidt 	       "font      window      linear buffer\n");
1132a8445737SSøren Schmidt 	printf("---------------------------------------"
1133a8445737SSøren Schmidt 	       "---------------------------------------\n");
1134f1121206SXin LI 
11358f92a81bSBruce Evans 	memset(&info, 0, sizeof(info));
1136a8de143cSEitan Adler 	for (mode = 0; mode <= M_VESA_MODE_MAX; ++mode) {
11378f92a81bSBruce Evans 		info.vi_mode = mode;
11388f92a81bSBruce Evans 		if (ioctl(0, CONS_MODEINFO, &info))
1139a8445737SSøren Schmidt 			continue;
11408f92a81bSBruce Evans 		if (info.vi_mode != mode)
1141ac80d4b4SKazutaka YOKOTA 			continue;
11428f92a81bSBruce Evans 		if (info.vi_width == 0 && info.vi_height == 0 &&
11438f92a81bSBruce Evans 		    info.vi_cwidth == 0 && info.vi_cheight == 0)
114416028f6aSEd Maste 			continue;
1145a8445737SSøren Schmidt 
1146a8445737SSøren Schmidt 		printf("%3d (0x%03x)", mode, mode);
11478f92a81bSBruce Evans     		printf(" 0x%08x", info.vi_flags);
11488f92a81bSBruce Evans 		if (info.vi_flags & V_INFO_GRAPHICS) {
1149a8445737SSøren Schmidt 			c = 'G';
1150f1121206SXin LI 
11518f92a81bSBruce Evans 			if (info.vi_mem_model == V_INFO_MM_PLANAR)
1152a8445737SSøren Schmidt 				snprintf(buf, sizeof(buf), "%dx%dx%d %d",
11538f92a81bSBruce Evans 				    info.vi_width, info.vi_height,
11548f92a81bSBruce Evans 				    info.vi_depth, info.vi_planes);
1155f46f4ae1SJung-uk Kim 			else {
11568f92a81bSBruce Evans 				switch (info.vi_mem_model) {
1157f46f4ae1SJung-uk Kim 				case V_INFO_MM_PACKED:
1158f46f4ae1SJung-uk Kim 					mm = 'P';
1159f46f4ae1SJung-uk Kim 					break;
1160f46f4ae1SJung-uk Kim 				case V_INFO_MM_DIRECT:
1161f46f4ae1SJung-uk Kim 					mm = 'D';
1162f46f4ae1SJung-uk Kim 					break;
1163f46f4ae1SJung-uk Kim 				case V_INFO_MM_CGA:
1164f46f4ae1SJung-uk Kim 					mm = 'C';
1165f46f4ae1SJung-uk Kim 					break;
1166f46f4ae1SJung-uk Kim 				case V_INFO_MM_HGC:
1167f46f4ae1SJung-uk Kim 					mm = 'H';
1168f46f4ae1SJung-uk Kim 					break;
1169f46f4ae1SJung-uk Kim 				case V_INFO_MM_VGAX:
1170f46f4ae1SJung-uk Kim 					mm = 'V';
1171f46f4ae1SJung-uk Kim 					break;
1172f46f4ae1SJung-uk Kim 				default:
1173f46f4ae1SJung-uk Kim 					mm = ' ';
1174f46f4ae1SJung-uk Kim 					break;
1175f46f4ae1SJung-uk Kim 				}
1176f46f4ae1SJung-uk Kim 				snprintf(buf, sizeof(buf), "%dx%dx%d %c",
11778f92a81bSBruce Evans 				    info.vi_width, info.vi_height,
11788f92a81bSBruce Evans 				    info.vi_depth, mm);
1179f46f4ae1SJung-uk Kim 			}
1180a8445737SSøren Schmidt 		} else {
1181a8445737SSøren Schmidt 			c = 'T';
1182f1121206SXin LI 
1183a8445737SSøren Schmidt 			snprintf(buf, sizeof(buf), "%dx%d",
11848f92a81bSBruce Evans 				 info.vi_width, info.vi_height);
1185a8445737SSøren Schmidt 		}
1186f1121206SXin LI 
1187a8445737SSøren Schmidt 		printf(" %c %-15s", c, buf);
1188a8445737SSøren Schmidt 		snprintf(buf, sizeof(buf), "%dx%d",
11898f92a81bSBruce Evans 			 info.vi_cwidth, info.vi_cheight);
1190a8445737SSøren Schmidt 		printf(" %-5s", buf);
11919a03b27dSXin LI     		printf(" 0x%05zx %2dk %2dk",
11928f92a81bSBruce Evans 		       info.vi_window, (int)info.vi_window_size/1024,
11938f92a81bSBruce Evans 		       (int)info.vi_window_gran/1024);
11949a03b27dSXin LI     		printf(" 0x%08zx %dk\n",
11958f92a81bSBruce Evans 		       info.vi_buffer, (int)info.vi_buffer_size/1024);
1196a8445737SSøren Schmidt 	}
1197a8445737SSøren Schmidt }
1198a8445737SSøren Schmidt 
1199f1121206SXin LI 
12009a03b27dSXin LI static void
show_info(char * arg)1201a8445737SSøren Schmidt show_info(char *arg)
1202a8445737SSøren Schmidt {
1203449d10e5SEdward Tomasz Napierala 
1204449d10e5SEdward Tomasz Napierala 	if (!strcmp(arg, "active")) {
1205449d10e5SEdward Tomasz Napierala 		show_active_info();
1206449d10e5SEdward Tomasz Napierala 	} else if (!strcmp(arg, "adapter")) {
1207a8445737SSøren Schmidt 		show_adapter_info();
1208f1121206SXin LI 	} else if (!strcmp(arg, "mode")) {
1209a8445737SSøren Schmidt 		show_mode_info();
1210f1121206SXin LI 	} else {
1211f1121206SXin LI 		revert();
1212449d10e5SEdward Tomasz Napierala 		errx(1, "argument to -i must be active, adapter, or mode");
1213a8445737SSøren Schmidt 	}
1214a8445737SSøren Schmidt }
1215a8445737SSøren Schmidt 
1216f1121206SXin LI 
12179a03b27dSXin LI static void
test_frame(void)12189a03b27dSXin LI test_frame(void)
12197363955dSSøren Schmidt {
12208f92a81bSBruce Evans 	vid_info_t info;
12216be33b83SBruce Evans 	const char *bg, *sep;
12222b375b4eSYoshihiro Takahashi 	int i, fore;
1223947d66c0SYoshihiro Takahashi 
12248f92a81bSBruce Evans 	info.size = sizeof(info);
12258f92a81bSBruce Evans 	if (ioctl(0, CONS_GETINFO, &info) == -1)
12268f92a81bSBruce Evans 		err(1, "getting console information");
12278f92a81bSBruce Evans 
1228947d66c0SYoshihiro Takahashi 	fore = 15;
1229b60e1b81SBruce Evans 	if (info.mv_csz < 80) {
1230b60e1b81SBruce Evans 		bg = "BG";
1231b60e1b81SBruce Evans 		sep = " ";
1232b60e1b81SBruce Evans 	} else {
1233b60e1b81SBruce Evans 		bg = "BACKGROUND";
1234b60e1b81SBruce Evans 		sep = "    ";
1235b60e1b81SBruce Evans 	}
1236947d66c0SYoshihiro Takahashi 
12375ad9a2d7SYoshihiro Takahashi 	fprintf(stdout, "\033[=0G\n\n");
12387363955dSSøren Schmidt 	for (i=0; i<8; i++) {
1239b60e1b81SBruce Evans 		fprintf(stdout,
1240b60e1b81SBruce Evans 		    "\033[=%dF\033[=0G%2d \033[=%dF%-7s%s"
1241b60e1b81SBruce Evans 		    "\033[=%dF\033[=0G%2d \033[=%dF%-12s%s"
1242b60e1b81SBruce Evans 		    "\033[=%dF%2d \033[=%dG%s\033[=0G%s"
1243b60e1b81SBruce Evans 		    "\033[=%dF%2d \033[=%dG%s\033[=0G\n",
1244b60e1b81SBruce Evans 		    fore, i, i, legal_colors[i], sep,
1245b60e1b81SBruce Evans 		    fore, i + 8, i + 8, legal_colors[i + 8], sep,
1246b60e1b81SBruce Evans 		    fore, i, i, bg, sep,
1247b60e1b81SBruce Evans 		    fore, i + 8, i + 8, bg);
12487363955dSSøren Schmidt 	}
12495ad9a2d7SYoshihiro Takahashi 	fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n",
12507363955dSSøren Schmidt 		info.mv_norm.fore, info.mv_norm.back,
12517363955dSSøren Schmidt 		info.mv_rev.fore, info.mv_rev.back);
12527363955dSSøren Schmidt }
12537363955dSSøren Schmidt 
1254f1121206SXin LI 
1255d02ca551SMaxim Sobolev /*
1256d02ca551SMaxim Sobolev  * Snapshot the video memory of that terminal, using the CONS_SCRSHOT
1257d02ca551SMaxim Sobolev  * ioctl, and writes the results to stdout either in the special
1258d02ca551SMaxim Sobolev  * binary format (see manual page for details), or in the plain
1259d02ca551SMaxim Sobolev  * text format.
1260d02ca551SMaxim Sobolev  */
1261f1121206SXin LI 
12629a03b27dSXin LI static void
dump_screen(int mode,int opt)1263c449db6aSMaxim Sobolev dump_screen(int mode, int opt)
1264d02ca551SMaxim Sobolev {
1265d02ca551SMaxim Sobolev 	scrshot_t shot;
12668f92a81bSBruce Evans 	vid_info_t info;
1267d02ca551SMaxim Sobolev 
12688f92a81bSBruce Evans 	info.size = sizeof(info);
12698f92a81bSBruce Evans 	if (ioctl(0, CONS_GETINFO, &info) == -1) {
1270f1121206SXin LI 		revert();
12718f92a81bSBruce Evans 		err(1, "getting console information");
1272d02ca551SMaxim Sobolev 	}
1273d02ca551SMaxim Sobolev 
1274c449db6aSMaxim Sobolev 	shot.x = shot.y = 0;
12758f92a81bSBruce Evans 	shot.xsize = info.mv_csz;
12768f92a81bSBruce Evans 	shot.ysize = info.mv_rsz;
1277c449db6aSMaxim Sobolev 	if (opt == DUMP_ALL)
12788f92a81bSBruce Evans 		shot.ysize += info.mv_hsz;
1279c449db6aSMaxim Sobolev 
1280c449db6aSMaxim Sobolev 	shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t));
1281d02ca551SMaxim Sobolev 	if (shot.buf == NULL) {
1282f1121206SXin LI 		revert();
1283f1121206SXin LI 		errx(1, "failed to allocate memory for dump");
1284d02ca551SMaxim Sobolev 	}
1285d02ca551SMaxim Sobolev 
1286d02ca551SMaxim Sobolev 	if (ioctl(0, CONS_SCRSHOT, &shot) == -1) {
1287f1121206SXin LI 		revert();
12882b881cf4SBruce Evans 		err(1, "dumping screen");
1289d02ca551SMaxim Sobolev 	}
1290d02ca551SMaxim Sobolev 
1291c449db6aSMaxim Sobolev 	if (mode == DUMP_FMT_RAW) {
1292d02ca551SMaxim Sobolev 		printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2,
1293d02ca551SMaxim Sobolev 		       shot.xsize, shot.ysize);
1294f1121206SXin LI 
1295d02ca551SMaxim Sobolev 		fflush(stdout);
1296d02ca551SMaxim Sobolev 
1297f1121206SXin LI 		write(STDOUT_FILENO, shot.buf,
1298d02ca551SMaxim Sobolev 		      shot.xsize * shot.ysize * sizeof(u_int16_t));
1299d02ca551SMaxim Sobolev 	} else {
1300d02ca551SMaxim Sobolev 		char *line;
1301d02ca551SMaxim Sobolev 		int x, y;
1302d02ca551SMaxim Sobolev 		u_int16_t ch;
1303d02ca551SMaxim Sobolev 
1304d02ca551SMaxim Sobolev 		line = alloca(shot.xsize + 1);
1305f1121206SXin LI 
1306d02ca551SMaxim Sobolev 		if (line == NULL) {
1307f1121206SXin LI 			revert();
1308f1121206SXin LI 			errx(1, "failed to allocate memory for line buffer");
1309d02ca551SMaxim Sobolev 		}
1310d02ca551SMaxim Sobolev 
1311d02ca551SMaxim Sobolev 		for (y = 0; y < shot.ysize; y++) {
1312d02ca551SMaxim Sobolev 			for (x = 0; x < shot.xsize; x++) {
1313d02ca551SMaxim Sobolev 				ch = shot.buf[x + (y * shot.xsize)];
1314d02ca551SMaxim Sobolev 				ch &= 0xff;
1315f1121206SXin LI 
1316d02ca551SMaxim Sobolev 				if (isprint(ch) == 0)
1317d02ca551SMaxim Sobolev 					ch = ' ';
1318f1121206SXin LI 
1319d02ca551SMaxim Sobolev 				line[x] = (char)ch;
1320d02ca551SMaxim Sobolev 			}
1321d02ca551SMaxim Sobolev 
1322d02ca551SMaxim Sobolev 			/* Trim trailing spaces */
1323f1121206SXin LI 
1324d02ca551SMaxim Sobolev 			do {
1325d02ca551SMaxim Sobolev 				line[x--] = '\0';
1326d02ca551SMaxim Sobolev 			} while (line[x] == ' ' && x != 0);
1327d02ca551SMaxim Sobolev 
1328d02ca551SMaxim Sobolev 			puts(line);
1329d02ca551SMaxim Sobolev 		}
1330f1121206SXin LI 
1331d02ca551SMaxim Sobolev 		fflush(stdout);
1332d02ca551SMaxim Sobolev 	}
1333d02ca551SMaxim Sobolev }
1334d02ca551SMaxim Sobolev 
1335f1121206SXin LI 
1336f1121206SXin LI /*
1337f1121206SXin LI  * Set the console history buffer size.
1338f1121206SXin LI  */
1339f1121206SXin LI 
13409a03b27dSXin LI static void
set_history(char * opt)1341031c57afSDag-Erling Smørgrav set_history(char *opt)
1342031c57afSDag-Erling Smørgrav {
1343031c57afSDag-Erling Smørgrav 	int size;
1344031c57afSDag-Erling Smørgrav 
1345031c57afSDag-Erling Smørgrav 	size = atoi(opt);
1346f1121206SXin LI 
1347031c57afSDag-Erling Smørgrav 	if ((*opt == '\0') || size < 0) {
1348f1121206SXin LI 		revert();
134982edb108SEd Maste 		errx(1, "argument must not be less than zero");
1350031c57afSDag-Erling Smørgrav 	}
1351f1121206SXin LI 
1352f1121206SXin LI 	if (ioctl(0, CONS_HISTORY, &size) == -1) {
1353f1121206SXin LI 		revert();
13542b881cf4SBruce Evans 		err(1, "setting history buffer size");
1355031c57afSDag-Erling Smørgrav 	}
1356f1121206SXin LI }
1357f1121206SXin LI 
1358f1121206SXin LI 
1359f1121206SXin LI /*
1360f1121206SXin LI  * Clear the console history buffer.
1361f1121206SXin LI  */
1362031c57afSDag-Erling Smørgrav 
13639a03b27dSXin LI static void
clear_history(void)13649a03b27dSXin LI clear_history(void)
1365031c57afSDag-Erling Smørgrav {
1366f1121206SXin LI 	if (ioctl(0, CONS_CLRHIST) == -1) {
1367f1121206SXin LI 		revert();
13682b881cf4SBruce Evans 		err(1, "clearing history buffer");
1369031c57afSDag-Erling Smørgrav 	}
1370f1121206SXin LI }
1371f1121206SXin LI 
1372d09131e0SBruce Evans static int
get_terminal_emulator(int i,struct term_info * tip)1373d09131e0SBruce Evans get_terminal_emulator(int i, struct term_info *tip)
1374d09131e0SBruce Evans {
1375d09131e0SBruce Evans 	tip->ti_index = i;
1376d09131e0SBruce Evans 	if (ioctl(0, CONS_GETTERM, tip) == 0)
1377d09131e0SBruce Evans 		return (1);
13784138acc5SBruce Evans 	strlcpy((char *)tip->ti_name, "unknown", sizeof(tip->ti_name));
13794138acc5SBruce Evans 	strlcpy((char *)tip->ti_desc, "unknown", sizeof(tip->ti_desc));
1380d09131e0SBruce Evans 	return (0);
1381d09131e0SBruce Evans }
1382d09131e0SBruce Evans 
1383d09131e0SBruce Evans static void
get_terminal_emulators(void)1384d09131e0SBruce Evans get_terminal_emulators(void)
1385d09131e0SBruce Evans {
1386d09131e0SBruce Evans 	struct term_info ti;
1387d09131e0SBruce Evans 	int i;
1388d09131e0SBruce Evans 
1389d09131e0SBruce Evans 	for (i = 0; i < 10; i++) {
1390d09131e0SBruce Evans 		if (get_terminal_emulator(i, &ti) == 0)
1391d09131e0SBruce Evans 			break;
1392d09131e0SBruce Evans 		printf("%d: %s (%s)%s\n", i, ti.ti_name, ti.ti_desc,
1393d09131e0SBruce Evans 		    i == 0 ? " (active)" : "");
1394d09131e0SBruce Evans 	}
1395d09131e0SBruce Evans }
1396d09131e0SBruce Evans 
1397d09131e0SBruce Evans static void
set_terminal_emulator(const char * name)1398d09131e0SBruce Evans set_terminal_emulator(const char *name)
1399d09131e0SBruce Evans {
1400d09131e0SBruce Evans 	struct term_info old_ti, ti;
1401d09131e0SBruce Evans 
1402d09131e0SBruce Evans 	get_terminal_emulator(0, &old_ti);
14034138acc5SBruce Evans 	strlcpy((char *)ti.ti_name, name, sizeof(ti.ti_name));
1404d09131e0SBruce Evans 	if (ioctl(0, CONS_SETTERM, &ti) != 0)
1405d09131e0SBruce Evans 		warn("SETTERM '%s'", name);
1406d09131e0SBruce Evans 	get_terminal_emulator(0, &ti);
1407d09131e0SBruce Evans 	printf("%s (%s) -> %s (%s)\n", old_ti.ti_name, old_ti.ti_desc,
1408d09131e0SBruce Evans 	    ti.ti_name, ti.ti_desc);
1409d09131e0SBruce Evans }
1410d09131e0SBruce Evans 
1411c8f1c817SEd Schouten static void
set_terminal_mode(char * arg)1412c8f1c817SEd Schouten set_terminal_mode(char *arg)
1413c8f1c817SEd Schouten {
1414c8f1c817SEd Schouten 
1415c8f1c817SEd Schouten 	if (strcmp(arg, "xterm") == 0)
1416c8f1c817SEd Schouten 		fprintf(stderr, "\033[=T");
1417c8f1c817SEd Schouten 	else if (strcmp(arg, "cons25") == 0)
1418c8f1c817SEd Schouten 		fprintf(stderr, "\033[=1T");
1419c8f1c817SEd Schouten }
1420c8f1c817SEd Schouten 
1421031c57afSDag-Erling Smørgrav 
1422bfc214e3SBrian Somers int
main(int argc,char ** argv)14237363955dSSøren Schmidt main(int argc, char **argv)
14247363955dSSøren Schmidt {
1425436f6474SAndrey A. Chernov 	char    *font, *type, *termmode;
142630bf10efSAleksandr Rybalko 	const char *opts;
1427c449db6aSMaxim Sobolev 	int	dumpmod, dumpopt, opt;
14287363955dSSøren Schmidt 
142930bf10efSAleksandr Rybalko 	vt4_mode = is_vt4();
143030bf10efSAleksandr Rybalko 
1431f1121206SXin LI 	init();
1432f1121206SXin LI 
1433c449db6aSMaxim Sobolev 	dumpmod = 0;
1434c449db6aSMaxim Sobolev 	dumpopt = DUMP_FBF;
1435436f6474SAndrey A. Chernov 	termmode = NULL;
143630bf10efSAleksandr Rybalko 	if (vt4_mode)
1437*c71ae91fSEd Maste 		opts = "b:Cc:fg:h:i:M:m:r:S:s:T:t:x";
143830bf10efSAleksandr Rybalko 	else
1439d09131e0SBruce Evans 		opts = "b:Cc:deE:fg:h:Hi:l:LM:m:pPr:S:s:T:t:x";
144030bf10efSAleksandr Rybalko 
144130bf10efSAleksandr Rybalko 	while ((opt = getopt(argc, argv, opts)) != -1)
14427363955dSSøren Schmidt 		switch(opt) {
14437363955dSSøren Schmidt 		case 'b':
14447363955dSSøren Schmidt 			set_border_color(optarg);
14457363955dSSøren Schmidt 			break;
1446031c57afSDag-Erling Smørgrav 		case 'C':
1447031c57afSDag-Erling Smørgrav 			clear_history();
1448031c57afSDag-Erling Smørgrav 			break;
1449bfa09c9cSSøren Schmidt 		case 'c':
1450bfa09c9cSSøren Schmidt 			set_cursor_type(optarg);
1451bfa09c9cSSøren Schmidt 			break;
14527363955dSSøren Schmidt 		case 'd':
145330bf10efSAleksandr Rybalko 			if (vt4_mode)
145430bf10efSAleksandr Rybalko 				break;
14557363955dSSøren Schmidt 			print_scrnmap();
14567363955dSSøren Schmidt 			break;
1457d09131e0SBruce Evans 		case 'E':
1458d09131e0SBruce Evans 			if (vt4_mode)
1459d09131e0SBruce Evans 				break;
1460d09131e0SBruce Evans 			set_terminal_emulator(optarg);
1461d09131e0SBruce Evans 			break;
1462d09131e0SBruce Evans 		case 'e':
1463d09131e0SBruce Evans 			if (vt4_mode)
1464d09131e0SBruce Evans 				break;
1465d09131e0SBruce Evans 			get_terminal_emulators();
1466d09131e0SBruce Evans 			break;
14677363955dSSøren Schmidt 		case 'f':
1468069f1c25SJean-Sébastien Pédron 			optarg = nextarg(argc, argv, &optind, 'f', 0);
1469069f1c25SJean-Sébastien Pédron 			if (optarg != NULL) {
14705e0db936SMaxim Sobolev 				font = nextarg(argc, argv, &optind, 'f', 0);
1471f1121206SXin LI 
14725e0db936SMaxim Sobolev 				if (font == NULL) {
14735e0db936SMaxim Sobolev 					type = NULL;
14745e0db936SMaxim Sobolev 					font = optarg;
1475069f1c25SJean-Sébastien Pédron 				} else
1476069f1c25SJean-Sébastien Pédron 					type = optarg;
1477f1121206SXin LI 
14785e0db936SMaxim Sobolev 				load_font(type, font);
1479069f1c25SJean-Sébastien Pédron 			} else {
1480069f1c25SJean-Sébastien Pédron 				if (!vt4_mode)
1481069f1c25SJean-Sébastien Pédron 					usage(); /* Switch syscons to ROM? */
1482069f1c25SJean-Sébastien Pédron 
1483069f1c25SJean-Sébastien Pédron 				load_default_vt4font();
1484069f1c25SJean-Sébastien Pédron 			}
14857363955dSSøren Schmidt 			break;
1486acdb2839SMaxim Sobolev 		case 'g':
1487f1121206SXin LI 			if (sscanf(optarg, "%dx%d",
1488f1121206SXin LI 			    &vesa_cols, &vesa_rows) != 2) {
1489f1121206SXin LI 				revert();
1490acdb2839SMaxim Sobolev 				warnx("incorrect geometry: %s", optarg);
1491acdb2839SMaxim Sobolev 				usage();
1492acdb2839SMaxim Sobolev 			}
1493acdb2839SMaxim Sobolev                 	break;
1494031c57afSDag-Erling Smørgrav 		case 'h':
1495031c57afSDag-Erling Smørgrav 			set_history(optarg);
1496031c57afSDag-Erling Smørgrav 			break;
1497c449db6aSMaxim Sobolev 		case 'H':
1498c449db6aSMaxim Sobolev 			dumpopt = DUMP_ALL;
1499c449db6aSMaxim Sobolev 			break;
1500a8445737SSøren Schmidt 		case 'i':
1501a8445737SSøren Schmidt 			show_info(optarg);
1502a8445737SSøren Schmidt 			break;
15037363955dSSøren Schmidt 		case 'l':
150430bf10efSAleksandr Rybalko 			if (vt4_mode)
150530bf10efSAleksandr Rybalko 				break;
15067363955dSSøren Schmidt 			load_scrnmap(optarg);
15077363955dSSøren Schmidt 			break;
15087363955dSSøren Schmidt 		case 'L':
150930bf10efSAleksandr Rybalko 			if (vt4_mode)
151030bf10efSAleksandr Rybalko 				break;
15117363955dSSøren Schmidt 			load_default_scrnmap();
15127363955dSSøren Schmidt 			break;
1513e2f29c6eSKazutaka YOKOTA 		case 'M':
1514e2f29c6eSKazutaka YOKOTA 			set_mouse_char(optarg);
1515e2f29c6eSKazutaka YOKOTA 			break;
1516bfa09c9cSSøren Schmidt 		case 'm':
1517bfa09c9cSSøren Schmidt 			set_mouse(optarg);
1518bfa09c9cSSøren Schmidt 			break;
1519d02ca551SMaxim Sobolev 		case 'p':
1520c449db6aSMaxim Sobolev 			dumpmod = DUMP_FMT_RAW;
1521d02ca551SMaxim Sobolev 			break;
1522d02ca551SMaxim Sobolev 		case 'P':
1523c449db6aSMaxim Sobolev 			dumpmod = DUMP_FMT_TXT;
1524d02ca551SMaxim Sobolev 			break;
15257363955dSSøren Schmidt 		case 'r':
15261b8c842eSBruce Evans 			set_reverse_colors(argc, argv, &optind);
15277363955dSSøren Schmidt 			break;
1528b471ed9eSDima Dorfman 		case 'S':
1529b471ed9eSDima Dorfman 			set_lockswitch(optarg);
1530b471ed9eSDima Dorfman 			break;
1531bfc214e3SBrian Somers 		case 's':
1532bfc214e3SBrian Somers 			set_console(optarg);
1533bfc214e3SBrian Somers 			break;
1534c8f1c817SEd Schouten 		case 'T':
1535436f6474SAndrey A. Chernov 			if (strcmp(optarg, "xterm") != 0 &&
1536436f6474SAndrey A. Chernov 			    strcmp(optarg, "cons25") != 0)
1537436f6474SAndrey A. Chernov 				usage();
1538436f6474SAndrey A. Chernov 			termmode = optarg;
1539c8f1c817SEd Schouten 			break;
15407363955dSSøren Schmidt 		case 't':
15417363955dSSøren Schmidt 			set_screensaver_timeout(optarg);
15427363955dSSøren Schmidt 			break;
15437363955dSSøren Schmidt 		case 'x':
15447363955dSSøren Schmidt 			hex = 1;
15457363955dSSøren Schmidt 			break;
15467363955dSSøren Schmidt 		default:
15477363955dSSøren Schmidt 			usage();
15487363955dSSøren Schmidt 		}
1549f1121206SXin LI 
1550c449db6aSMaxim Sobolev 	if (dumpmod != 0)
1551c449db6aSMaxim Sobolev 		dump_screen(dumpmod, dumpopt);
15521b8c842eSBruce Evans 	video_mode(argc, argv, &optind);
15531b8c842eSBruce Evans 	set_normal_colors(argc, argv, &optind);
1554f1121206SXin LI 
15557363955dSSøren Schmidt 	if (optind < argc && !strcmp(argv[optind], "show")) {
15567363955dSSøren Schmidt 		test_frame();
15577363955dSSøren Schmidt 		optind++;
15587363955dSSøren Schmidt 	}
1559f1121206SXin LI 
1560436f6474SAndrey A. Chernov 	if (termmode != NULL)
1561436f6474SAndrey A. Chernov 		set_terminal_mode(termmode);
1562f1121206SXin LI 
15639396247eSPhilippe Charnier 	if ((optind != argc) || (argc == 1))
15647363955dSSøren Schmidt 		usage();
15651b8c842eSBruce Evans 	return (0);
15667363955dSSøren Schmidt }
15677363955dSSøren Schmidt 
1568