1 /*
2 * title: uni.c
3 * abstract: Uniterm Terminal Window interface for Metafont.
4 * author: T.R.Hageman, Groningen, The Netherlands.
5 * created: May 1990
6 * modified:
7 * description:
8 * Uniterm (Simon Poole's terminal emulator for the Atari ST)
9 * emulates a `smart' Tektronix 4014 graphics terminal,
10 * and allows selective erasing of the graphics screen.
11 * (I do not know whether this is a standard feature of smart Teks
12 * or an invention of Mr. Poole)
13 *
14 * This file is offered as an alternative to the "standard"
15 * tektronix driver (which I find rather slow...)
16 *
17 * {{a possible way to improve the standard TEK driver would be to
18 * remember the (merged) transition lists instead converting to
19 * a bit map and back again.}}
20 *---*/
21
22 #define EXTERN extern
23 #include "../mfd.h"
24
25 #ifdef UNITERMWIN /* Whole file */
26
27 #define WIDTH 1024
28 #define HEIGHT 780
29 /*
30 * Send a vector to the graphics terminal
31 * (in a slightly optimized way).
32 */
33 static void
sendvector(x,y)34 sendvector(x, y)
35 register unsigned x, y;
36 {
37 static int Hi_Y, Lo_Y, Hi_X; /* remembered values */
38 register int Lo_Y_sent = 0;
39 register int t;
40 #ifdef DEBUG
41 if (x >= WIDTH) /* clip... */
42 x = WIDTH - 1;
43 if (y >= HEIGHT)
44 y = HEIGHT - 1;
45 #endif
46 /*
47 * Send Hi_Y only if it has changed.
48 */
49 if ((t = 0x20|(y >> 5)) != Hi_Y) {
50 Hi_Y = t, putchar(t);
51 }
52 /*
53 * Likewise, send Lo_Y only if it has changed.
54 * (and remember that it has been sent)
55 */
56 if ((t = 0x60|(y & 0x1f)) != Lo_Y) {
57 Lo_Y_sent = 1;
58 Lo_Y = t, putchar(t);
59 }
60 /*
61 * A slight complication here. If Hi_X has changed,
62 * we must send Lo_Y too, but only if we didn't already send it.
63 */
64 if ((t = 0x20|(x >> 5)) != Hi_X) {
65 if (!Lo_Y_sent)
66 putchar(Lo_Y);
67 Hi_X = t, putchar(t);
68 }
69 /*
70 * Lo_X is always sent, so don't bother to remember it.
71 */
72 t = 0x40|(x & 0x1f), putchar(t);
73 }
74 /*
75 * Tektronix has origin in lower-left corner, whereas MetaFont
76 * has its origin in the upper-left corner.
77 * The next macro hides this.
78 */
79 #define VECTOR(col,row) sendvector((unsigned)(col),(unsigned)(HEIGHT-1-(row)))
80 /*
81 * GS - `Dark' vectors are in fact invisible, i.e., a move.
82 * (Also switches from text- to graphics screen.)
83 */
84 #define DARK() putchar('\35')
85 /*
86 * CAN - Switch from graphics- to text screen.
87 */
88 #define TEXT_SCREEN() putchar('\30')
89 /*
90 * ESC STX(ETX) - Enable(disable) block-fill mode.
91 */
92 #define BLOCK(on) (putchar('\33'),putchar(2+!(on)))
93 /*
94 * ESC / 0(1) d - Set black(white) ink.
95 */
96 #define INK(on) (putchar('\33'), putchar('\57'), \
97 putchar('\61'-(on)), putchar('\144'))
98 /*
99 * US - Switch to `alpha mode'
100 */
101 #define ALPHA_MODE() putchar('\37')
102 /*
103 * ESC FF - clear graphics&alpha screen.
104 */
105 #define ALPHA_CLS(); (putchar('\33'), putchar('\14'))
106
107 #include <mfdisplay.h>
108
109 int
mf_uniterm_initscreen(void)110 mf_uniterm_initscreen(void)
111 {
112 ALPHA_CLS();
113 TEXT_SCREEN();
114 return 1;
115 }
116 void
mf_uniterm_updatescreen(void)117 mf_uniterm_updatescreen(void)
118 {
119 DARK();
120 VECTOR(0,HEIGHT-1);
121 fflush(stdout);
122 TEXT_SCREEN(); /* switch to text mode */
123 }
124 void
mf_uniterm_blankrectangle(screencol left,screencol right,screenrow top,screenrow bottom)125 mf_uniterm_blankrectangle (screencol left,
126 screencol right,
127 screenrow top,
128 screenrow bottom)
129 {
130 if (top==0 && left==0 && bottom>=HEIGHT-1 && right>=WIDTH-1) {
131 ALPHA_CLS();
132 return;
133 }
134 DARK();
135 VECTOR(left, top);
136 BLOCK(1); /* setup block erase mode */
137 INK(0); /* use white ink */
138 VECTOR(right-1, bottom-1); /* this draws the block */
139 BLOCK(0); /* back to (black) linedraw mode */
140 INK(1); /* black ink */
141 }
142 void
mf_uniterm_paintrow(screenrow row,pixelcolor init_color,register transspec transition_vector,register screencol vector_size)143 mf_uniterm_paintrow (screenrow row,
144 pixelcolor init_color,
145 register transspec transition_vector,
146 register screencol vector_size)
147 {
148 register int blank = !init_color;
149 #if 0
150 /* This is the basic */
151 DARK();
152 VECTOR(*transition_vector++, row); /* move to first transition */
153 do {
154 INK(blank ^= 1);
155 VECTOR(*transition_vector++ - 1, row);
156 } while (--vector_size > 0);
157 #endif
158 register screencol col;
159 /* However, we optimize the amount of output a bit by blanking
160 out the row first (since each INK command takes 4 bytes) */
161 DARK();
162 if (blank) {
163 VECTOR(transition_vector[((vector_size-1)&~1)+1] - 1, row);
164 INK(0);
165 VECTOR(*transition_vector++, row);
166 INK(1);
167 if (vector_size==1)
168 return;
169 }
170 else {
171 if (vector_size > 1) {
172 VECTOR(transition_vector[vector_size & ~1] - 1, row);
173 INK(0);
174 VECTOR(transition_vector[1], row);
175 INK(1);
176 DARK();
177 }
178 VECTOR(*transition_vector++, row);
179 }
180 do {
181 col = *transition_vector++;
182 if ((blank ^= 1) == 0)
183 DARK(); /* white -> black; move to first black pixel */
184 else
185 col--; /* black -> white; blacken to col-1 */
186 VECTOR(col, row);
187 } while (--vector_size > 0);
188 }
189 #else
190 int uniterm_dummy;
191 #endif /* UNITERMWIN */
192