jfh@rpp386.cactus.org (John F. Haugh II) (02/20/90)
I wrote this a while ago and recently fixed something. I forget what I fixed, but I know it made it work better with GNUPLOT. Save the rest of this file as "therc.c" then follow the directions. -- #include <stdio.h> #include <signal.h> #include <sys/ioctl.h> #include <sys/comcrt.h> #include <sys/machdep.h> #include <sys/sysmacros.h> /* * Copyright 1988, 1990, John F. Haugh II * All rights reserved. * * Recipient is free to use and distribute this code as they see fit, * provided they do not restrict the rights of other recipients to use * and distribute in a like manner. This code may be used for commercial * uses provided the author is given credit. Distribution with * commercial products requires credit be given the author in the * documentation included with this software. * * Under no circumstances may this copyright notice be modified or * removed. THIS COPYRIGHT IS INTENDED TO HAVE LEGAL SIGNIFICANCE. * CONTACT AN ATTORNEY OR THE AUTHOR IF YOU HAVE ANY QUESTION REGARDING * YOUR RIGHTS. It is the intent of this copyright to insure free use * and distribution for all parties. PERSONS RESTRICTING THE RIGHTS OF * OTHERS TO FREELY DISTRIBUTE THIS SOFTWARE WILL BE PROSECUTED. * * For more information or bug reports, you may contact the author at: * * John F. Haugh II * 3220 Duval Rd, Apt 1513 * Austin, TX 78759 * (512) 832-8832 * * UUCP: jfh@rpp386.cactus.org */ /* * How to compile: * * first, select PIX_HORZ to suit your fancy. i suggest you use * the square version only if drawing boxes and circles. plots * look better if full-screen. * * then, pick your cc command from below: * * cc -o therc -M3 -Ox -s therc.c * - or - * cc -o therc -M2l -Ox -s therc.c * * How to use: * therc [ from a file or pipe ] * therc plotfile [ from a plot format file ] * * Pressing <DEL> (or whatever your interrupt key is) will produce the * next screen. Pressing <QUIT> should cause an exit. Warning: this * command is not for novice users. Resetting the screen can be quite * involved! In particular, don't pipe GNUPLOT or anything else into * this command since your characters you type will disappear! */ /* * produces an almost square display */ #define PIX_SQUARE 550L /* * produces a full screen (but not square) display */ #define PIX_FULL 720L #define PIX_VERT 348L int PIX_HORZ = PIX_FULL; int cur_x; int cur_y; int off_x; int off_y; int x_scale; int y_scale; int is_blank = 1; int hflg; char *malloc (); #ifdef M_286 char far *scrmem; #else char *scrmem; #endif int screenfd; int savemode; int scrdesc; #define swap(a,b) { a ^= b; b ^= a; a ^= b; } short bits[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; short dotted[16] = { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 }; short solid[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; short longdashed[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; short shortdashed[16] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 }; short dotdashed[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 }; short *line = solid; #ifndef MAXPLT #define MAXPLT 1024 #endif int PLTSIZ = MAXPLT; int blank = 1; typedef char letter_t[12]; static letter_t letters[128] = { /* */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ! */ {0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00}, /* " */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x63,0x63,0x63,0x00}, /* # */ {0x00,0x00,0x36,0x36,0x7f,0x36,0x36,0x36,0x7f,0x36,0x36,0x00}, /* $ */ {0x00,0x0c,0x0c,0x7e,0xc3,0x03,0x7e,0xc0,0xc3,0x7e,0x0c,0x0c}, /* % */ {0x00,0x00,0xc3,0x63,0x30,0x18,0x0c,0x06,0xc3,0xc1,0x00,0x00}, /* & */ {0x00,0x00,0x76,0xcc,0xcc,0xdc,0x76,0x38,0x6c,0x6c,0x38,0x00}, /* ' */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x30,0x30,0x00}, /* ( */ {0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00}, /* ) */ {0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00}, /* * */ {0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00}, /* + */ {0x00,0x00,0x00,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x00,0x00}, /* , */ {0x00,0x00,0x60,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* - */ {0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00}, /* . */ {0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* / */ {0x00,0x00,0x80,0xc0,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00}, /* 0 */ {0x00,0x00,0x7e,0xc3,0xe3,0xf3,0xdb,0xcf,0xc7,0xc3,0x7e,0x00}, /* 1 */ {0x00,0x00,0x3f,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x1c,0x0c,0x00}, /* 2 */ {0x00,0x00,0x7f,0x63,0x30,0x18,0x0c,0x06,0x03,0x63,0x3e,0x00}, /* 3 */ {0x00,0x00,0x7e,0xc3,0x03,0x03,0x3e,0x03,0x03,0xc3,0x7e,0x00}, /* 4 */ {0x00,0x00,0x0f,0x06,0x06,0x7f,0x66,0x36,0x1e,0x0e,0x06,0x00}, /* 5 */ {0x00,0x00,0x7e,0xc3,0x03,0x03,0xfe,0xc0,0xc0,0xc0,0xff,0x00}, /* 6 */ {0x00,0x00,0x7e,0xc3,0xc3,0xc3,0xfe,0xc0,0xc0,0x60,0x3c,0x00}, /* 7 */ {0x00,0x00,0x18,0x18,0x18,0x18,0x0c,0x06,0x03,0x63,0x7f,0x00}, /* 8 */ {0x00,0x00,0x7e,0xc3,0xc3,0xc3,0x7e,0xc3,0xc3,0xc3,0x7e,0x00}, /* 9 */ {0x00,0x00,0x3c,0x06,0x03,0x03,0x7f,0xc3,0xc3,0xc3,0x7e,0x00}, /* : */ {0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00}, /* ; */ {0x00,0x00,0x30,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00}, /* < */ {0x00,0x00,0x03,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x03,0x00}, /* = */ {0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x3e,0x00,0x00,0x00}, /* > */ {0x00,0x00,0x30,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x30,0x00}, /* ? */ {0x00,0x00,0x0c,0x0c,0x00,0x0c,0x0c,0x06,0x63,0x63,0x3e,0x00}, /* @ */ {0x00,0x00,0x3f,0x60,0x6e,0x6f,0x6f,0x6f,0x63,0x63,0x3e,0x00}, /* A */ {0x00,0x00,0x63,0x63,0x63,0x7f,0x63,0x63,0x36,0x1c,0x08,0x00}, /* B */ {0x00,0x00,0xfe,0x63,0x63,0x63,0x7e,0x63,0x63,0x63,0xfe,0x00}, /* C */ {0x00,0x00,0x1e,0x33,0x61,0x60,0x60,0x60,0x61,0x33,0x1e,0x00}, /* D */ {0x00,0x00,0xfc,0x66,0x63,0x63,0x63,0x63,0x63,0x66,0xfc,0x00}, /* E */ {0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x31,0x33,0x7f,0x00}, /* F */ {0x00,0x00,0x78,0x30,0x30,0x34,0x3c,0x34,0x31,0x33,0x7f,0x00}, /* G */ {0x00,0x00,0x1d,0x33,0x63,0x6f,0x60,0x60,0x61,0x33,0x1e,0x00}, /* H */ {0x00,0x00,0x63,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x00}, /* I */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, /* J */ {0x00,0x00,0x3c,0x66,0x66,0x06,0x06,0x06,0x06,0x06,0x0f,0x00}, /* K */ {0x00,0x00,0x73,0x33,0x36,0x36,0x3c,0x36,0x36,0x36,0x73,0x00}, /* L */ {0x00,0x00,0x7f,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x78,0x00}, /* M */ {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00}, /* N */ {0x00,0x00,0x63,0x63,0x63,0x67,0x6f,0x7f,0x7b,0x73,0x63,0x00}, /* O */ {0x00,0x00,0x3c,0x66,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x00}, /* P */ {0x00,0x00,0x78,0x30,0x30,0x30,0x3e,0x33,0x33,0x33,0x7e,0x00}, /* Q */ {0x00,0x07,0x06,0x36,0x6f,0x6b,0x63,0x63,0x63,0x63,0x3e,0x00}, /* R */ {0x00,0x00,0x73,0x33,0x33,0x36,0x3e,0x33,0x33,0x33,0x7e,0x00}, /* S */ {0x00,0x00,0x3e,0x63,0x63,0x06,0x1c,0x30,0xc3,0xc3,0x3e,0x00}, /* T */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x99,0xdb,0xff,0x00}, /* U */ {0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00}, /* V */ {0x00,0x00,0x18,0x3c,0x66,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x00}, /* W */ {0x00,0x00,0x66,0x66,0xff,0xdb,0xdb,0xc3,0xc3,0xc3,0xc3,0x00}, /* X */ {0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0xc3,0x00}, /* Y */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x3c,0x66,0xc3,0xc3,0xc3,0x00}, /* Z */ {0x00,0x00,0xff,0xc3,0x61,0x30,0x18,0x0c,0x86,0xc3,0xff,0x00}, /* [ */ {0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00}, /* \ */ {0x00,0x00,0x01,0x03,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, /* ] */ {0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00}, /* ^ */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0x6c,0x38,0x10}, /* _ */ {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ` */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x60,0x60,0x60}, /* a */ {0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x78,0x00,0x00,0x00,0x00}, /* b */ {0x00,0x00,0xfc,0x66,0x66,0x66,0x6c,0x78,0x60,0x60,0xe0,0x00}, /* c */ {0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00}, /* d */ {0x00,0x00,0x3f,0x66,0x66,0x66,0x36,0x1e,0x06,0x06,0x07,0x00}, /* e */ {0x00,0x00,0x7c,0xc6,0xc0,0xfe,0xc6,0x7c,0x00,0x00,0x00,0x00}, /* f */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x3c,0x18,0x19,0x1b,0x0e,0x00}, /* g */ {0x7c,0xc6,0x06,0x7e,0xc6,0xc6,0xc6,0x7b,0x00,0x00,0x00,0x00}, /* h */ {0x00,0x00,0xe6,0x66,0x66,0x66,0x76,0x6c,0x60,0x60,0xe0,0x00}, /* i */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x38,0x00,0x18,0x18,0x00}, /* j */ {0x3c,0x66,0x66,0x06,0x06,0x06,0x06,0x0e,0x00,0x06,0x06,0x00}, /* k */ {0x00,0x00,0xe6,0x66,0x6c,0x78,0x6c,0x66,0x60,0x60,0xe0,0x00}, /* l */ {0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0x00}, /* m */ {0x00,0x00,0xdb,0xdb,0xdb,0xdb,0xff,0xe6,0x00,0x00,0x00,0x00}, /* n */ {0x00,0x00,0x63,0x63,0x63,0x63,0x73,0xde,0x00,0x00,0x00,0x00}, /* o */ {0x00,0x00,0x7e,0xc3,0xc3,0xc3,0xc3,0x7e,0x00,0x00,0x00,0x00}, /* p */ {0xf0,0x60,0x60,0x7e,0x63,0x63,0x73,0xde,0x00,0x00,0x00,0x00}, /* q */ {0x0f,0x06,0x06,0x7e,0xc6,0xc6,0xce,0x7b,0x00,0x00,0x00,0x00}, /* r */ {0x00,0x00,0xf0,0x60,0x60,0x63,0x73,0xde,0x00,0x00,0x00,0x00}, /* s */ {0x00,0x00,0x3c,0x66,0x1c,0x38,0x66,0x3c,0x00,0x00,0x00,0x00}, /* t */ {0x00,0x00,0x0c,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x08,0x00}, /* u */ {0x00,0x00,0x7b,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00}, /* v */ {0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00}, /* w */ {0x00,0x00,0x66,0xff,0xdb,0xdb,0xc3,0xc3,0x00,0x00,0x00,0x00}, /* x */ {0x00,0x00,0xc6,0x6c,0x38,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, /* y */ {0x78,0x0c,0x06,0x7e,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00}, /* z */ {0x00,0x00,0xfe,0x66,0x30,0x18,0xcc,0xfe,0x00,0x00,0x00,0x00}, /* { */ {0x00,0x00,0x0e,0x18,0x18,0x18,0x30,0x18,0x18,0x18,0x0e,0x00}, /* | */ {0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00}, /* } */ {0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x70,0x00}, /* ~ */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6e,0x3b} }; static string (s, xp, yp) char *s; int *xp; int *yp; { int i, j; int c; int mask; int xpos = *xp; int ypos = *yp; int y; int x; y = (ypos * PIX_VERT) / y_scale; x = (xpos * PIX_HORZ) / x_scale; for (;*s;s++) { c = *s; if (c >= ' ' || c <= '~') { for (i = 0;i < sizeof (letter_t);i++) { mask = letters[c - ' '][i]; for (j = 7;j >= 0;j--) if ((1 << j) & mask) mdapoint (y + i, x + 7 - j, 0); } } x += PIX_HORZ / 80; } } getword () { int i; i = getchar () & 0377; i |= ((getchar () & 0377) << 8); return (i); } linemode (mode) char *mode; { if (strcmp (mode, "dotted") == 0) line = dotted; else if (strcmp (mode, "solid") == 0) line = solid; else if (strcmp (mode, "longdashed") == 0) line = longdashed; else if (strcmp (mode, "shortdashed") == 0) line = shortdashed; else if (strcmp (mode, "dotdashed") == 0) line = dotdashed; else line = solid; } draw (x, y) { draw2 (cur_x, cur_y, x, y); } draw2 (x1, y1, x2, y2) { int txo, txd, dx; int tyo, tyd, dy; int tmp; int otx, tx, x; int oty, ty, y; int xs; int ys; txo = x1; txd = x2; tyo = y1; tyd = y2; if (txo > txd) { tmp = txo; txo = txd; txd = tmp; tmp = tyo; tyo = tyd; tyd = tmp; } dx = txd - txo; dy = tyd - tyo; xs = (x_scale * 2) / PIX_HORZ; xs /= 2; if (xs == 0) xs = 1; ys = y_scale / PIX_VERT; ys /= 2; if (ys == 0) ys = 1; if (dx == 0 || (dy > 0 && dy > dx) || (dy < 0 && - dy > dx)) { if (dy > 0) { /* plot in y direction */ for (y = 0;y < dy;y += ys) setpoint (((int) (txo + ((long) y * dx) / dy)), y + tyo); } else { for (y = dy + 1;y <= 0;y += ys) setpoint (((int) (txo + ((long) y * dx) / dy)), y + tyo); } } else { /* plot in x direction */ for (x = 0;x < dx;x += xs) setpoint (x + txo, ((int) (((long) x * dy) / dx + tyo))); } cur_x = x2; cur_y = y2; } move (x, y) { cur_x = x; cur_y = y; } point (x, y) { cur_x = x; cur_y = y; setpoint (x, y); } setpoint (x, y) { static int cur_point; is_blank = 0; if (++cur_point >= 32) /* increase spacing between dots ... */ cur_point = 0; /* ... so the line style is more ... */ if (! line[cur_point / 2]) /* ... obvious. adjust to suit ... */ return; /* ... you personal taste. */ mdapoint (y, x, 1); } label (s) char *s; { int tx; int ty; short *saveline = line; line = solid; blank = 0; tx = cur_x; ty = cur_y; string (s, &tx, &ty); line = saveline; } erase () { memset (scrmem, 0, 32768); blank = 1; } space (ulx, uly, lrx, lry) { off_x = ulx; off_y = uly; x_scale = lrx - ulx; y_scale = lry - uly; } mdapoint (y, x, scale) int y; int x; int scale; { int page; int line; int column; int bit; int offset; if (blank) blank = 0; if (scale) { y = (y * PIX_VERT) / y_scale; x = (x * PIX_HORZ) / x_scale; } if (y < 0) y = 0; else if (y >= PIX_VERT) y = PIX_VERT-1; if (x < 0) x = 0; else if (x >= PIX_HORZ) x = PIX_HORZ-1; y = (PIX_VERT-1) - y; /* invert y axis */ page = y & 03; line = y / 4; column = x / 8; bit = 1 << (7 - (x & 07)); offset = (page * 8192) + line * 90 + column; scrmem[offset] |= bit; } cleanup (sig) int sig; { signal (sig, cleanup); if (sig != SIGINT) { ioctl(screenfd, MODESWITCH | savemode, 0); exit (0); } } main (argc, argv) int argc; char **argv; { int c; char buffer[BUFSIZ]; int x1, y1; int x2, y2; int plots = 0; char *file = (char *) 0; if (argc > 1 && argv[1][0] == '-') { if (argv[1][1] == 's' || argv[1][1] == 'S') { PIX_HORZ = PIX_SQUARE; file = argv[2]; } else { fprintf (stderr, "usage: therc [ plotfile ]\n"); exit (1); } } else file = argv[1]; if (file != (char *) 0) { if (! freopen (file, "r", stdin)) { perror (file); exit (1); } } signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); signal (SIGTERM, SIG_IGN); if ((screenfd = open("/dev/mono",1)) < 0) { perror("/dev/mono"); exit(1); } if ((savemode = ioctl(screenfd, MCA_GET, 0)) < 0) { printf("Cannot get current adapter mode\n"); close(screenfd); exit(1); } if (ioctl(screenfd, SW_HGC_P0, 0) < 0) { printf("Cannot switch modes on monitor\n"); close(screenfd); exit(1); } ioctl(screenfd, MODESWITCH | savemode, 0); ioctl(screenfd, SW_HGC_P0, 0); if ((scrdesc = ioctl(screenfd, MAPMONO, (char *)0) ) < 0) { ioctl(screenfd, savemode, 0); printf("Cannot get screen descriptor to B800\n"); close(screenfd); exit(1); } #ifdef M_286 scrmem = sotofar (scrdesc, 0); #else scrmem = (char *) scrdesc; #endif signal (SIGINT, cleanup); signal (SIGQUIT, cleanup); signal (SIGTERM, cleanup); while ((c = getchar ()) != EOF) { switch (c) { case 'm': x1 = getword (); y1 = getword (); move (x1, y1); break; case 'n': x1 = getword (); y1 = getword (); draw (x1, y1); break; case 'p': x1 = getword (); y1 = getword (); point (x1, y1); break; case 'l': x1 = getword (); y1 = getword (); x2 = getword (); y2 = getword (); draw2 (x1, y1, x2, y2); break; case 't': gets (buffer); label (buffer); break; case 'e': if (! blank) pause (); erase (); break; case 'f': gets (buffer); linemode (buffer); break; case 's': x1 = getword (); y1 = getword (); x2 = getword (); y2 = getword (); space (x1, y1, x2, y2); break; } } write (2, "", 6); pause (); ioctl(screenfd, MODESWITCH | savemode, 0); } -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org