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