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