1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
/*
* 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'))
int mf_uniterm_initscreen()
{
ALPHA_CLS();
TEXT_SCREEN();
return 1;
}
void mf_uniterm_updatescreen()
{
DARK();
VECTOR(0,HEIGHT-1);
fflush(stdout);
TEXT_SCREEN(); /* switch to text mode */
}
void mf_uniterm_blankrectangle P4C(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 P4C(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 */
|