1 /*
2 * HP2627 Terminal Window interface to Unix Metafont.
3 */
4
5 #define EXTERN extern
6 #include "../mfd.h"
7
8 #ifdef HP2627WIN
9
10 #include <stdio.h>
11
12 /*
13 * HP2627a Color Graphics Terminal: Escape code definitions
14 *
15 * Drawing pen colors
16 */
17 #define HP2627_BLACK '0'
18 #define HP2627_RED '1'
19 #define HP2627_GREEN '2'
20 #define HP2627_YELLOW '3'
21 #define HP2627_BLUE '4'
22 #define HP2627_MAGENTA '5'
23 #define HP2627_CYAN '6'
24 #define HP2627_WHITE '7'
25
26 /*
27 * Initialization: just do a hard graphics reset
28 * (then we can depend on the defaults
29 * being as we want them)
30 */
31 #define HP2627_INITSTRING "\033*wR"
32 #define HP2627_INITSTRINGLEN 4
33
34 /*
35 * We want the text to be visible over both background and forground
36 * graphics data; the best color combination I found for this
37 * was to set the background RED and then paint with BLUE,
38 * although the eye doesn't focus on BLUE very well (black
39 * might be better? Or green? [to get in the holiday mood])
40 */
41 #define HP2627_BACKGROUNDPEN HP2627_RED
42 #define HP2627_FOREGROUNDPEN HP2627_BLUE
43
44 static char mf_hp2627_pencolors[2] = {
45 HP2627_BACKGROUNDPEN, /* white */
46 HP2627_FOREGROUNDPEN /* black */
47 };
48
49 /*
50 * Screen dimensions: Note the origin is at the lower-left corner,
51 * not the upper left as MF expects - hence we need to translate.
52 */
53 #define HP2627_MAXX 511
54 #define HP2627_MAXY 389
55
56 /*
57 * The actual Graphics routines. Note that these are highly tty
58 * dependent so I can minimize the number of characters that
59 * need to be sent to paint an image, since we only talk to
60 * the HP at 9.6Kb.
61 */
62
63 /*
64 * function init_screen: boolean;
65 *
66 * Return true if window operations legal.
67 * We always return true (I suppose we could try to
68 * sense status or something masochistic like that)
69 */
70
71 #include <mfdisplay.h>
72
mf_hp2627_initscreen(void)73 int mf_hp2627_initscreen(void)
74 {
75 (void) fflush(stdout); /* make sure pascal-level output flushed */
76 (void) write(fileno(stdout), HP2627_INITSTRING, HP2627_INITSTRINGLEN);
77 return(1);
78 }
79
80 /*
81 * procedure updatescreen;
82 *
83 * Just make sure screen is ready to view
84 * (since we do Unix-level WRITE()s,
85 * we don't really need to flush stdio,
86 * but why not?)
87 */
88
mf_hp2627_updatescreen(void)89 void mf_hp2627_updatescreen(void)
90 {
91 (void) fflush(stdout);
92 }
93
94 /*
95 * procedure blankrectangle(left, right, top, bottom: integer);
96 *
97 * reset rectangle bounded by ([left,right],[top,bottom])
98 * to background color
99 */
100
mf_hp2627_blankrectangle(screencol left,screencol right,screenrow top,screenrow bottom)101 void mf_hp2627_blankrectangle (screencol left,
102 screencol right,
103 screenrow top,
104 screenrow bottom)
105 {
106 char sprbuf[128];
107
108 (void) sprintf(sprbuf, "\033*m%cx%d,%d %d,%dE", HP2627_BACKGROUNDPEN,
109 left, HP2627_MAXY-bottom,
110 right, HP2627_MAXY-top);
111 (void) write(fileno(stdout), sprbuf, strlen(sprbuf));
112 }
113
114 /*
115 * procedure paintrow(
116 * row: screenrow;
117 * init_color: pixelcolor;
118 * var trans_vector: transspec;
119 * vector_size: screencol );
120 *
121 * Paint "row" starting with color "init_color", up to next
122 * transition specified by "transition_vector", switch colors,
123 * and continue for "vector_size" transitions.
124 */
125
126 /*
127 * First some useful definitions:
128 */
129 #define ASCIILABS 0 /* plot cmd format: ASCII long abs */
130 #define BINLABS 1 /* plot cmd format: BINARY long abs */
131 #define BINSINC 2 /* plot cmd format: BINARY short incr */
132
133 #define ABS(x) ((x>=0)?x:-x) /* absolute value */
134
135 /*
136 * An optimized "move to (x,y), with current pen lowered unless UP is
137 * true" function. Takes advantage of short commands for short
138 * movements to minimize character traffic to term.
139 *
140 * Note: the "x -= 1;" fudge is because we only want to DRAW
141 * to the next transition_vector entry - 1, but if we
142 * have the pen raised, we want to move to exactly the
143 * next point.
144 */
145 #define MOVETO(x,y,up) \
146 if (up) *op++ = 'a'; \
147 else x -= 1; \
148 if (ABS(x-oldx) < 16 && ABS(y-oldy) < 16) { \
149 if (currentformat != BINSINC) { \
150 *op++ = 'j'; \
151 currentformat = BINSINC; \
152 } \
153 *op++ = (((x-oldx) & 0x1f) + ' '); \
154 *op++ = (((y-oldy) & 0x1f) + ' '); \
155 } else { \
156 if (currentformat != BINLABS) { \
157 *op++ = 'i'; \
158 currentformat = BINLABS; \
159 } \
160 *op++ = (((x&0x3e0)>>5)+' '); \
161 *op++ = ((x&0x01f) +' '); \
162 *op++ = (((y&0x3e0)>>5)+' '); \
163 *op++ = ((y&0x01f) +' '); \
164 } \
165 oldx = x; \
166 oldy = y;
167
mf_hp2627_paintrow(screenrow row,pixelcolor init_color,transspec transition_vector,screencol vector_size)168 void mf_hp2627_paintrow (screenrow row,
169 pixelcolor init_color,
170 transspec transition_vector,
171 screencol vector_size)
172 {
173 register color;
174 char outbuf[512*6]; /* enough to hold an alternate color */
175 /* in each column */
176 register char *op;
177 register x, y, oldx, oldy;
178 int currentformat;
179
180 color = (init_color == 0)? 0 : 1;
181
182 /*
183 * We put all escape sequences in a buffer so the write
184 * has a chance of being atomic, and not interrupted by
185 * other independent output to our TTY. Also to avoid
186 * (literally millions) of stdio calls.
187 */
188 op = outbuf;
189 /*
190 * Select current pen to be the color of the first segment:
191 *
192 * our strategy here is to paint a long line from the first
193 * transition_vector value (left edge of row) to the last
194 * transition_vector entry (right edge of row). Then we switch
195 * colors to the contrasting color, and paint alternate
196 * segments with that color. Would that the HP2627 would provide
197 * a mode to paint the "background" color while the PEN is lifted.
198 * However, this is faster than using rectangular area fills.
199 */
200
201 *op++ = '\033'; *op++ = '*'; *op++ = 'm';
202 *op++ = mf_hp2627_pencolors[color];
203 *op++ = 'X';
204
205 /*
206 * Reset our "remembered" state for (X,Y) positioning and plot
207 * command format
208 */
209 oldx = oldy = -999;
210 currentformat = ASCIILABS;
211
212 /*
213 * Now, paint across the entire width of this row, make it the
214 * initial segment color.
215 */
216 x = *transition_vector;
217 y = HP2627_MAXY-row;
218 *op++ = '\033'; *op++ = '*'; *op++ = 'p';
219 MOVETO(x,y,1);
220 x = transition_vector[vector_size];
221 MOVETO(x,y,0);
222 *op++ = 'Z';
223
224 /*
225 * If there remain other segments (of contrasting color) to paint,
226 * switch pens colors and draw them
227 */
228 if (--vector_size > 0) {
229 *op++ = '\033'; *op++ = '*'; *op++ = 'm';
230 *op++ = mf_hp2627_pencolors[1-color]; *op++ = 'X';
231 color = 1-color;
232
233 oldx = oldy = -999;
234 currentformat = ASCIILABS;
235 *op++ = '\033'; *op++ = '*'; *op++ = 'p';
236 x = *++transition_vector;
237 MOVETO(x,y,1);
238 while (vector_size-- > 0) {
239 x = *++transition_vector;
240 MOVETO(x,y,(color==init_color));
241 color = 1 - color;
242 };
243 *op++ = 'Z';
244 };
245
246 /*
247 * Write the resulting plot commands, hopefully atomically
248 */
249 (void) write(fileno(stdout), outbuf, op-outbuf);
250 }
251
252 #else
253 int hp2627_dummy;
254 #endif /* HP2627WIN */
255