12089Ssos/*- 2228976Suqs * Copyright (c) 1994-1996 S��ren Schmidt 32089Ssos * All rights reserved. 42089Ssos * 5146736Sdelphij * Portions of this software are based in part on the work of 6146736Sdelphij * Sascha Wildner <saw@online.de> contributed to The DragonFly Project 7146736Sdelphij * 82089Ssos * Redistribution and use in source and binary forms, with or without 92089Ssos * modification, are permitted provided that the following conditions 102089Ssos * are met: 112089Ssos * 1. Redistributions of source code must retain the above copyright 125994Ssos * notice, this list of conditions and the following disclaimer, 135994Ssos * in this position and unchanged. 142089Ssos * 2. Redistributions in binary form must reproduce the above copyright 152089Ssos * notice, this list of conditions and the following disclaimer in the 162089Ssos * documentation and/or other materials provided with the distribution. 172089Ssos * 3. The name of the author may not be used to endorse or promote products 1897748Sschweikh * derived from this software without specific prior written permission 192089Ssos * 202089Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 212089Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 222089Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 232089Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 242089Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 252089Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 262089Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 272089Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 282089Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 292089Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30146736Sdelphij * 31146736Sdelphij * $DragonFly: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.10 2005/03/02 06:08:29 joerg Exp $ 322089Ssos */ 332089Ssos 3430764Scharnier#ifndef lint 3530764Scharnierstatic const char rcsid[] = 3650479Speter "$FreeBSD$"; 3730764Scharnier#endif /* not lint */ 3830764Scharnier 392089Ssos#include <ctype.h> 4030764Scharnier#include <err.h> 4155849Syokota#include <limits.h> 422089Ssos#include <stdio.h> 4323457Sbrian#include <stdlib.h> 4430764Scharnier#include <string.h> 4523702Speter#include <unistd.h> 4666834Sphk#include <sys/fbio.h> 4766834Sphk#include <sys/consio.h> 482089Ssos#include <sys/errno.h> 4975344Ssobomax#include <sys/types.h> 5075344Ssobomax#include <sys/stat.h> 512089Ssos#include "path.h" 5223457Sbrian#include "decode.h" 532089Ssos 5471642Ssobomax 55146736Sdelphij#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 56146736Sdelphij 57102111Ssobomax/* Screen dump modes */ 58102111Ssobomax#define DUMP_FMT_RAW 1 59102111Ssobomax#define DUMP_FMT_TXT 2 60102111Ssobomax/* Screen dump options */ 61102111Ssobomax#define DUMP_FBF 0 62102111Ssobomax#define DUMP_ALL 1 63102111Ssobomax/* Screen dump file format revision */ 6476845Ssobomax#define DUMP_FMT_REV 1 6576845Ssobomax 66228425Sedstatic const char *legal_colors[16] = { 672089Ssos "black", "blue", "green", "cyan", 682089Ssos "red", "magenta", "brown", "white", 692089Ssos "grey", "lightblue", "lightgreen", "lightcyan", 702089Ssos "lightred", "lightmagenta", "yellow", "lightwhite" 716628Ssos}; 722089Ssos 73241737Sedstatic struct { 74146736Sdelphij int active_vty; 75146736Sdelphij vid_info_t console_info; 76146736Sdelphij unsigned char screen_map[256]; 77146736Sdelphij int video_mode_number; 78146736Sdelphij struct video_info video_mode_info; 79146736Sdelphij} cur_info; 802089Ssos 81228425Sedstatic int hex = 0; 82228425Sedstatic int vesa_cols; 83228425Sedstatic int vesa_rows; 84228425Sedstatic int font_height; 85228425Sedstatic int colors_changed; 86228425Sedstatic int video_mode_changed; 87228425Sedstatic int normal_fore_color, normal_back_color; 88228425Sedstatic int revers_fore_color, revers_back_color; 89228425Sedstatic struct vid_info info; 90228425Sedstatic struct video_info new_mode_info; 91146736Sdelphij 92146736Sdelphij 93146736Sdelphij/* 94146736Sdelphij * Initialize revert data. 95146736Sdelphij * 96146736Sdelphij * NOTE: the following parameters are not yet saved/restored: 97146736Sdelphij * 98146736Sdelphij * screen saver timeout 99146736Sdelphij * cursor type 100146736Sdelphij * mouse character and mouse show/hide state 101146736Sdelphij * vty switching on/off state 102146736Sdelphij * history buffer size 103146736Sdelphij * history contents 104146736Sdelphij * font maps 105146736Sdelphij */ 106146736Sdelphij 10730764Scharnierstatic void 108146736Sdelphijinit(void) 109146736Sdelphij{ 110146736Sdelphij if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) == -1) 111146736Sdelphij errc(1, errno, "getting active vty"); 112146736Sdelphij 113146736Sdelphij cur_info.console_info.size = sizeof(cur_info.console_info); 114146736Sdelphij 115146736Sdelphij if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1) 116146736Sdelphij errc(1, errno, "getting console information"); 117146736Sdelphij 118146736Sdelphij if (ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1) 119146736Sdelphij errc(1, errno, "getting screen map"); 120146736Sdelphij 121146736Sdelphij if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1) 122146736Sdelphij errc(1, errno, "getting video mode number"); 123146736Sdelphij 124146736Sdelphij cur_info.video_mode_info.vi_mode = cur_info.video_mode_number; 125146736Sdelphij 126146736Sdelphij if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1) 127146736Sdelphij errc(1, errno, "getting video mode parameters"); 128146736Sdelphij 129146736Sdelphij normal_fore_color = cur_info.console_info.mv_norm.fore; 130146736Sdelphij normal_back_color = cur_info.console_info.mv_norm.back; 131146736Sdelphij revers_fore_color = cur_info.console_info.mv_rev.fore; 132146736Sdelphij revers_back_color = cur_info.console_info.mv_rev.back; 133146736Sdelphij} 134146736Sdelphij 135146736Sdelphij 136146736Sdelphij/* 137146736Sdelphij * If something goes wrong along the way we call revert() to go back to the 138146736Sdelphij * console state we came from (which is assumed to be working). 139146736Sdelphij * 140146736Sdelphij * NOTE: please also read the comments of init(). 141146736Sdelphij */ 142146736Sdelphij 143146736Sdelphijstatic void 144146736Sdelphijrevert(void) 145146736Sdelphij{ 146146736Sdelphij int size[3]; 147146736Sdelphij 148162671Sru ioctl(0, VT_ACTIVATE, cur_info.active_vty); 149146736Sdelphij 150146736Sdelphij fprintf(stderr, "\033[=%dA", cur_info.console_info.mv_ovscan); 151146736Sdelphij fprintf(stderr, "\033[=%dF", cur_info.console_info.mv_norm.fore); 152146736Sdelphij fprintf(stderr, "\033[=%dG", cur_info.console_info.mv_norm.back); 153146736Sdelphij fprintf(stderr, "\033[=%dH", cur_info.console_info.mv_rev.fore); 154146736Sdelphij fprintf(stderr, "\033[=%dI", cur_info.console_info.mv_rev.back); 155146736Sdelphij 156146736Sdelphij ioctl(0, PIO_SCRNMAP, &cur_info.screen_map); 157146736Sdelphij 158146736Sdelphij if (cur_info.video_mode_number >= M_VESA_BASE) 159146736Sdelphij ioctl(0, _IO('V', cur_info.video_mode_number - M_VESA_BASE), 160146736Sdelphij NULL); 161146736Sdelphij else 162146736Sdelphij ioctl(0, _IO('S', cur_info.video_mode_number), NULL); 163146736Sdelphij 164146736Sdelphij if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) { 165146736Sdelphij size[0] = cur_info.video_mode_info.vi_width / 8; 166146736Sdelphij size[1] = cur_info.video_mode_info.vi_height / 167146736Sdelphij cur_info.console_info.font_size; 168146736Sdelphij size[2] = cur_info.console_info.font_size; 169146736Sdelphij 170146736Sdelphij ioctl(0, KDRASTER, size); 171146736Sdelphij } 172146736Sdelphij} 173146736Sdelphij 174146736Sdelphij 175146736Sdelphij/* 176146736Sdelphij * Print a short usage string describing all options, then exit. 177146736Sdelphij */ 178146736Sdelphij 179146736Sdelphijstatic void 180140159Sdelphijusage(void) 1816628Ssos{ 18299706Sdd fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 183102111Ssobomax"usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]", 18477329Sdes" [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 18599706Sdd" [-M char] [-m on | off] [-r foreground background]", 186199174Sed" [-S on | off] [-s number] [-T xterm | cons25] [-t N | off]", 187199174Sed" [mode] [foreground [background]] [show]"); 18830764Scharnier exit(1); 1896628Ssos} 1906628Ssos 191146736Sdelphij 192146736Sdelphij/* 193146736Sdelphij * Retrieve the next argument from the command line (for options that require 194146736Sdelphij * more than one argument). 195146736Sdelphij */ 196146736Sdelphij 197140159Sdelphijstatic char * 19875344Ssobomaxnextarg(int ac, char **av, int *indp, int oc, int strict) 1992089Ssos{ 2002089Ssos if (*indp < ac) 2012089Ssos return(av[(*indp)++]); 202146736Sdelphij 203146736Sdelphij if (strict != 0) { 204146736Sdelphij revert(); 20575344Ssobomax errx(1, "option requires two arguments -- %c", oc); 206146736Sdelphij } 207146736Sdelphij 20875344Ssobomax return(NULL); 2092089Ssos} 2102089Ssos 211146736Sdelphij 212146736Sdelphij/* 213146736Sdelphij * Guess which file to open. Try to open each combination of a specified set 214146736Sdelphij * of file name components. 215146736Sdelphij */ 216146736Sdelphij 217140159Sdelphijstatic FILE * 218140159Sdelphijopenguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name) 2192089Ssos{ 22092460Ssobomax FILE *f; 22192460Ssobomax int i, j, k, l; 2222089Ssos 22392460Ssobomax for (i = 0; a[i] != NULL; i++) { 22492460Ssobomax for (j = 0; b[j] != NULL; j++) { 22592460Ssobomax for (k = 0; c[k] != NULL; k++) { 22692460Ssobomax for (l = 0; d[l] != NULL; l++) { 227146736Sdelphij asprintf(name, "%s%s%s%s", 228146736Sdelphij a[i], b[j], c[k], d[l]); 229146736Sdelphij 23092460Ssobomax f = fopen(*name, "r"); 231146736Sdelphij 23292460Ssobomax if (f != NULL) 23392460Ssobomax return (f); 234146736Sdelphij 23592460Ssobomax free(*name); 23692460Ssobomax } 23792460Ssobomax } 23892460Ssobomax } 23952262Sbillf } 24092460Ssobomax return (NULL); 2412089Ssos} 2422089Ssos 243146736Sdelphij 244146736Sdelphij/* 245146736Sdelphij * Load a screenmap from a file and set it. 246146736Sdelphij */ 247146736Sdelphij 248140159Sdelphijstatic void 249140159Sdelphijload_scrnmap(const char *filename) 2502089Ssos{ 25192460Ssobomax FILE *fd; 25292460Ssobomax int size; 2532089Ssos char *name; 2542089Ssos scrmap_t scrnmap; 255140159Sdelphij const char *a[] = {"", SCRNMAP_PATH, NULL}; 256140159Sdelphij const char *b[] = {filename, NULL}; 257140159Sdelphij const char *c[] = {"", ".scm", NULL}; 258140159Sdelphij const char *d[] = {"", NULL}; 2592089Ssos 26092460Ssobomax fd = openguess(a, b, c, d, &name); 261146736Sdelphij 2622089Ssos if (fd == NULL) { 263146736Sdelphij revert(); 264146736Sdelphij errx(1, "screenmap file not found"); 2652089Ssos } 266146736Sdelphij 2672089Ssos size = sizeof(scrnmap); 268146736Sdelphij 26975344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 2702089Ssos rewind(fd); 271146736Sdelphij 272146736Sdelphij if (fread(&scrnmap, 1, size, fd) != (size_t)size) { 27330764Scharnier warnx("bad screenmap file"); 27423457Sbrian fclose(fd); 275146736Sdelphij revert(); 276146736Sdelphij errx(1, "bad screenmap file"); 2772089Ssos } 2782089Ssos } 279146736Sdelphij 280146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 281146736Sdelphij revert(); 282146736Sdelphij errc(1, errno, "loading screenmap"); 283146736Sdelphij } 284146736Sdelphij 28523457Sbrian fclose(fd); 2862089Ssos} 2872089Ssos 288146736Sdelphij 289146736Sdelphij/* 290146736Sdelphij * Set the default screenmap. 291146736Sdelphij */ 292146736Sdelphij 293140159Sdelphijstatic void 294140159Sdelphijload_default_scrnmap(void) 2952089Ssos{ 2966628Ssos scrmap_t scrnmap; 2972089Ssos int i; 2982089Ssos 2992089Ssos for (i=0; i<256; i++) 3002089Ssos *((char*)&scrnmap + i) = i; 301146736Sdelphij 302146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 303146736Sdelphij revert(); 304146736Sdelphij errc(1, errno, "loading default screenmap"); 305146736Sdelphij } 3062089Ssos} 3072089Ssos 308146736Sdelphij 309146736Sdelphij/* 310146736Sdelphij * Print the current screenmap to stdout. 311146736Sdelphij */ 312146736Sdelphij 313140159Sdelphijstatic void 314140159Sdelphijprint_scrnmap(void) 3152089Ssos{ 3162089Ssos unsigned char map[256]; 317140159Sdelphij size_t i; 3182089Ssos 319146736Sdelphij if (ioctl(0, GIO_SCRNMAP, &map) == -1) { 320146736Sdelphij revert(); 321146736Sdelphij errc(1, errno, "getting screenmap"); 3222089Ssos } 3232089Ssos for (i=0; i<sizeof(map); i++) { 324140159Sdelphij if (i != 0 && i % 16 == 0) 3252089Ssos fprintf(stdout, "\n"); 326146736Sdelphij 327146736Sdelphij if (hex != 0) 3288857Srgrimes fprintf(stdout, " %02x", map[i]); 3292089Ssos else 3302089Ssos fprintf(stdout, " %03d", map[i]); 3312089Ssos } 3322089Ssos fprintf(stdout, "\n"); 3332089Ssos 3342089Ssos} 3352089Ssos 336146736Sdelphij 337146736Sdelphij/* 338146736Sdelphij * Determine a file's size. 339146736Sdelphij */ 340146736Sdelphij 341140159Sdelphijstatic int 34275344Ssobomaxfsize(FILE *file) 34375344Ssobomax{ 34475344Ssobomax struct stat sb; 34575344Ssobomax 34675344Ssobomax if (fstat(fileno(file), &sb) == 0) 34775344Ssobomax return sb.st_size; 34875344Ssobomax else 34975344Ssobomax return -1; 35075344Ssobomax} 35175344Ssobomax 35275344Ssobomax 353146736Sdelphij/* 354146736Sdelphij * Load a font from file and set it. 355146736Sdelphij */ 356146736Sdelphij 357140159Sdelphijstatic void 358140159Sdelphijload_font(const char *type, const char *filename) 3592089Ssos{ 36092460Ssobomax FILE *fd; 36175344Ssobomax int h, i, size, w; 36275344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 36392460Ssobomax char *name, *fontmap, size_sufx[6]; 364140159Sdelphij const char *a[] = {"", FONT_PATH, NULL}; 365140159Sdelphij const char *b[] = {filename, NULL}; 366140159Sdelphij const char *c[] = {"", size_sufx, NULL}; 367140159Sdelphij const char *d[] = {"", ".fnt", NULL}; 368140159Sdelphij vid_info_t _info; 3692089Ssos 37075344Ssobomax struct sizeinfo { 37175344Ssobomax int w; 37275344Ssobomax int h; 37375344Ssobomax unsigned long io; 37475344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 37575344Ssobomax {8, 14, PIO_FONT8x14}, 37675344Ssobomax {8, 8, PIO_FONT8x8}, 37775344Ssobomax {0, 0, 0}}; 37875344Ssobomax 379140159Sdelphij _info.size = sizeof(_info); 380140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 381146736Sdelphij revert(); 38292460Ssobomax warn("failed to obtain current video mode parameters"); 38392460Ssobomax return; 3842089Ssos } 385146736Sdelphij 386140159Sdelphij snprintf(size_sufx, sizeof(size_sufx), "-8x%d", _info.font_size); 38792460Ssobomax fd = openguess(a, b, c, d, &name); 388146736Sdelphij 3892089Ssos if (fd == NULL) { 390146736Sdelphij revert(); 391146736Sdelphij errx(1, "%s: can't load font file", filename); 3922089Ssos } 393146736Sdelphij 39475344Ssobomax if (type != NULL) { 39575344Ssobomax size = 0; 396146736Sdelphij if (sscanf(type, "%dx%d", &w, &h) == 2) { 397146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 39875344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 39975344Ssobomax size = DATASIZE(sizes[i]); 40075344Ssobomax io = sizes[i].io; 401146736Sdelphij font_height = sizes[i].h; 40275344Ssobomax } 403146736Sdelphij } 404146736Sdelphij } 40575344Ssobomax if (size == 0) { 40675344Ssobomax fclose(fd); 407146736Sdelphij revert(); 408146736Sdelphij errx(1, "%s: bad font size specification", type); 40975344Ssobomax } 41075344Ssobomax } else { 41175344Ssobomax /* Apply heuristics */ 412146736Sdelphij 41375344Ssobomax int j; 41475344Ssobomax int dsize[2]; 41575344Ssobomax 41675344Ssobomax size = DATASIZE(sizes[0]); 41775344Ssobomax fontmap = (char*) malloc(size); 41875344Ssobomax dsize[0] = decode(fd, fontmap, size); 41975344Ssobomax dsize[1] = fsize(fd); 42075344Ssobomax free(fontmap); 42175344Ssobomax 42275344Ssobomax size = 0; 423146736Sdelphij for (j = 0; j < 2; j++) { 424146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 42575344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 42675344Ssobomax size = dsize[j]; 42775344Ssobomax io = sizes[i].io; 428146736Sdelphij font_height = sizes[i].h; 42975344Ssobomax j = 2; /* XXX */ 43075344Ssobomax break; 43175344Ssobomax } 432146736Sdelphij } 433146736Sdelphij } 43475344Ssobomax 43575344Ssobomax if (size == 0) { 43675344Ssobomax fclose(fd); 437146736Sdelphij revert(); 438146736Sdelphij errx(1, "%s: can't guess font size", filename); 43975344Ssobomax } 440146736Sdelphij 44175344Ssobomax rewind(fd); 4422089Ssos } 44375344Ssobomax 4442089Ssos fontmap = (char*) malloc(size); 445146736Sdelphij 44675344Ssobomax if (decode(fd, fontmap, size) != size) { 4472089Ssos rewind(fd); 448146736Sdelphij if (fsize(fd) != size || 449146736Sdelphij fread(fontmap, 1, size, fd) != (size_t)size) { 45075344Ssobomax warnx("%s: bad font file", filename); 45123457Sbrian fclose(fd); 4522089Ssos free(fontmap); 453146736Sdelphij revert(); 454146736Sdelphij errx(1, "%s: bad font file", filename); 4552089Ssos } 4562089Ssos } 457146736Sdelphij 458146736Sdelphij if (ioctl(0, io, fontmap) == -1) { 459146736Sdelphij revert(); 460146736Sdelphij errc(1, errno, "loading font"); 461146736Sdelphij } 462146736Sdelphij 46323457Sbrian fclose(fd); 4642089Ssos free(fontmap); 4652089Ssos} 4662089Ssos 467146736Sdelphij 468146736Sdelphij/* 469146736Sdelphij * Set the timeout for the screensaver. 470146736Sdelphij */ 471146736Sdelphij 472140159Sdelphijstatic void 4732089Ssosset_screensaver_timeout(char *arg) 4742089Ssos{ 4752089Ssos int nsec; 4762089Ssos 477146736Sdelphij if (!strcmp(arg, "off")) { 4782089Ssos nsec = 0; 479146736Sdelphij } else { 4802089Ssos nsec = atoi(arg); 481146736Sdelphij 4822089Ssos if ((*arg == '\0') || (nsec < 1)) { 483146736Sdelphij revert(); 484146736Sdelphij errx(1, "argument must be a positive number"); 4852089Ssos } 4862089Ssos } 487146736Sdelphij 488146736Sdelphij if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) { 489146736Sdelphij revert(); 490146736Sdelphij errc(1, errno, "setting screensaver period"); 491146736Sdelphij } 4922089Ssos} 4932089Ssos 494146736Sdelphij 495146736Sdelphij/* 496146736Sdelphij * Set the cursor's shape/type. 497146736Sdelphij */ 498146736Sdelphij 499140159Sdelphijstatic void 500228990Suqsset_cursor_type(char *appearance) 5012089Ssos{ 5025536Ssos int type; 5032089Ssos 504228990Suqs if (!strcmp(appearance, "normal")) 5056230Ssos type = 0; 506228990Suqs else if (!strcmp(appearance, "blink")) 5075536Ssos type = 1; 508228990Suqs else if (!strcmp(appearance, "destructive")) 5096230Ssos type = 3; 5105536Ssos else { 511146736Sdelphij revert(); 512146736Sdelphij errx(1, "argument to -c must be normal, blink or destructive"); 5132089Ssos } 514146736Sdelphij 515146736Sdelphij if (ioctl(0, CONS_CURSORTYPE, &type) == -1) { 516146736Sdelphij revert(); 517146736Sdelphij errc(1, errno, "setting cursor type"); 518146736Sdelphij } 5192089Ssos} 5202089Ssos 521146736Sdelphij 522146736Sdelphij/* 523146736Sdelphij * Set the video mode. 524146736Sdelphij */ 525146736Sdelphij 526140159Sdelphijstatic int 527146736Sdelphijvideo_mode(int argc, char **argv, int *mode_index) 5282089Ssos{ 52939592Syokota static struct { 530140159Sdelphij const char *name; 53139592Syokota unsigned long mode; 532146736Sdelphij unsigned long mode_num; 53339592Syokota } modes[] = { 534146736Sdelphij { "80x25", SW_TEXT_80x25, M_TEXT_80x25 }, 535146736Sdelphij { "80x30", SW_TEXT_80x30, M_TEXT_80x30 }, 536146736Sdelphij { "80x43", SW_TEXT_80x43, M_TEXT_80x43 }, 537146736Sdelphij { "80x50", SW_TEXT_80x50, M_TEXT_80x50 }, 538146736Sdelphij { "80x60", SW_TEXT_80x60, M_TEXT_80x60 }, 539146736Sdelphij { "132x25", SW_TEXT_132x25, M_TEXT_132x25 }, 540146736Sdelphij { "132x30", SW_TEXT_132x30, M_TEXT_132x30 }, 541146736Sdelphij { "132x43", SW_TEXT_132x43, M_TEXT_132x43 }, 542146736Sdelphij { "132x50", SW_TEXT_132x50, M_TEXT_132x50 }, 543146736Sdelphij { "132x60", SW_TEXT_132x60, M_TEXT_132x60 }, 544146736Sdelphij { "VGA_40x25", SW_VGA_C40x25, M_VGA_C40x25 }, 545146736Sdelphij { "VGA_80x25", SW_VGA_C80x25, M_VGA_C80x25 }, 546146736Sdelphij { "VGA_80x30", SW_VGA_C80x30, M_VGA_C80x30 }, 547146736Sdelphij { "VGA_80x50", SW_VGA_C80x50, M_VGA_C80x50 }, 548146736Sdelphij { "VGA_80x60", SW_VGA_C80x60, M_VGA_C80x60 }, 54948105Syokota#ifdef SW_VGA_C90x25 550146736Sdelphij { "VGA_90x25", SW_VGA_C90x25, M_VGA_C90x25 }, 551146736Sdelphij { "VGA_90x30", SW_VGA_C90x30, M_VGA_C90x30 }, 552146736Sdelphij { "VGA_90x43", SW_VGA_C90x43, M_VGA_C90x43 }, 553146736Sdelphij { "VGA_90x50", SW_VGA_C90x50, M_VGA_C90x50 }, 554146736Sdelphij { "VGA_90x60", SW_VGA_C90x60, M_VGA_C90x60 }, 55548105Syokota#endif 556146736Sdelphij { "VGA_320x200", SW_VGA_CG320, M_CG320 }, 557146736Sdelphij { "EGA_80x25", SW_ENH_C80x25, M_ENH_C80x25 }, 558146736Sdelphij { "EGA_80x43", SW_ENH_C80x43, M_ENH_C80x43 }, 559146736Sdelphij { "VESA_132x25", SW_VESA_C132x25,M_VESA_C132x25 }, 560146736Sdelphij { "VESA_132x43", SW_VESA_C132x43,M_VESA_C132x43 }, 561146736Sdelphij { "VESA_132x50", SW_VESA_C132x50,M_VESA_C132x50 }, 562146736Sdelphij { "VESA_132x60", SW_VESA_C132x60,M_VESA_C132x60 }, 563146736Sdelphij { "VESA_800x600", SW_VESA_800x600,M_VESA_800x600 }, 564146736Sdelphij { NULL, 0, 0 }, 56539592Syokota }; 566146736Sdelphij 567146736Sdelphij int new_mode_num = 0; 56842605Smjacob unsigned long mode = 0; 56948105Syokota int cur_mode; 57048105Syokota int ioerr; 57139287Ssos int size[3]; 57239592Syokota int i; 5732089Ssos 57448105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 57548105Syokota err(1, "cannot get the current video mode"); 576146736Sdelphij 577146736Sdelphij /* 578146736Sdelphij * Parse the video mode argument... 579146736Sdelphij */ 580146736Sdelphij 581146736Sdelphij if (*mode_index < argc) { 582146736Sdelphij if (!strncmp(argv[*mode_index], "MODE_", 5)) { 583146736Sdelphij if (!isdigit(argv[*mode_index][5])) 584146736Sdelphij errx(1, "invalid video mode number"); 585146736Sdelphij 586146736Sdelphij new_mode_num = atoi(&argv[*mode_index][5]); 587146736Sdelphij } else { 588146736Sdelphij for (i = 0; modes[i].name != NULL; ++i) { 589146736Sdelphij if (!strcmp(argv[*mode_index], modes[i].name)) { 590146736Sdelphij mode = modes[i].mode; 591146736Sdelphij new_mode_num = modes[i].mode_num; 592146736Sdelphij break; 593146736Sdelphij } 59439592Syokota } 595146736Sdelphij 596146736Sdelphij if (modes[i].name == NULL) 597146736Sdelphij return EXIT_FAILURE; 598146736Sdelphij if (ioctl(0, mode, NULL) < 0) { 599146736Sdelphij warn("cannot set videomode"); 600146736Sdelphij return EXIT_FAILURE; 601146736Sdelphij } 60239592Syokota } 603146736Sdelphij 604146736Sdelphij /* 605146736Sdelphij * Collect enough information about the new video mode... 606146736Sdelphij */ 607146736Sdelphij 608146736Sdelphij new_mode_info.vi_mode = new_mode_num; 609146736Sdelphij 610146736Sdelphij if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) { 611146736Sdelphij revert(); 612146736Sdelphij errc(1, errno, "obtaining new video mode parameters"); 613120201Seivind } 614146736Sdelphij 615146736Sdelphij if (mode == 0) { 616146736Sdelphij if (new_mode_num >= M_VESA_BASE) 617146736Sdelphij mode = _IO('V', new_mode_num - M_VESA_BASE); 618146736Sdelphij else 619146736Sdelphij mode = _IO('S', new_mode_num); 620146736Sdelphij } 621146736Sdelphij 622146736Sdelphij /* 623146736Sdelphij * Try setting the new mode. 624146736Sdelphij */ 625146736Sdelphij 626146736Sdelphij if (ioctl(0, mode, NULL) == -1) { 627146736Sdelphij revert(); 628146736Sdelphij errc(1, errno, "setting video mode"); 629146736Sdelphij } 630146736Sdelphij 631146736Sdelphij /* 632146736Sdelphij * For raster modes it's not enough to just set the mode. 633146736Sdelphij * We also need to explicitly set the raster mode. 634146736Sdelphij */ 635146736Sdelphij 636146736Sdelphij if (new_mode_info.vi_flags & V_INFO_GRAPHICS) { 637146736Sdelphij /* font size */ 638146736Sdelphij 639146736Sdelphij if (font_height == 0) 640146736Sdelphij font_height = cur_info.console_info.font_size; 641146736Sdelphij 642146736Sdelphij size[2] = font_height; 643146736Sdelphij 644146736Sdelphij /* adjust columns */ 645146736Sdelphij 646146736Sdelphij if ((vesa_cols * 8 > new_mode_info.vi_width) || 647146736Sdelphij (vesa_cols <= 0)) { 648146736Sdelphij size[0] = new_mode_info.vi_width / 8; 64971642Ssobomax } else { 65071642Ssobomax size[0] = vesa_cols; 65171642Ssobomax } 652146736Sdelphij 653146736Sdelphij /* adjust rows */ 654146736Sdelphij 655146736Sdelphij if ((vesa_rows * font_height > new_mode_info.vi_height) || 656146736Sdelphij (vesa_rows <= 0)) { 657146736Sdelphij size[1] = new_mode_info.vi_height / 658146736Sdelphij font_height; 65971642Ssobomax } else { 66071642Ssobomax size[1] = vesa_rows; 66171642Ssobomax } 662146736Sdelphij 663146736Sdelphij /* set raster mode */ 664146736Sdelphij 66548105Syokota if (ioctl(0, KDRASTER, size)) { 66648105Syokota ioerr = errno; 66748105Syokota if (cur_mode >= M_VESA_BASE) 66880148Syokota ioctl(0, 66980148Syokota _IO('V', cur_mode - M_VESA_BASE), 67080148Syokota NULL); 67148105Syokota else 67248105Syokota ioctl(0, _IO('S', cur_mode), NULL); 673146736Sdelphij revert(); 67448105Syokota warnc(ioerr, "cannot activate raster display"); 675120201Seivind return EXIT_FAILURE; 67648105Syokota } 67739287Ssos } 678146736Sdelphij 679146736Sdelphij video_mode_changed = 1; 680146736Sdelphij 681146736Sdelphij (*mode_index)++; 6822089Ssos } 683120201Seivind return EXIT_SUCCESS; 6842089Ssos} 6858857Srgrimes 686146736Sdelphij 687146736Sdelphij/* 688146736Sdelphij * Return the number for a specified color name. 689146736Sdelphij */ 690146736Sdelphij 691140159Sdelphijstatic int 6922089Ssosget_color_number(char *color) 6932089Ssos{ 6942089Ssos int i; 6952089Ssos 696146736Sdelphij for (i=0; i<16; i++) { 6972089Ssos if (!strcmp(color, legal_colors[i])) 6982089Ssos return i; 699146736Sdelphij } 7002089Ssos return -1; 7012089Ssos} 7022089Ssos 703146736Sdelphij 704146736Sdelphij/* 705146736Sdelphij * Get normal text and background colors. 706146736Sdelphij */ 707146736Sdelphij 708140159Sdelphijstatic void 709146736Sdelphijget_normal_colors(int argc, char **argv, int *_index) 7102089Ssos{ 7112089Ssos int color; 7122089Ssos 713140159Sdelphij if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) { 714140159Sdelphij (*_index)++; 715146241Snyan fprintf(stderr, "\033[=%dF", color); 716150246Srodrigc normal_fore_color=color; 717150246Srodrigc colors_changed = 1; 718140159Sdelphij if (*_index < argc 719140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 7202089Ssos && color < 8) { 721140159Sdelphij (*_index)++; 722146241Snyan fprintf(stderr, "\033[=%dG", color); 723150246Srodrigc normal_back_color=color; 7242089Ssos } 7252089Ssos } 7262089Ssos} 7272089Ssos 728146736Sdelphij 729146736Sdelphij/* 730146736Sdelphij * Get reverse text and background colors. 731146736Sdelphij */ 732146736Sdelphij 733140159Sdelphijstatic void 734146736Sdelphijget_reverse_colors(int argc, char **argv, int *_index) 7352089Ssos{ 7362089Ssos int color; 7372089Ssos 738140159Sdelphij if ((color = get_color_number(argv[*(_index)-1])) != -1) { 739146241Snyan fprintf(stderr, "\033[=%dH", color); 740150246Srodrigc revers_fore_color=color; 741150246Srodrigc colors_changed = 1; 742140159Sdelphij if (*_index < argc 743140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 7442089Ssos && color < 8) { 745140159Sdelphij (*_index)++; 746146241Snyan fprintf(stderr, "\033[=%dI", color); 747150246Srodrigc revers_back_color=color; 7482089Ssos } 7492089Ssos } 7502089Ssos} 7512089Ssos 752146736Sdelphij 753146736Sdelphij/* 754146736Sdelphij * Set normal and reverse foreground and background colors. 755146736Sdelphij */ 756146736Sdelphij 757140159Sdelphijstatic void 758146736Sdelphijset_colors(void) 759146736Sdelphij{ 760146736Sdelphij fprintf(stderr, "\033[=%dF", normal_fore_color); 761146736Sdelphij fprintf(stderr, "\033[=%dG", normal_back_color); 762146736Sdelphij fprintf(stderr, "\033[=%dH", revers_fore_color); 763146736Sdelphij fprintf(stderr, "\033[=%dI", revers_back_color); 764146736Sdelphij} 765146736Sdelphij 766146736Sdelphij 767146736Sdelphij/* 768146736Sdelphij * Switch to virtual terminal #arg. 769146736Sdelphij */ 770146736Sdelphij 771146736Sdelphijstatic void 77223457Sbrianset_console(char *arg) 77323457Sbrian{ 77423457Sbrian int n; 77523457Sbrian 776146736Sdelphij if(!arg || strspn(arg,"0123456789") != strlen(arg)) { 777146736Sdelphij revert(); 778146736Sdelphij errx(1, "bad console number"); 77923457Sbrian } 78023457Sbrian 78123457Sbrian n = atoi(arg); 782146736Sdelphij 78351393Syokota if (n < 1 || n > 16) { 784146736Sdelphij revert(); 785146736Sdelphij errx(1, "console number out of range"); 786162671Sru } else if (ioctl(0, VT_ACTIVATE, n) == -1) { 787146736Sdelphij revert(); 788146736Sdelphij errc(1, errno, "switching vty"); 789146736Sdelphij } 79023457Sbrian} 79123457Sbrian 792146736Sdelphij 793146736Sdelphij/* 794146736Sdelphij * Sets the border color. 795146736Sdelphij */ 796146736Sdelphij 797140159Sdelphijstatic void 7982089Ssosset_border_color(char *arg) 7992089Ssos{ 8002089Ssos int color; 8012089Ssos 8022089Ssos if ((color = get_color_number(arg)) != -1) { 803146241Snyan fprintf(stderr, "\033[=%dA", color); 8042089Ssos } 8052089Ssos else 8068857Srgrimes usage(); 8072089Ssos} 8082089Ssos 809140159Sdelphijstatic void 81055849Syokotaset_mouse_char(char *arg) 81155849Syokota{ 81255849Syokota struct mouse_info mouse; 81355849Syokota long l; 81455849Syokota 81555849Syokota l = strtol(arg, NULL, 0); 816146736Sdelphij 81775788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 818146736Sdelphij revert(); 81975788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 82055849Syokota return; 82155849Syokota } 822146736Sdelphij 82355849Syokota mouse.operation = MOUSE_MOUSECHAR; 82455849Syokota mouse.u.mouse_char = (int)l; 825146736Sdelphij 826146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 827146736Sdelphij revert(); 828146736Sdelphij errc(1, errno, "setting mouse character"); 829146736Sdelphij } 83055849Syokota} 83155849Syokota 832146736Sdelphij 833146736Sdelphij/* 834146736Sdelphij * Show/hide the mouse. 835146736Sdelphij */ 836146736Sdelphij 837140159Sdelphijstatic void 83816565Ssosset_mouse(char *arg) 83916565Ssos{ 84016565Ssos struct mouse_info mouse; 84116565Ssos 842146736Sdelphij if (!strcmp(arg, "on")) { 84316565Ssos mouse.operation = MOUSE_SHOW; 844146736Sdelphij } else if (!strcmp(arg, "off")) { 84516565Ssos mouse.operation = MOUSE_HIDE; 846146736Sdelphij } else { 847146736Sdelphij revert(); 848146736Sdelphij errx(1, "argument to -m must be either on or off"); 84916565Ssos } 850146736Sdelphij 851146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 852146736Sdelphij revert(); 853146736Sdelphij errc(1, errno, "%sing the mouse", 854146736Sdelphij mouse.operation == MOUSE_SHOW ? "show" : "hid"); 855146736Sdelphij } 85616565Ssos} 85716565Ssos 858146736Sdelphij 859140159Sdelphijstatic void 86099705Sddset_lockswitch(char *arg) 86199705Sdd{ 86299705Sdd int data; 86399705Sdd 864146736Sdelphij if (!strcmp(arg, "off")) { 86599705Sdd data = 0x01; 866146736Sdelphij } else if (!strcmp(arg, "on")) { 86799705Sdd data = 0x02; 868146736Sdelphij } else { 869146736Sdelphij revert(); 870146736Sdelphij errx(1, "argument to -S must be either on or off"); 87199705Sdd } 872146736Sdelphij 873146736Sdelphij if (ioctl(0, VT_LOCKSWITCH, &data) == -1) { 874146736Sdelphij revert(); 875146736Sdelphij errc(1, errno, "turning %s vty switching", 876146736Sdelphij data == 0x01 ? "off" : "on"); 877146736Sdelphij } 87899705Sdd} 87999705Sdd 880146736Sdelphij 881146736Sdelphij/* 882146736Sdelphij * Return the adapter name for a specified type. 883146736Sdelphij */ 884146736Sdelphij 885140159Sdelphijstatic const char 88639287Ssos*adapter_name(int type) 88739287Ssos{ 88839287Ssos static struct { 88939287Ssos int type; 890140159Sdelphij const char *name; 89139287Ssos } names[] = { 89239287Ssos { KD_MONO, "MDA" }, 89339287Ssos { KD_HERCULES, "Hercules" }, 89439287Ssos { KD_CGA, "CGA" }, 89539287Ssos { KD_EGA, "EGA" }, 89639287Ssos { KD_VGA, "VGA" }, 89739287Ssos { KD_PC98, "PC-98xx" }, 89848105Syokota { KD_TGA, "TGA" }, 89939287Ssos { -1, "Unknown" }, 90039287Ssos }; 901146736Sdelphij 90239287Ssos int i; 90339287Ssos 90439287Ssos for (i = 0; names[i].type != -1; ++i) 90539287Ssos if (names[i].type == type) 90639287Ssos break; 90739287Ssos return names[i].name; 90839287Ssos} 90939287Ssos 910146736Sdelphij 911146736Sdelphij/* 912146736Sdelphij * Show graphics adapter information. 913146736Sdelphij */ 914146736Sdelphij 915140159Sdelphijstatic void 91639287Ssosshow_adapter_info(void) 91739287Ssos{ 91842505Syokota struct video_adapter_info ad; 91939287Ssos 92039287Ssos ad.va_index = 0; 921146736Sdelphij 922146736Sdelphij if (ioctl(0, CONS_ADPINFO, &ad) == -1) { 923146736Sdelphij revert(); 924146736Sdelphij errc(1, errno, "obtaining adapter information"); 92539287Ssos } 92639287Ssos 92742505Syokota printf("fb%d:\n", ad.va_index); 92842505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 92942505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 93039287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 93142505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 93239287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 93339287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 934140159Sdelphij printf(" frame buffer window:0x%zx, buffer size:0x%zx\n", 93548105Syokota ad.va_window, ad.va_buffer_size); 936140159Sdelphij printf(" window size:0x%zx, origin:0x%x\n", 93748105Syokota ad.va_window_size, ad.va_window_orig); 93848105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 93948105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 940140159Sdelphij printf(" reserved:0x%zx\n", ad.va_unused0); 94139287Ssos} 94239287Ssos 943146736Sdelphij 944146736Sdelphij/* 945146736Sdelphij * Show video mode information. 946146736Sdelphij */ 947146736Sdelphij 948140159Sdelphijstatic void 94939287Ssosshow_mode_info(void) 95039287Ssos{ 951205855Sjkim char buf[80]; 952140159Sdelphij struct video_info _info; 953205855Sjkim int c; 954205855Sjkim int mm; 95539287Ssos int mode; 95639287Ssos 95739287Ssos printf(" mode# flags type size " 95839287Ssos "font window linear buffer\n"); 95939287Ssos printf("---------------------------------------" 96039287Ssos "---------------------------------------\n"); 961146736Sdelphij 962250509Seadler for (mode = 0; mode <= M_VESA_MODE_MAX; ++mode) { 963140159Sdelphij _info.vi_mode = mode; 964140159Sdelphij if (ioctl(0, CONS_MODEINFO, &_info)) 96539287Ssos continue; 966140159Sdelphij if (_info.vi_mode != mode) 96748105Syokota continue; 96839287Ssos 96939287Ssos printf("%3d (0x%03x)", mode, mode); 970140159Sdelphij printf(" 0x%08x", _info.vi_flags); 971140159Sdelphij if (_info.vi_flags & V_INFO_GRAPHICS) { 97239287Ssos c = 'G'; 973146736Sdelphij 974205855Sjkim if (_info.vi_mem_model == V_INFO_MM_PLANAR) 975205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %d", 976205855Sjkim _info.vi_width, _info.vi_height, 977205855Sjkim _info.vi_depth, _info.vi_planes); 978205855Sjkim else { 979205855Sjkim switch (_info.vi_mem_model) { 980205855Sjkim case V_INFO_MM_PACKED: 981205855Sjkim mm = 'P'; 982205855Sjkim break; 983205855Sjkim case V_INFO_MM_DIRECT: 984205855Sjkim mm = 'D'; 985205855Sjkim break; 986205855Sjkim case V_INFO_MM_CGA: 987205855Sjkim mm = 'C'; 988205855Sjkim break; 989205855Sjkim case V_INFO_MM_HGC: 990205855Sjkim mm = 'H'; 991205855Sjkim break; 992205855Sjkim case V_INFO_MM_VGAX: 993205855Sjkim mm = 'V'; 994205855Sjkim break; 995205855Sjkim default: 996205855Sjkim mm = ' '; 997205855Sjkim break; 998205855Sjkim } 999205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %c", 1000205855Sjkim _info.vi_width, _info.vi_height, 1001205855Sjkim _info.vi_depth, mm); 1002205855Sjkim } 100339287Ssos } else { 100439287Ssos c = 'T'; 1005146736Sdelphij 100639287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1007140159Sdelphij _info.vi_width, _info.vi_height); 100839287Ssos } 1009146736Sdelphij 101039287Ssos printf(" %c %-15s", c, buf); 101139287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1012140159Sdelphij _info.vi_cwidth, _info.vi_cheight); 101339287Ssos printf(" %-5s", buf); 1014140159Sdelphij printf(" 0x%05zx %2dk %2dk", 1015140159Sdelphij _info.vi_window, (int)_info.vi_window_size/1024, 1016140159Sdelphij (int)_info.vi_window_gran/1024); 1017140159Sdelphij printf(" 0x%08zx %dk\n", 1018140159Sdelphij _info.vi_buffer, (int)_info.vi_buffer_size/1024); 101939287Ssos } 102039287Ssos} 102139287Ssos 1022146736Sdelphij 1023140159Sdelphijstatic void 102439287Ssosshow_info(char *arg) 102539287Ssos{ 1026146736Sdelphij if (!strcmp(arg, "adapter")) { 102739287Ssos show_adapter_info(); 1028146736Sdelphij } else if (!strcmp(arg, "mode")) { 102939287Ssos show_mode_info(); 1030146736Sdelphij } else { 1031146736Sdelphij revert(); 1032146736Sdelphij errx(1, "argument to -i must be either adapter or mode"); 103339287Ssos } 103439287Ssos} 103539287Ssos 1036146736Sdelphij 1037140159Sdelphijstatic void 1038140159Sdelphijtest_frame(void) 10392089Ssos{ 1040146237Snyan int i, cur_mode, fore; 10412089Ssos 1042146237Snyan fore = 15; 1043146237Snyan 1044146237Snyan if (ioctl(0, CONS_GET, &cur_mode) < 0) 1045146237Snyan err(1, "must be on a virtual console"); 1046146237Snyan switch (cur_mode) { 1047146237Snyan case M_PC98_80x25: 1048146237Snyan case M_PC98_80x30: 1049146237Snyan fore = 7; 1050146237Snyan break; 1051146237Snyan } 1052146237Snyan 1053146241Snyan fprintf(stdout, "\033[=0G\n\n"); 10542089Ssos for (i=0; i<8; i++) { 1055146241Snyan fprintf(stdout, "\033[=%dF\033[=0G %2d \033[=%dF%-16s" 1056146241Snyan "\033[=%dF\033[=0G %2d \033[=%dF%-16s " 1057146241Snyan "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n", 1058146237Snyan fore, i, i, legal_colors[i], 1059146237Snyan fore, i+8, i+8, legal_colors[i+8], 1060146237Snyan fore, i, i); 10612089Ssos } 1062146241Snyan fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n", 10638857Srgrimes info.mv_norm.fore, info.mv_norm.back, 10642089Ssos info.mv_rev.fore, info.mv_rev.back); 10652089Ssos} 10662089Ssos 1067146736Sdelphij 106876845Ssobomax/* 106976845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 107076845Ssobomax * ioctl, and writes the results to stdout either in the special 107176845Ssobomax * binary format (see manual page for details), or in the plain 107276845Ssobomax * text format. 107376845Ssobomax */ 1074146736Sdelphij 1075140159Sdelphijstatic void 1076102111Ssobomaxdump_screen(int mode, int opt) 107776845Ssobomax{ 107876845Ssobomax scrshot_t shot; 1079140159Sdelphij vid_info_t _info; 108076845Ssobomax 1081140159Sdelphij _info.size = sizeof(_info); 1082146736Sdelphij 1083140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 1084146736Sdelphij revert(); 1085146736Sdelphij errc(1, errno, "obtaining current video mode parameters"); 108676845Ssobomax return; 108776845Ssobomax } 108876845Ssobomax 1089102111Ssobomax shot.x = shot.y = 0; 1090140159Sdelphij shot.xsize = _info.mv_csz; 1091140159Sdelphij shot.ysize = _info.mv_rsz; 1092102111Ssobomax if (opt == DUMP_ALL) 1093140159Sdelphij shot.ysize += _info.mv_hsz; 1094102111Ssobomax 1095102111Ssobomax shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t)); 109676845Ssobomax if (shot.buf == NULL) { 1097146736Sdelphij revert(); 1098146736Sdelphij errx(1, "failed to allocate memory for dump"); 109976845Ssobomax } 110076845Ssobomax 110176845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 1102146736Sdelphij revert(); 1103146736Sdelphij errc(1, errno, "dumping screen"); 110476845Ssobomax } 110576845Ssobomax 1106102111Ssobomax if (mode == DUMP_FMT_RAW) { 110776845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 110876845Ssobomax shot.xsize, shot.ysize); 1109146736Sdelphij 111076845Ssobomax fflush(stdout); 111176845Ssobomax 1112146736Sdelphij write(STDOUT_FILENO, shot.buf, 1113146736Sdelphij shot.xsize * shot.ysize * sizeof(u_int16_t)); 111476845Ssobomax } else { 111576845Ssobomax char *line; 111676845Ssobomax int x, y; 111776845Ssobomax u_int16_t ch; 111876845Ssobomax 111976845Ssobomax line = alloca(shot.xsize + 1); 1120146736Sdelphij 112176845Ssobomax if (line == NULL) { 1122146736Sdelphij revert(); 1123146736Sdelphij errx(1, "failed to allocate memory for line buffer"); 112476845Ssobomax } 112576845Ssobomax 112676845Ssobomax for (y = 0; y < shot.ysize; y++) { 112776845Ssobomax for (x = 0; x < shot.xsize; x++) { 112876845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 112976845Ssobomax ch &= 0xff; 1130146736Sdelphij 113176845Ssobomax if (isprint(ch) == 0) 113276845Ssobomax ch = ' '; 1133146736Sdelphij 113476845Ssobomax line[x] = (char)ch; 113576845Ssobomax } 113676845Ssobomax 113776845Ssobomax /* Trim trailing spaces */ 1138146736Sdelphij 113976845Ssobomax do { 114076845Ssobomax line[x--] = '\0'; 114176845Ssobomax } while (line[x] == ' ' && x != 0); 114276845Ssobomax 114376845Ssobomax puts(line); 114476845Ssobomax } 1145146736Sdelphij 114676845Ssobomax fflush(stdout); 114776845Ssobomax } 114876845Ssobomax} 114976845Ssobomax 1150146736Sdelphij 1151146736Sdelphij/* 1152146736Sdelphij * Set the console history buffer size. 1153146736Sdelphij */ 1154146736Sdelphij 1155140159Sdelphijstatic void 115677329Sdesset_history(char *opt) 115777329Sdes{ 115877329Sdes int size; 115977329Sdes 116077329Sdes size = atoi(opt); 1161146736Sdelphij 116277329Sdes if ((*opt == '\0') || size < 0) { 1163146736Sdelphij revert(); 1164146736Sdelphij errx(1, "argument must be a positive number"); 116577329Sdes } 1166146736Sdelphij 1167146736Sdelphij if (ioctl(0, CONS_HISTORY, &size) == -1) { 1168146736Sdelphij revert(); 1169146736Sdelphij errc(1, errno, "setting history buffer size"); 1170146736Sdelphij } 117177329Sdes} 117277329Sdes 1173146736Sdelphij 1174146736Sdelphij/* 1175146736Sdelphij * Clear the console history buffer. 1176146736Sdelphij */ 1177146736Sdelphij 1178140159Sdelphijstatic void 1179140159Sdelphijclear_history(void) 118077329Sdes{ 1181146736Sdelphij if (ioctl(0, CONS_CLRHIST) == -1) { 1182146736Sdelphij revert(); 1183146736Sdelphij errc(1, errno, "clearing history buffer"); 1184146736Sdelphij } 118577329Sdes} 118677329Sdes 1187199174Sedstatic void 1188199174Sedset_terminal_mode(char *arg) 1189199174Sed{ 1190146736Sdelphij 1191199174Sed if (strcmp(arg, "xterm") == 0) 1192199174Sed fprintf(stderr, "\033[=T"); 1193199174Sed else if (strcmp(arg, "cons25") == 0) 1194199174Sed fprintf(stderr, "\033[=1T"); 1195199174Sed} 1196199174Sed 1197199174Sed 119823457Sbrianint 11992089Ssosmain(int argc, char **argv) 12002089Ssos{ 1201237777Sache char *font, *type, *termmode; 1202102111Ssobomax int dumpmod, dumpopt, opt; 1203120201Seivind int reterr; 12042089Ssos 1205146736Sdelphij init(); 1206146736Sdelphij 12072089Ssos info.size = sizeof(info); 1208146736Sdelphij 1209146736Sdelphij if (ioctl(0, CONS_GETINFO, &info) == -1) 121030764Scharnier err(1, "must be on a virtual console"); 1211102111Ssobomax dumpmod = 0; 1212102111Ssobomax dumpopt = DUMP_FBF; 1213237777Sache termmode = NULL; 1214199174Sed while ((opt = getopt(argc, argv, 1215199174Sed "b:Cc:df:g:h:Hi:l:LM:m:pPr:S:s:T:t:x")) != -1) 12162089Ssos switch(opt) { 121777329Sdes case 'b': 121877329Sdes set_border_color(optarg); 121977329Sdes break; 122077329Sdes case 'C': 122177329Sdes clear_history(); 122277329Sdes break; 122377329Sdes case 'c': 122477329Sdes set_cursor_type(optarg); 122577329Sdes break; 122677329Sdes case 'd': 122777329Sdes print_scrnmap(); 122877329Sdes break; 122977329Sdes case 'f': 123077329Sdes type = optarg; 123177329Sdes font = nextarg(argc, argv, &optind, 'f', 0); 1232146736Sdelphij 123377329Sdes if (font == NULL) { 123477329Sdes type = NULL; 123577329Sdes font = optarg; 123677329Sdes } 1237146736Sdelphij 123877329Sdes load_font(type, font); 123977329Sdes break; 124077329Sdes case 'g': 1241146736Sdelphij if (sscanf(optarg, "%dx%d", 1242146736Sdelphij &vesa_cols, &vesa_rows) != 2) { 1243146736Sdelphij revert(); 124477329Sdes warnx("incorrect geometry: %s", optarg); 12452089Ssos usage(); 124677329Sdes } 1247146736Sdelphij break; 124877329Sdes case 'h': 124977329Sdes set_history(optarg); 125077329Sdes break; 1251102111Ssobomax case 'H': 1252102111Ssobomax dumpopt = DUMP_ALL; 1253102111Ssobomax break; 125477329Sdes case 'i': 125577329Sdes show_info(optarg); 125677329Sdes break; 125777329Sdes case 'l': 125877329Sdes load_scrnmap(optarg); 125977329Sdes break; 126077329Sdes case 'L': 126177329Sdes load_default_scrnmap(); 126277329Sdes break; 126377329Sdes case 'M': 126477329Sdes set_mouse_char(optarg); 126577329Sdes break; 126677329Sdes case 'm': 126777329Sdes set_mouse(optarg); 126877329Sdes break; 126977329Sdes case 'p': 1270102111Ssobomax dumpmod = DUMP_FMT_RAW; 127177329Sdes break; 127277329Sdes case 'P': 1273102111Ssobomax dumpmod = DUMP_FMT_TXT; 127477329Sdes break; 127577329Sdes case 'r': 1276146736Sdelphij get_reverse_colors(argc, argv, &optind); 127777329Sdes break; 127899705Sdd case 'S': 127999705Sdd set_lockswitch(optarg); 128099705Sdd break; 128177329Sdes case 's': 128277329Sdes set_console(optarg); 128377329Sdes break; 1284199174Sed case 'T': 1285237777Sache if (strcmp(optarg, "xterm") != 0 && 1286237777Sache strcmp(optarg, "cons25") != 0) 1287237777Sache usage(); 1288237777Sache termmode = optarg; 1289199174Sed break; 129077329Sdes case 't': 129177329Sdes set_screensaver_timeout(optarg); 129277329Sdes break; 129377329Sdes case 'x': 129477329Sdes hex = 1; 129577329Sdes break; 129677329Sdes default: 129777329Sdes usage(); 12982089Ssos } 1299146736Sdelphij 1300102111Ssobomax if (dumpmod != 0) 1301102111Ssobomax dump_screen(dumpmod, dumpopt); 1302120201Seivind reterr = video_mode(argc, argv, &optind); 1303146736Sdelphij get_normal_colors(argc, argv, &optind); 1304146736Sdelphij 13052089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 13062089Ssos test_frame(); 13072089Ssos optind++; 13082089Ssos } 1309146736Sdelphij 1310146736Sdelphij video_mode(argc, argv, &optind); 1311237777Sache if (termmode != NULL) 1312237777Sache set_terminal_mode(termmode); 1313146736Sdelphij 1314146736Sdelphij get_normal_colors(argc, argv, &optind); 1315146736Sdelphij 1316146736Sdelphij if (colors_changed || video_mode_changed) { 1317146736Sdelphij if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) { 1318146736Sdelphij if ((normal_back_color < 8) && (revers_back_color < 8)) { 1319146736Sdelphij set_colors(); 1320146736Sdelphij } else { 1321146736Sdelphij revert(); 1322146736Sdelphij errx(1, "bg color for text modes must be < 8"); 1323146736Sdelphij } 1324146736Sdelphij } else { 1325146736Sdelphij set_colors(); 1326146736Sdelphij } 1327146736Sdelphij } 1328146736Sdelphij 132930764Scharnier if ((optind != argc) || (argc == 1)) 13302089Ssos usage(); 1331120201Seivind return reterr; 13322089Ssos} 13332089Ssos 1334