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
GRchex(val,string,nchars)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
GRsetwmask(mask)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
GRsetcolor(color)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
GRoutxy20(x,y)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
GRsetpos(x,y)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
GRsetcharstyle(style)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
GRsetlinestyle(style)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
GRsetcharsize(size)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
GRInit(stream,invert)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
GRClose()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
GRSetMap(pmap)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