/* * title: uni.c * abstract: Uniterm Terminal Window interface for Metafont. * author: T.R.Hageman, Groningen, The Netherlands. * created: May 1990 * modified: * description: * Uniterm (Simon Poole's terminal emulator for the Atari ST) * emulates a `smart' Tektronix 4014 graphics terminal, * and allows selective erasing of the graphics screen. * (I do not know whether this is a standard feature of smart Teks * or an invention of Mr. Poole) * * This file is offered as an alternative to the "standard" * tektronix driver (which I find rather slow...) * * {{a possible way to improve the standard TEK driver would be to * remember the (merged) transition lists instead converting to * a bit map and back again.}} *---*/ #define EXTERN extern #include "../mfd.h" #ifdef UNITERMWIN /* Whole file */ #define WIDTH 1024 #define HEIGHT 780 /* * Send a vector to the graphics terminal * (in a slightly optimized way). */ static void sendvector(x, y) register unsigned x, y; { static int Hi_Y, Lo_Y, Hi_X; /* remembered values */ register int Lo_Y_sent = 0; register int t; #ifdef DEBUG if (x >= WIDTH) /* clip... */ x = WIDTH - 1; if (y >= HEIGHT) y = HEIGHT - 1; #endif /* * Send Hi_Y only if it has changed. */ if ((t = 0x20|(y >> 5)) != Hi_Y) { Hi_Y = t, putchar(t); } /* * Likewise, send Lo_Y only if it has changed. * (and remember that it has been sent) */ if ((t = 0x60|(y & 0x1f)) != Lo_Y) { Lo_Y_sent = 1; Lo_Y = t, putchar(t); } /* * A slight complication here. If Hi_X has changed, * we must send Lo_Y too, but only if we didn't already send it. */ if ((t = 0x20|(x >> 5)) != Hi_X) { if (!Lo_Y_sent) putchar(Lo_Y); Hi_X = t, putchar(t); } /* * Lo_X is always sent, so don't bother to remember it. */ t = 0x40|(x & 0x1f), putchar(t); } /* * Tektronix has origin in lower-left corner, whereas MetaFont * has its origin in the upper-left corner. * The next macro hides this. */ #define VECTOR(col,row) sendvector((unsigned)(col),(unsigned)(HEIGHT-1-(row))) /* * GS - `Dark' vectors are in fact invisible, i.e., a move. * (Also switches from text- to graphics screen.) */ #define DARK() putchar('\35') /* * CAN - Switch from graphics- to text screen. */ #define TEXT_SCREEN() putchar('\30') /* * ESC STX(ETX) - Enable(disable) block-fill mode. */ #define BLOCK(on) (putchar('\33'),putchar(2+!(on))) /* * ESC / 0(1) d - Set black(white) ink. */ #define INK(on) (putchar('\33'), putchar('\57'), \ putchar('\61'-(on)), putchar('\144')) /* * US - Switch to `alpha mode' */ #define ALPHA_MODE() putchar('\37') /* * ESC FF - clear graphics&alpha screen. */ #define ALPHA_CLS(); (putchar('\33'), putchar('\14')) #include int mf_uniterm_initscreen(void) { ALPHA_CLS(); TEXT_SCREEN(); return 1; } void mf_uniterm_updatescreen(void) { DARK(); VECTOR(0,HEIGHT-1); fflush(stdout); TEXT_SCREEN(); /* switch to text mode */ } void mf_uniterm_blankrectangle (screencol left, screencol right, screenrow top, screenrow bottom) { if (top==0 && left==0 && bottom>=HEIGHT-1 && right>=WIDTH-1) { ALPHA_CLS(); return; } DARK(); VECTOR(left, top); BLOCK(1); /* setup block erase mode */ INK(0); /* use white ink */ VECTOR(right-1, bottom-1); /* this draws the block */ BLOCK(0); /* back to (black) linedraw mode */ INK(1); /* black ink */ } void mf_uniterm_paintrow (screenrow row, pixelcolor init_color, register transspec transition_vector, register screencol vector_size) { register int blank = !init_color; #if 0 /* This is the basic */ DARK(); VECTOR(*transition_vector++, row); /* move to first transition */ do { INK(blank ^= 1); VECTOR(*transition_vector++ - 1, row); } while (--vector_size > 0); #endif register screencol col; /* However, we optimize the amount of output a bit by blanking out the row first (since each INK command takes 4 bytes) */ DARK(); if (blank) { VECTOR(transition_vector[((vector_size-1)&~1)+1] - 1, row); INK(0); VECTOR(*transition_vector++, row); INK(1); if (vector_size==1) return; } else { if (vector_size > 1) { VECTOR(transition_vector[vector_size & ~1] - 1, row); INK(0); VECTOR(transition_vector[1], row); INK(1); DARK(); } VECTOR(*transition_vector++, row); } do { col = *transition_vector++; if ((blank ^= 1) == 0) DARK(); /* white -> black; move to first black pixel */ else col--; /* black -> white; blacken to col-1 */ VECTOR(col, row); } while (--vector_size > 0); } #else int uniterm_dummy; #endif /* UNITERMWIN */