1 /*- 2 * Copyright (c) 1994-1996 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: vidcontrol.c,v 1.16 1997/03/07 01:34:47 brian Exp $ 29 */ 30 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <machine/console.h> 37 #include <sys/errno.h> 38 #include "path.h" 39 #include "decode.h" 40 41 char legal_colors[16][16] = { 42 "black", "blue", "green", "cyan", 43 "red", "magenta", "brown", "white", 44 "grey", "lightblue", "lightgreen", "lightcyan", 45 "lightred", "lightmagenta", "yellow", "lightwhite" 46 }; 47 int hex = 0; 48 int number; 49 char letter; 50 struct vid_info info; 51 52 53 void 54 usage() 55 { 56 fprintf(stderr, 57 "Usage: vidcontrol mode (available modes: VGA_40x25, VGA_80x25,\n" 58 " VGA_80x50, VGA_320x200,\n" 59 " EGA_80x25, EGA_80x43)\n" 60 " (experimental) VGA_80x30, VGA_80x60)\n" 61 "\n" 62 " show (show available colors)\n" 63 " fgcol bgcol (set fore- & background colors)\n" 64 " -r fgcol bgcol (set reverse fore- & background colors)\n" 65 " -b color (set border color)\n" 66 " -c normal (set cursor to inverting block)\n" 67 " -c blink (set cursor to blinking inverted block)\n" 68 " -c destructive (set cursor to blinking destructive char)\n" 69 " -d (dump screenmap to stdout)\n" 70 " -l filename (load screenmap file filename)\n" 71 " -m on|off (switch mousepointer support on or off)\n" 72 " -L (load default screenmap)\n" 73 " -f DxL filename (load font, D dots wide & L lines high)\n" 74 " -t N (set screensaver timeout in seconds)\n" 75 " -x (use hex numbers for output)\n" 76 ); 77 } 78 79 char * 80 nextarg(int ac, char **av, int *indp, int oc) 81 { 82 if (*indp < ac) 83 return(av[(*indp)++]); 84 fprintf(stderr, "%s: option requires two arguments -- %c\n", av[0], oc); 85 usage(); 86 exit(1); 87 return(""); 88 } 89 90 char * 91 mkfullname(const char *s1, const char *s2, const char *s3) 92 { 93 static char *buf = NULL; 94 static int bufl = 0; 95 int f; 96 97 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 98 if (f > bufl) 99 if (buf) 100 buf = (char *)realloc(buf, f); 101 else 102 buf = (char *)malloc(f); 103 if (!buf) { 104 bufl = 0; 105 return(NULL); 106 } 107 108 bufl = f; 109 strcpy(buf, s1); 110 strcat(buf, s2); 111 strcat(buf, s3); 112 return(buf); 113 } 114 115 void 116 load_scrnmap(char *filename) 117 { 118 FILE *fd = 0; 119 int i, size; 120 char *name; 121 scrmap_t scrnmap; 122 char *prefix[] = {"", "", SCRNMAP_PATH, SCRNMAP_PATH, NULL}; 123 char *postfix[] = {"", ".scm", "", ".scm"}; 124 125 for (i=0; prefix[i]; i++) { 126 name = mkfullname(prefix[i], filename, postfix[i]); 127 fd = fopen(name, "r"); 128 if (fd) 129 break; 130 } 131 if (fd == NULL) { 132 perror("screenmap file not found"); 133 return; 134 } 135 size = sizeof(scrnmap); 136 if (decode(fd, (char *)&scrnmap) != size) { 137 rewind(fd); 138 if (fread(&scrnmap, 1, size, fd) != size) { 139 fprintf(stderr, "bad scrnmap file\n"); 140 fclose(fd); 141 return; 142 } 143 } 144 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 145 perror("can't load screenmap"); 146 fclose(fd); 147 } 148 149 void 150 load_default_scrnmap() 151 { 152 scrmap_t scrnmap; 153 int i; 154 155 for (i=0; i<256; i++) 156 *((char*)&scrnmap + i) = i; 157 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 158 perror("can't load default screenmap"); 159 } 160 161 void 162 print_scrnmap() 163 { 164 unsigned char map[256]; 165 int i; 166 167 if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 168 perror("getting scrnmap"); 169 return; 170 } 171 for (i=0; i<sizeof(map); i++) { 172 if (i > 0 && i % 16 == 0) 173 fprintf(stdout, "\n"); 174 if (hex) 175 fprintf(stdout, " %02x", map[i]); 176 else 177 fprintf(stdout, " %03d", map[i]); 178 } 179 fprintf(stdout, "\n"); 180 181 } 182 183 void 184 load_font(char *type, char *filename) 185 { 186 FILE *fd = 0; 187 int i, io, size; 188 char *name, *fontmap; 189 char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; 190 char *postfix[] = {"", ".fnt", "", ".fnt"}; 191 192 for (i=0; prefix[i]; i++) { 193 name = mkfullname(prefix[i], filename, postfix[i]); 194 fd = fopen(name, "r"); 195 if (fd) 196 break; 197 } 198 if (fd == NULL) { 199 perror("font file not found"); 200 return; 201 } 202 if (!strcmp(type, "8x8")) { 203 size = 8*256; 204 io = PIO_FONT8x8; 205 } 206 else if (!strcmp(type, "8x14")) { 207 size = 14*256; 208 io = PIO_FONT8x14; 209 } 210 else if (!strcmp(type, "8x16")) { 211 size = 16*256; 212 io = PIO_FONT8x16; 213 } 214 else { 215 perror("bad font size specification"); 216 fclose(fd); 217 return; 218 } 219 fontmap = (char*) malloc(size); 220 if (decode(fd, fontmap) != size) { 221 rewind(fd); 222 if (fread(fontmap, 1, size, fd) != size) { 223 fprintf(stderr, "bad font file\n"); 224 fclose(fd); 225 free(fontmap); 226 return; 227 } 228 } 229 if (ioctl(0, io, fontmap) < 0) 230 perror("can't load font"); 231 fclose(fd); 232 free(fontmap); 233 } 234 235 void 236 set_screensaver_timeout(char *arg) 237 { 238 int nsec; 239 240 if (!strcmp(arg, "off")) 241 nsec = 0; 242 else { 243 nsec = atoi(arg); 244 if ((*arg == '\0') || (nsec < 1)) { 245 fprintf(stderr, "argument must be a positive number\n"); 246 return; 247 } 248 } 249 if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 250 perror("setting screensaver period"); 251 } 252 253 void 254 set_cursor_type(char *appearence) 255 { 256 int type; 257 258 if (!strcmp(appearence, "normal")) 259 type = 0; 260 else if (!strcmp(appearence, "blink")) 261 type = 1; 262 else if (!strcmp(appearence, "destructive")) 263 type = 3; 264 else { 265 fprintf(stderr, 266 "argument to -c must be normal, blink or destructive\n"); 267 return; 268 } 269 ioctl(0, CONS_CURSORTYPE, &type); 270 } 271 272 void 273 video_mode(int argc, char **argv, int *index) 274 { 275 int mode; 276 277 if (*index < argc) { 278 if (!strcmp(argv[*index], "VGA_40x25")) 279 mode = SW_VGA_C40x25; 280 else if (!strcmp(argv[*index], "VGA_80x25")) 281 mode = SW_VGA_C80x25; 282 else if (!strcmp(argv[*index], "VGA_80x30")) 283 mode = SW_VGA_C80x30; 284 else if (!strcmp(argv[*index], "VGA_80x50")) 285 mode = SW_VGA_C80x50; 286 else if (!strcmp(argv[*index], "VGA_80x60")) 287 mode = SW_VGA_C80x60; 288 else if (!strcmp(argv[*index], "VGA_320x200")) 289 mode = SW_VGA_CG320; 290 else if (!strcmp(argv[*index], "EGA_80x25")) 291 mode = SW_ENH_C80x25; 292 else if (!strcmp(argv[*index], "EGA_80x43")) 293 mode = SW_ENH_C80x43; 294 else 295 return; 296 if (ioctl(0, mode, NULL) < 0) 297 perror("Cannot set videomode"); 298 (*index)++; 299 } 300 return; 301 } 302 303 int 304 get_color_number(char *color) 305 { 306 int i; 307 308 for (i=0; i<16; i++) 309 if (!strcmp(color, legal_colors[i])) 310 return i; 311 return -1; 312 } 313 314 void 315 set_normal_colors(int argc, char **argv, int *index) 316 { 317 int color; 318 319 if (*index < argc && (color = get_color_number(argv[*index])) != -1) { 320 (*index)++; 321 fprintf(stderr, "[=%dF", color); 322 if (*index < argc 323 && (color = get_color_number(argv[*index])) != -1 324 && color < 8) { 325 (*index)++; 326 fprintf(stderr, "[=%dG", color); 327 } 328 } 329 } 330 331 void 332 set_reverse_colors(int argc, char **argv, int *index) 333 { 334 int color; 335 336 if ((color = get_color_number(argv[*(index)-1])) != -1) { 337 fprintf(stderr, "[=%dH", color); 338 if (*index < argc 339 && (color = get_color_number(argv[*index])) != -1 340 && color < 8) { 341 (*index)++; 342 fprintf(stderr, "[=%dI", color); 343 } 344 } 345 } 346 347 void 348 set_console(char *arg) 349 { 350 int n; 351 352 if( !arg || strspn(arg,"0123456789") != strlen(arg)) { 353 fprintf(stderr,"vidcontrol: Bad console number\n"); 354 usage(); 355 return; 356 } 357 358 n = atoi(arg); 359 if (n < 1 || n > 12) { 360 fprintf(stderr,"vidcontrol: Console number out of range\n"); 361 usage(); 362 } else if (ioctl(0,VT_ACTIVATE,(char *)n) == -1) 363 perror("ioctl(VT_ACTIVATE)"); 364 } 365 366 void 367 set_border_color(char *arg) 368 { 369 int color; 370 371 if ((color = get_color_number(arg)) != -1) { 372 fprintf(stderr, "[=%dA", color); 373 } 374 else 375 usage(); 376 } 377 378 void 379 set_mouse(char *arg) 380 { 381 struct mouse_info mouse; 382 383 if (!strcmp(arg, "on")) 384 mouse.operation = MOUSE_SHOW; 385 else if (!strcmp(arg, "off")) 386 mouse.operation = MOUSE_HIDE; 387 else { 388 fprintf(stderr, 389 "argument to -m must either on or off\n"); 390 return; 391 } 392 ioctl(0, CONS_MOUSECTL, &mouse); 393 } 394 395 void 396 test_frame() 397 { 398 int i; 399 400 fprintf(stdout, "[=0G\n\n"); 401 for (i=0; i<8; i++) { 402 fprintf(stdout, "[=15F[=0G %2d [=%dF%-16s" 403 "[=15F[=0G %2d [=%dF%-16s " 404 "[=15F %2d [=%dGBACKGROUND[=0G\n", 405 i, i, legal_colors[i], i+8, i+8, 406 legal_colors[i+8], i, i); 407 } 408 fprintf(stdout, "[=%dF[=%dG[=%dH[=%dI\n", 409 info.mv_norm.fore, info.mv_norm.back, 410 info.mv_rev.fore, info.mv_rev.back); 411 } 412 413 int 414 main(int argc, char **argv) 415 { 416 extern char *optarg; 417 extern int optind; 418 int opt; 419 420 421 info.size = sizeof(info); 422 if (ioctl(0, CONS_GETINFO, &info) < 0) { 423 perror("Must be on a virtual console"); 424 return 1; 425 } 426 while((opt = getopt(argc, argv, "b:c:df:l:Lm:r:s:t:x")) != -1) 427 switch(opt) { 428 case 'b': 429 set_border_color(optarg); 430 break; 431 case 'c': 432 set_cursor_type(optarg); 433 break; 434 case 'd': 435 print_scrnmap(); 436 break; 437 case 'f': 438 load_font(optarg, 439 nextarg(argc, argv, &optind, 'f')); 440 break; 441 case 'l': 442 load_scrnmap(optarg); 443 break; 444 case 'L': 445 load_default_scrnmap(); 446 break; 447 case 'm': 448 set_mouse(optarg); 449 break; 450 case 'r': 451 set_reverse_colors(argc, argv, &optind); 452 break; 453 case 's': 454 set_console(optarg); 455 break; 456 case 't': 457 set_screensaver_timeout(optarg); 458 break; 459 case 'x': 460 hex = 1; 461 break; 462 default: 463 usage(); 464 return 1; 465 } 466 video_mode(argc, argv, &optind); 467 set_normal_colors(argc, argv, &optind); 468 if (optind < argc && !strcmp(argv[optind], "show")) { 469 test_frame(); 470 optind++; 471 } 472 if ((optind != argc) || (argc == 1)) { 473 usage(); 474 return 1; 475 } 476 return 0; 477 } 478 479