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(¶m, ",")) != 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