1 /* @(#)graphics1.c	1.3	05/05/83
2  *
3  * Copyright -C- 1982 Barry S. Roitblat
4  *
5  *
6  * This file contains primitive functions to manipulate an AED512
7  * color display.
8  *
9  * (Modified from software written by John Ousterhout for the caesar
10  *  program)
11  */
12 #include "gremlin.h"
13 #include <sgtty.h>
14 
15 /* The following variables are used to hold state that we keep around
16  * between procedure calls in order to reduce the amount of information
17  * that must be shipped to the terminal.
18  */
19 
20 static char dbuf[BUFSIZ];	/* Used to buffer display characters */
21 static struct sgttyb sgttyb;	/* Used to save terminal control bits */
22 static int sgflags;		/* Used to save flags from sgttyb */
23 static char sgispeed, sgospeed;	/* Used to save baud rates */
24 static int localmode;		/* Used to save terminal local mode word */
25 static curcharsize;		/* Current character size */
26 static int wmask;		/* Current write mask value */
27 
28 
29 /* The following strings are used to as the colors for drawing and
30  * erasing.  They permit layer inversion, such that the drawing of
31  * the layer causes zeroes to be written and erasing causes ones to
32  * be written.
33  */
34 
35 static char draw[4], erase[4];
36 
37 /* The following arrays are used to define the line styles we use for
38  * for drawing.  Color and stipple are used as a representation of
39  * styles on the AED but are not necessarily accurate with the final
40  * output.
41  */
42 
43 static int stylecolor[11] = { 0, 041, 041, 043, 041, 041, 042,
44                               044, 044, 0200, 0100 };
45 static int stipple[11]  = { 255, 136, 228, 255, 240, 255, 255,
46                             255, 255, 136, 255 };
47 
48 /* The following table contains the color lookup used to represent
49  * different fonts on the AED.
50  */
51 
52 static int fontmap[8] = { 0, 041, 044, 045, 046, 0, 0, 0 };
53 
54 /* The following variables are made available to the outside world. */
55 
56 int GrXMax = 511;		/* Maximum x-coordinate of screen */
57 int GrYMax = 482;		/* Maximum y-coordinate of screen */
58 FILE *display;			/* The file for the AED512 */
59 int charxsize;			/* Character x dimension */
60 int charysize;			/* Character y dimension */
61 int descenders;			/* Character descender length */
62 int curx, cury;			/* Current access position */
63 int rmask;                      /* read mask */
64 
65 /* The following table is used to convert numbers to hex.  We cannot use
66  * standard C library conversion because it generates lower case letters
67  * which are bad news to the AED512.
68  */
69 
70 static char hex[] = "0123456789ABCDEF";
71 
72 
73 #ifndef FASTIO
74 GRchex(val, string, nchars)
75 int val;			/* Integer value to be converted. */
76 char *string;			/* Pointer to string area to be used for
77 				 * converted result.
78 				 */
79 int nchars;			/* Number of characters to be converted. */
80 
81 /*---------------------------------------------------------
82  *	This is a routine that converts an integer to a string
83  *	of hexadecimal characters.
84  *
85  *	Results:	None.
86  *
87  *	Side Effects:
88  *	The string contains the value of the low-order nchars 4-bit chunks
89  *	of val, as represented in hexadecimal.  String is zero-filled.
90  *---------------------------------------------------------
91  */
92 
93 {
94     string = &(string[nchars]);
95     *string = '\0';
96     for (; nchars>0 ; nchars--)
97     {
98 	*(--string) = hex[val & 017];
99 	val >>= 4;
100     }
101 }
102 #endif
103 
104 GRsetwmask(mask)
105 int mask;			/* New value for write mask */
106 
107 /*---------------------------------------------------------
108  *	This is a routine that resets the value of the current
109  *	write mask, if necessary.
110  *
111  *	Results:	None.
112  *
113  *	Side Effects:
114  *	If wmask is different from mask, then the new mask is output to
115  *	the display and stored in wmask.
116  *
117  *	Errors:		None.
118  *---------------------------------------------------------
119  */
120 
121 {
122     char s[4];
123     wmask = mask;
124 #ifndef FASTIO
125     GRchex(wmask, s, 2);
126     fprintf(display, "L%s", s);
127 #else
128     putc('L', display);
129     putc(mask&0377, display);
130 #endif
131 }
132 
133 GRsetcolor(color)
134 int color;
135 /*
136  *      This routine sets the current color for the graphics display
137  */
138 
139 {
140 
141 #ifndef FASTIO
142 	char s1[3];
143 
144 	GRchex(color, s1, 2);
145 	fprintf(display, "C%s",s1);
146 #else
147 	fprintf(display,"C%c", color&0377);
148 #endif
149 
150 }  /* end setcolor */
151 
152 
153 GRoutxy20(x, y)
154 int x,y;			/* The coordinates to be output */
155 
156 /*---------------------------------------------------------
157  *	This routine outputs an x-y coordinate pair in the standard
158  *	format required by the AED display.
159  *
160  *	Results:	None.
161  *
162  *	Side Effects:
163  *	Characters are output to the AED512 in the standard way required
164  *	for values indicated by "xy20" in the user manual.
165  *
166  *	Errors:		None.
167  *
168  * (Modified from software written by John Ousterhout for the caesar
169  *  program)
170  *---------------------------------------------------------
171  */
172 
173 {
174 #ifndef FASTIO
175     char s1[4], s2[4], s3[4];
176     GRchex(((y>>8)&03) | ((x>>6)&014), s1, 1);
177     GRchex(x&0377, s2, 2);
178     GRchex(y&0377, s3, 2);
179     fprintf(display, "%s%s%s", s1, s2, s3);
180 #else
181     putc(((x>>4)&020)+((y>>8)&01), display);
182     putc(x&0377, display);
183     putc(y&0377, display);
184 #endif
185 }
186 
187 GRsetpos(x, y)
188 int x, y;			/* Screen coordinates.
189 
190 /*---------------------------------------------------------
191  *	This routine sets the current access position, if necessary.
192  *
193  *	Results:	None.
194  *
195  *	Side Effects:
196  *	If x and y are equal to curx and cury, respectively, then nothing
197  *	happens.  Otherwise, x and y are stored into curx and cury and the
198  *	current access position of the AED is set to those coordinates.
199  *
200  *	Errors:		None.
201  *---------------------------------------------------------
202  */
203 
204 {
205     if (x==curx && y==cury) return;
206     curx = x;
207     cury = y;
208     putc('Q', display);
209     GRoutxy20(x, y);
210 }
211 
212 
213 GRsetcharstyle(style)
214 int style;			/* New font. */
215 
216 /*---------------------------------------------------------
217  *	This routine sets the current character style.
218  *
219  *	Results:	None.
220  *
221  *	Side Effects:
222  *	A new character style is output to the display.
223  *---------------------------------------------------------
224  */
225 
226 {
227     GRsetcolor(fontmap[style]);
228 }
229 
230 GRsetlinestyle(style)
231 int style;			/* New stipple pattern for lines. */
232 
233 /*---------------------------------------------------------
234  *	This routine sets the current line style.
235  *
236  *	Results:	None.
237  *
238  *	Side Effects:
239  *	A new line style is output to the display.
240  *---------------------------------------------------------
241  */
242 
243 {
244     char s[4];
245 
246     GRsetcolor(stylecolor[style]);
247 
248 #ifndef FASTIO
249     GRchex(stipple[style], s, 2);
250     fprintf(display, "1%sFF", s);
251 #else
252     putc('1', display);
253     putc(stipple[style]&0377, display);
254     putc(0377, display);
255 #endif
256 }
257 
258 
259 GRsetcharsize(size)
260 int size;			/* character size (1 - 4) */
261 
262 /*---------------------------------------------------------
263  *	This routine sets the character size in the display,
264  *	if necessary.
265  *
266  *	Results:	None.
267  *
268  *	Side Effects:
269  *	If the current display character size isn't already equal to size,
270  *	then it is made so.
271  *---------------------------------------------------------
272  */
273 
274 {
275     if (size == curcharsize) return;
276     curcharsize = size;
277 #ifndef FASTIO
278     if (curcharsize == 4)
279     {
280         fputs("^270F18L",display);
281 	charxsize = 15;
282 	charysize = 24;
283         descenders = 6;
284     }
285     else if (curcharsize == 3)
286          {
287              fputs("^250A0EL",display);
288              charxsize = 10;
289              charysize = 14;
290              descenders = 2;
291          }
292          else if (curcharsize == 2)
293               {
294 	          fputs("^17070CL", display);
295 	          charxsize = 8;
296 	          charysize = 12;
297                   descenders = 3;
298               }
299               else
300               {
301 	          fputs("^15050BL", display);
302 	          charxsize = 6;
303 	          charysize = 7;
304                   descenders = 1;
305                };
306 #else
307     if (curcharsize == 4)
308     {
309         fputs("^27\17\30L",display);
310 	charxsize = 15;
311 	charysize = 24;
312         descenders = 6;
313     }
314     else if (curcharsize == 3)
315          {
316              fputs("^25\12\16L",display);
317              charxsize = 10;
318              charysize = 14;
319              descenders = 2;
320          }
321          else if (curcharsize == 2)
322               {
323 	          fputs("^17\10\14L", display);
324 	          charxsize = 8;
325 	          charysize = 12;
326                   descenders = 3;
327               }
328               else
329               {
330 	          fputs("^15\6\7L", display);
331 	          charxsize = 6;
332 	          charysize = 7;
333                   descenders = 1;
334                };
335 #endif
336 }
337 
338 
339 GRInit(stream, invert)
340 FILE *stream;			/* A pointer to the graphics display
341 				 * file descriptor.  The file must have
342 				 * been opened by the caller.
343 				 */
344 int invert;			/* An integer whose low-order eight bits
345 				 * are ones iff the corresponding layers
346 				 * are to be inverted (drawing means write
347 				 * zeroes and erasing means write ones).
348 				 */
349 
350 /*---------------------------------------------------------
351  *	GRInit initializes the graphics display and clears its screen.
352  *
353  *	Results:	None.
354  *
355  *	Side Effects:
356  *	The display is re-initialized and the file is remembered for
357  *	use in all subsequent calls to this module.  The display's
358  *	color map is reset.  The display is put into raw mode, but
359  *	the previous mode bits are saved.
360  *
361  *	Errors:		None.
362  *---------------------------------------------------------
363  */
364 
365 {
366 #ifdef FASTIO
367     static int litout = LLITOUT;
368 #endif
369     static int ldisc = NTTYDISC;
370 
371     /* First, grab up the display modes, then reset them to put it
372      * into cooked mode.  Also, lock the terminal.  If doing fast I/O
373      * then set the LLITOUT bit.  Note:  setting the LLITOUT bit only
374      * works if it happens before the stty.  Also forces the display to
375      * run at 9600 baud.
376      */
377 
378     (void) ioctl(fileno(stream), TIOCSETD, (char *) &ldisc);
379     (void) ioctl(fileno(stream), TIOCLGET, (char *) &localmode);
380 #ifdef FASTIO
381     (void) ioctl(fileno(stream), TIOCLBIS, (char *) &litout);
382 #endif
383     (void) gtty(fileno(stream), &sgttyb);
384     sgflags = sgttyb.sg_flags;
385     sgispeed = sgttyb.sg_ispeed;
386     sgospeed = sgttyb.sg_ospeed;
387     sgttyb.sg_flags = (sgttyb.sg_flags &
388 	~(RAW | CBREAK | ECHO | LCASE)) | EVENP | ODDP | CRMOD;
389     sgttyb.sg_ispeed = B9600;
390     sgttyb.sg_ospeed = B9600;
391     (void) stty(fileno(stream), &sgttyb);
392     (void) ioctl(fileno(stream), TIOCEXCL, (char *) &sgttyb);
393 
394     /* Save the file pointer around for later use, then output an
395      * initialization string to the display.  The initialization
396      * string resets the terminal, sets formats, clears the display,
397      * and initializes the read and write masks.
398      */
399     display = stream;
400     setbuf(display, dbuf);
401 #ifndef FASTIO
402     GRchex(invert&0377, erase, 2);
403     GRchex((~invert)&0377, draw, 2);
404     fputs("\33\60", display);
405     (void) fflush(display);
406     (void) system("sleep 1");
407     fprintf(display, "\33\33G1HDHN[%sLFF\14\33C%sM7FFFFFFF", erase, draw);
408     fprintf(display, "c404022]+00002019001F02828");
409 #else
410     *erase = invert&0377;
411     *draw = (~invert)&0377;
412     fputs("\33\60", display);
413     (void) fflush(display);
414     (void) system("sleep 1");
415     fputs("\33\33G18D8N[", display);
416     putc(*erase, display);
417     fputs("L\377\14\33C", display);
418     putc(*draw, display);
419     fputs("M\177\377\377\377c\100\100\42]+", display);
420     putc('\0', display);
421     putc('\0', display);
422     fputs("2\01\220\01\360\50\50", display);
423 #endif
424     putc('3', display);			/* Make sure the crosshair is off */
425     putc('\0', display);
426     curx = -1;
427     cury = -1;
428     curcharsize = -1;
429     wmask = 0177;
430     rmask = 0177;
431     (void) fflush(display);
432 }
433 
434 
435 GRClose()
436 
437 /*---------------------------------------------------------
438  *	GRClose does whatever is necessary to reset the characteristics
439  *	of the AED512 after the program is finished.
440  *
441  *	Results:	None.
442  *
443  *	Side Effects:
444  *	The graphics display modes are reset.
445  *---------------------------------------------------------
446  */
447 
448 {
449     sgttyb.sg_flags = sgflags;
450     (void) stty(fileno(display), &sgttyb);
451     (void) ioctl(fileno(display), TIOCNXCL, (char *) &sgttyb);
452     (void) ioctl(fileno(display), TIOCLSET, (char *) &localmode);
453 }
454 
455 
456 GRSetMap(pmap)
457 char *pmap;			/* A pointer to 256*3 bytes containing the
458 				 * new values for the color map.  The first
459 				 * three values are red, green, and blue
460 				 * intensities for color 0, and so on.
461 				 */
462 
463 /*---------------------------------------------------------
464  *	GrSetMap outputs new values to the AED512 color map.
465  *
466  *	Results:	None.
467  *
468  *	Side Effects:
469  *	The values in the color map are set from the array indicated
470  *	by pmap.  The back1 and back2 strings are set so that the
471  *	routines GrBack1 and GrBack2 will switch the background color
472  *	to color 0 and color 256,respectively.
473  *
474  *	Errors:		None.
475  *
476  * (Modified from software written by John Ousterhout for the caesar
477  *  program)
478  *---------------------------------------------------------
479  */
480 
481 {
482     char s[4], *p;
483     int i;
484 
485     p = pmap;
486 #ifndef FASTIO
487     fputs("K0000", display);
488     for (i = 0; i<256*3; ++i)
489     {
490 	GRchex(*p++&0377, s, 2);
491 	fprintf(display, "%s", s);
492     }
493 #else
494     putc('K', display);
495     putc('\0', display);
496     putc('\0', display);
497     for (i = 0; i<256*3; ++i)
498     {
499 	putc(*p++&0377, display);
500     }
501 #endif
502     (void) fflush(display);
503 
504 }
505 
506