/* * HP2627 Terminal Window interface to Unix Metafont. */ #define EXTERN extern #include "../mfd.h" #ifdef HP2627WIN #include /* * HP2627a Color Graphics Terminal: Escape code definitions * * Drawing pen colors */ #define HP2627_BLACK '0' #define HP2627_RED '1' #define HP2627_GREEN '2' #define HP2627_YELLOW '3' #define HP2627_BLUE '4' #define HP2627_MAGENTA '5' #define HP2627_CYAN '6' #define HP2627_WHITE '7' /* * Initialization: just do a hard graphics reset * (then we can depend on the defaults * being as we want them) */ #define HP2627_INITSTRING "\033*wR" #define HP2627_INITSTRINGLEN 4 /* * We want the text to be visible over both background and forground * graphics data; the best color combination I found for this * was to set the background RED and then paint with BLUE, * although the eye doesn't focus on BLUE very well (black * might be better? Or green? [to get in the holiday mood]) */ #define HP2627_BACKGROUNDPEN HP2627_RED #define HP2627_FOREGROUNDPEN HP2627_BLUE static char mf_hp2627_pencolors[2] = { HP2627_BACKGROUNDPEN, /* white */ HP2627_FOREGROUNDPEN /* black */ }; /* * Screen dimensions: Note the origin is at the lower-left corner, * not the upper left as MF expects - hence we need to translate. */ #define HP2627_MAXX 511 #define HP2627_MAXY 389 /* * The actual Graphics routines. Note that these are highly tty * dependent so I can minimize the number of characters that * need to be sent to paint an image, since we only talk to * the HP at 9.6Kb. */ /* * function init_screen: boolean; * * Return true if window operations legal. * We always return true (I suppose we could try to * sense status or something masochistic like that) */ int mf_hp2627_initscreen() { (void) fflush(stdout); /* make sure pascal-level output flushed */ (void) write(fileno(stdout), HP2627_INITSTRING, HP2627_INITSTRINGLEN); return(1); } /* * procedure updatescreen; * * Just make sure screen is ready to view * (since we do Unix-level WRITE()s, * we don't really need to flush stdio, * but why not?) */ void mf_hp2627_updatescreen() { (void) fflush(stdout); } /* * procedure blankrectangle(left, right, top, bottom: integer); * * reset rectangle bounded by ([left,right],[top,bottom]) * to background color */ void mf_hp2627_blankrectangle P4C(screencol, left, screencol, right, screenrow, top, screenrow, bottom) { char sprbuf[128]; (void) sprintf(sprbuf, "\033*m%cx%d,%d %d,%dE", HP2627_BACKGROUNDPEN, left, HP2627_MAXY-bottom, right, HP2627_MAXY-top); (void) write(fileno(stdout), sprbuf, strlen(sprbuf)); } /* * procedure paintrow( * row: screenrow; * init_color: pixelcolor; * var trans_vector: transspec; * vector_size: screencol ); * * Paint "row" starting with color "init_color", up to next * transition specified by "transition_vector", switch colors, * and continue for "vector_size" transitions. */ /* * First some useful definitions: */ #define ASCIILABS 0 /* plot cmd format: ASCII long abs */ #define BINLABS 1 /* plot cmd format: BINARY long abs */ #define BINSINC 2 /* plot cmd format: BINARY short incr */ #define ABS(x) ((x>=0)?x:-x) /* absolute value */ /* * An optimized "move to (x,y), with current pen lowered unless UP is * true" function. Takes advantage of short commands for short * movements to minimize character traffic to term. * * Note: the "x -= 1;" fudge is because we only want to DRAW * to the next transition_vector entry - 1, but if we * have the pen raised, we want to move to exactly the * next point. */ #define MOVETO(x,y,up) \ if (up) *op++ = 'a'; \ else x -= 1; \ if (ABS(x-oldx) < 16 && ABS(y-oldy) < 16) { \ if (currentformat != BINSINC) { \ *op++ = 'j'; \ currentformat = BINSINC; \ } \ *op++ = (((x-oldx) & 0x1f) + ' '); \ *op++ = (((y-oldy) & 0x1f) + ' '); \ } else { \ if (currentformat != BINLABS) { \ *op++ = 'i'; \ currentformat = BINLABS; \ } \ *op++ = (((x&0x3e0)>>5)+' '); \ *op++ = ((x&0x01f) +' '); \ *op++ = (((y&0x3e0)>>5)+' '); \ *op++ = ((y&0x01f) +' '); \ } \ oldx = x; \ oldy = y; void mf_hp2627_paintrow P4C(screenrow, row, pixelcolor, init_color, transspec, transition_vector, screencol, vector_size) { register color; char outbuf[512*6]; /* enough to hold an alternate color */ /* in each column */ register char *op; register x, y, oldx, oldy; int currentformat; color = (init_color == 0)? 0 : 1; /* * We put all escape sequences in a buffer so the write * has a chance of being atomic, and not interrupted by * other independent output to our TTY. Also to avoid * (literally millions) of stdio calls. */ op = outbuf; /* * Select current pen to be the color of the first segment: * * our strategy here is to paint a long line from the first * transition_vector value (left edge of row) to the last * transition_vector entry (right edge of row). Then we switch * colors to the contrasting color, and paint alternate * segments with that color. Would that the HP2627 would provide * a mode to paint the "background" color while the PEN is lifted. * However, this is faster than using rectangular area fills. */ *op++ = '\033'; *op++ = '*'; *op++ = 'm'; *op++ = mf_hp2627_pencolors[color]; *op++ = 'X'; /* * Reset our "remembered" state for (X,Y) positioning and plot * command format */ oldx = oldy = -999; currentformat = ASCIILABS; /* * Now, paint across the entire width of this row, make it the * initial segment color. */ x = *transition_vector; y = HP2627_MAXY-row; *op++ = '\033'; *op++ = '*'; *op++ = 'p'; MOVETO(x,y,1); x = transition_vector[vector_size]; MOVETO(x,y,0); *op++ = 'Z'; /* * If there remain other segments (of contrasting color) to paint, * switch pens colors and draw them */ if (--vector_size > 0) { *op++ = '\033'; *op++ = '*'; *op++ = 'm'; *op++ = mf_hp2627_pencolors[1-color]; *op++ = 'X'; color = 1-color; oldx = oldy = -999; currentformat = ASCIILABS; *op++ = '\033'; *op++ = '*'; *op++ = 'p'; x = *++transition_vector; MOVETO(x,y,1); while (vector_size-- > 0) { x = *++transition_vector; MOVETO(x,y,(color==init_color)); color = 1 - color; }; *op++ = 'Z'; }; /* * Write the resulting plot commands, hopefully atomically */ (void) write(fileno(stdout), outbuf, op-outbuf); } #else int hp2627_dummy; #endif /* HP2627WIN */