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