Back to index

tetex-bin  3.0
hp2627.c
Go to the documentation of this file.
00001 /*
00002  * HP2627 Terminal Window interface to Unix Metafont.
00003  */
00004 
00005 #define       EXTERN extern
00006 #include "../mfd.h"
00007 
00008 #ifdef HP2627WIN
00009 
00010 #include <stdio.h>
00011 
00012 /*
00013  * HP2627a Color Graphics Terminal: Escape code definitions
00014  *
00015  *     Drawing pen colors
00016  */
00017 #define       HP2627_BLACK         '0'
00018 #define       HP2627_RED           '1'
00019 #define       HP2627_GREEN         '2'
00020 #define       HP2627_YELLOW        '3'
00021 #define       HP2627_BLUE          '4'
00022 #define       HP2627_MAGENTA              '5'
00023 #define       HP2627_CYAN          '6'
00024 #define       HP2627_WHITE         '7'
00025 
00026 /*
00027  *     Initialization: just do a hard graphics reset
00028  *            (then we can depend on the defaults
00029  *             being as we want them)
00030  */
00031 #define       HP2627_INITSTRING    "\033*wR"
00032 #define       HP2627_INITSTRINGLEN 4
00033 
00034 /*
00035  *     We want the text to be visible over both background and forground
00036  *            graphics data; the best color combination I found for this
00037  *            was to set the background RED and then paint with BLUE,
00038  *            although the eye doesn't focus on BLUE very well (black 
00039  *            might be better?  Or green? [to get in the holiday mood])
00040  */
00041 #define       HP2627_BACKGROUNDPEN HP2627_RED
00042 #define       HP2627_FOREGROUNDPEN HP2627_BLUE
00043 
00044 static char   mf_hp2627_pencolors[2] = {
00045               HP2627_BACKGROUNDPEN,              /* white */
00046               HP2627_FOREGROUNDPEN        /* black */
00047 };
00048 
00049 /*
00050  *     Screen dimensions:  Note the origin is at the lower-left corner,
00051  *            not the upper left as MF expects - hence we need to translate.
00052  */
00053 #define       HP2627_MAXX          511
00054 #define       HP2627_MAXY          389
00055 
00056 /*
00057  * The actual Graphics routines.  Note that these are highly tty
00058  *     dependent so I can minimize the number of characters that
00059  *     need to be sent to paint an image, since we only talk to
00060  *     the HP at 9.6Kb.
00061  */
00062 
00063 /*
00064  *     function init_screen: boolean;
00065  *
00066  *            Return true if window operations legal.
00067  *            We always return true (I suppose we could try to
00068  *            sense status or something masochistic like that)
00069  */
00070 
00071 int mf_hp2627_initscreen()
00072 {
00073        (void) fflush(stdout);      /* make sure pascal-level output flushed */
00074        (void) write(fileno(stdout), HP2627_INITSTRING, HP2627_INITSTRINGLEN);
00075        return(1);
00076 }
00077 
00078 /*
00079  *     procedure updatescreen; 
00080  *
00081  *            Just make sure screen is ready to view
00082  *            (since we do Unix-level WRITE()s,
00083  *            we don't really need to flush stdio,
00084  *            but why not?)
00085  */
00086 
00087 void mf_hp2627_updatescreen()
00088 {
00089        (void) fflush(stdout);
00090 }
00091 
00092 /*
00093  *     procedure blankrectangle(left, right, top, bottom: integer);
00094  *
00095  *             reset rectangle bounded by ([left,right],[top,bottom])
00096  *                   to background color
00097  */
00098 
00099 void mf_hp2627_blankrectangle P4C(screencol, left,
00100                                   screencol, right,
00101                                   screenrow, top,
00102                                   screenrow, bottom)
00103 {
00104        char   sprbuf[128];
00105 
00106        (void) sprintf(sprbuf, "\033*m%cx%d,%d %d,%dE", HP2627_BACKGROUNDPEN,
00107                      left, HP2627_MAXY-bottom,
00108                      right, HP2627_MAXY-top);
00109        (void) write(fileno(stdout), sprbuf, strlen(sprbuf));
00110 }
00111 
00112 /*
00113  *     procedure paintrow(
00114  *                   row:          screenrow;
00115  *                   init_color:   pixelcolor;
00116  *            var    trans_vector: transspec;
00117  *                   vector_size:  screencol            );
00118  *
00119  *            Paint "row" starting with color "init_color",  up to next
00120  *            transition specified by "transition_vector", switch colors,
00121  *            and continue for "vector_size" transitions.
00122  */
00123 
00124 /*
00125  *     First some useful definitions:
00126  */
00127 #define       ASCIILABS     0             /* plot cmd format: ASCII long abs    */
00128 #define       BINLABS              1             /* plot cmd format: BINARY long abs   */
00129 #define       BINSINC              2             /* plot cmd format: BINARY short incr */
00130 
00131 #define       ABS(x) ((x>=0)?x:-x)        /* absolute value                 */
00132 
00133 /*
00134  *     An optimized "move to (x,y), with current pen lowered unless UP is
00135  *            true" function.  Takes advantage of short commands for short
00136  *            movements to minimize character traffic to term.
00137  *
00138  *            Note: the "x -= 1;" fudge is because we only want to DRAW
00139  *                   to the next transition_vector entry - 1, but if we
00140  *                   have the pen raised, we want to move to exactly the
00141  *                   next point.
00142  */
00143 #define       MOVETO(x,y,up) \
00144        if (up) *op++ = 'a'; \
00145        else x -= 1; \
00146        if (ABS(x-oldx) < 16 && ABS(y-oldy) < 16) { \
00147               if (currentformat != BINSINC) { \
00148                      *op++ = 'j'; \
00149                      currentformat = BINSINC; \
00150               } \
00151               *op++ = (((x-oldx) & 0x1f) + ' '); \
00152               *op++ = (((y-oldy) & 0x1f) + ' '); \
00153        } else { \
00154               if (currentformat != BINLABS) { \
00155                      *op++ = 'i'; \
00156                      currentformat = BINLABS; \
00157               } \
00158               *op++ = (((x&0x3e0)>>5)+' '); \
00159               *op++ =  ((x&0x01f)    +' '); \
00160               *op++ = (((y&0x3e0)>>5)+' '); \
00161               *op++ =  ((y&0x01f)    +' '); \
00162        } \
00163        oldx = x; \
00164        oldy = y;
00165 
00166 void mf_hp2627_paintrow P4C(screenrow,    row,
00167                             pixelcolor,   init_color,
00168                             transspec,    transition_vector,
00169                             screencol,    vector_size)
00170 {
00171        register      color;
00172        char          outbuf[512*6];       /* enough to hold an alternate color */
00173                                    /* in each column                */
00174        register      char   *op;
00175        register      x, y, oldx, oldy;
00176        int           currentformat;
00177 
00178        color = (init_color == 0)? 0 : 1;
00179 
00180        /*
00181         * We put all escape sequences in a buffer so the write
00182         * has a chance of being atomic, and not interrupted by
00183         * other independent output to our TTY.  Also to avoid
00184         * (literally millions) of stdio calls.
00185         */
00186        op = outbuf;
00187        /*
00188         * Select current pen to be the color of the first segment:
00189         *
00190         * our strategy here is to paint a long line from the first
00191         * transition_vector value (left edge of row) to the last
00192         * transition_vector entry (right edge of row).  Then we switch
00193         * colors to the contrasting color, and paint alternate
00194         * segments with that color.  Would that the HP2627 would provide
00195         * a mode to paint the "background" color while the PEN is lifted.
00196         * However, this is faster than using rectangular area fills.
00197         */
00198 
00199        *op++ = '\033'; *op++ = '*'; *op++ = 'm';
00200        *op++ = mf_hp2627_pencolors[color];
00201        *op++ = 'X';
00202 
00203        /*
00204         * Reset our "remembered" state for (X,Y) positioning and plot
00205         *     command format
00206         */
00207        oldx = oldy = -999;
00208        currentformat = ASCIILABS;
00209 
00210        /*
00211         * Now, paint across the entire width of this row, make it the
00212         *     initial segment color.
00213         */
00214        x = *transition_vector;
00215        y = HP2627_MAXY-row;
00216        *op++ = '\033'; *op++ = '*'; *op++ = 'p';
00217        MOVETO(x,y,1);
00218        x = transition_vector[vector_size];
00219        MOVETO(x,y,0);
00220        *op++ = 'Z';
00221 
00222        /*
00223         * If there remain other segments (of contrasting color) to paint,
00224         *     switch pens colors and draw them
00225         */
00226        if (--vector_size > 0) {
00227               *op++ = '\033'; *op++ = '*'; *op++ = 'm';
00228               *op++ = mf_hp2627_pencolors[1-color]; *op++ = 'X';
00229               color = 1-color;
00230 
00231               oldx = oldy = -999;
00232               currentformat = ASCIILABS;
00233               *op++ = '\033'; *op++ = '*'; *op++ = 'p';
00234               x = *++transition_vector;
00235               MOVETO(x,y,1);
00236               while (vector_size-- > 0) {
00237                      x = *++transition_vector;
00238                      MOVETO(x,y,(color==init_color));
00239                      color = 1 - color;
00240               };
00241               *op++ = 'Z';
00242        };
00243 
00244        /*
00245         * Write the resulting plot commands, hopefully atomically
00246         */
00247        (void) write(fileno(stdout), outbuf, op-outbuf);
00248 }
00249 
00250 #else
00251 int hp2627_dummy;
00252 #endif /* HP2627WIN */