Back to index

tetex-bin  3.0
uniterm.c
Go to the documentation of this file.
00001 /*
00002  *  title:    uni.c
00003  *  abstract: Uniterm Terminal Window interface for Metafont.
00004  *  author:   T.R.Hageman, Groningen, The Netherlands.
00005  *  created:  May 1990
00006  *  modified:
00007  *  description:
00008  *    Uniterm (Simon Poole's terminal emulator for the Atari ST)
00009  *    emulates a `smart' Tektronix 4014 graphics terminal,
00010  *    and allows selective erasing of the graphics screen.
00011  *    (I do not know whether this is a standard feature of smart Teks
00012  *     or an invention of Mr. Poole)
00013  *
00014  *    This file is offered as an alternative to the "standard"
00015  *    tektronix driver (which I find rather slow...)
00016  *
00017  *    {{a possible way to improve the standard TEK driver would be to
00018  *      remember the (merged) transition lists instead converting to
00019  *      a bit map and back again.}}
00020  *---*/
00021 
00022 #define EXTERN extern
00023 #include "../mfd.h"
00024 
00025 #ifdef UNITERMWIN             /* Whole file */
00026 
00027 #define WIDTH 1024
00028 #define HEIGHT        780
00029 /*
00030  *    Send a vector to the graphics terminal
00031  *    (in a slightly optimized way).
00032  */
00033 static void
00034 sendvector(x, y)
00035 register unsigned     x, y;
00036 {
00037       static int      Hi_Y, Lo_Y, Hi_X;       /* remembered values */
00038       register int    Lo_Y_sent = 0;
00039       register int    t;
00040 #ifdef DEBUG
00041       if (x >= WIDTH)                 /* clip... */
00042               x = WIDTH - 1;
00043       if (y >= HEIGHT)
00044               y = HEIGHT - 1;
00045 #endif
00046       /*
00047        * Send Hi_Y only if it has changed.
00048        */
00049       if ((t = 0x20|(y >> 5)) != Hi_Y) {
00050               Hi_Y = t, putchar(t);
00051       }
00052       /*
00053        * Likewise, send Lo_Y only if it has changed.
00054        * (and remember that it has been sent)
00055        */
00056       if ((t = 0x60|(y & 0x1f)) != Lo_Y) {
00057               Lo_Y_sent = 1;
00058               Lo_Y = t, putchar(t);
00059       }
00060       /*
00061        * A slight complication here. If Hi_X has changed,
00062        * we must send Lo_Y too, but only if we didn't already send it.
00063        */
00064       if ((t = 0x20|(x >> 5)) != Hi_X) {
00065               if (!Lo_Y_sent)
00066                       putchar(Lo_Y);
00067               Hi_X = t, putchar(t);
00068       }
00069       /*
00070        * Lo_X is always sent, so don't bother to remember it.
00071        */
00072       t = 0x40|(x & 0x1f), putchar(t);
00073 }
00074 /*
00075  *    Tektronix has origin in lower-left corner, whereas MetaFont
00076  *    has its origin in the upper-left corner.
00077  *    The next macro hides this.
00078  */
00079 #define VECTOR(col,row) sendvector((unsigned)(col),(unsigned)(HEIGHT-1-(row)))
00080 /*
00081  *    GS              - `Dark' vectors are in fact invisible, i.e., a move.
00082  *                      (Also switches from text- to graphics screen.)
00083  */
00084 #define DARK()                putchar('\35')
00085 /*
00086  *    CAN             - Switch from graphics- to text screen.
00087  */
00088 #define TEXT_SCREEN() putchar('\30')
00089 /*
00090  *    ESC STX(ETX)    - Enable(disable) block-fill mode.
00091  */
00092 #define BLOCK(on)     (putchar('\33'),putchar(2+!(on)))
00093 /*
00094  *    ESC / 0(1) d    - Set black(white) ink.
00095  */
00096 #define INK(on)               (putchar('\33'), putchar('\57'), \
00097                        putchar('\61'-(on)), putchar('\144'))
00098 /*
00099  *    US              - Switch to `alpha mode'
00100  */
00101 #define ALPHA_MODE()  putchar('\37')
00102 /*
00103  *    ESC FF          - clear graphics&alpha screen.
00104  */
00105 #define ALPHA_CLS();  (putchar('\33'), putchar('\14'))
00106 int mf_uniterm_initscreen()
00107 {
00108       ALPHA_CLS();
00109       TEXT_SCREEN();
00110       return 1;
00111 }
00112 void mf_uniterm_updatescreen()
00113 {
00114       DARK();
00115       VECTOR(0,HEIGHT-1);
00116       fflush(stdout);
00117       TEXT_SCREEN();          /*  switch to text mode */
00118 }
00119 void mf_uniterm_blankrectangle P4C(screencol, left,
00120                                    screencol, right,
00121                                    screenrow, top,
00122                                    screenrow, bottom)
00123 {
00124       if (top==0 && left==0 && bottom>=HEIGHT-1 && right>=WIDTH-1) {
00125               ALPHA_CLS();
00126               return;
00127       }
00128       DARK();
00129       VECTOR(left, top);
00130       BLOCK(1);                       /* setup block erase mode */
00131       INK(0);                         /* use white ink */
00132       VECTOR(right-1, bottom-1);      /* this draws the block */
00133       BLOCK(0);                       /* back to (black) linedraw mode */
00134       INK(1);                         /* black ink */
00135 }
00136 void mf_uniterm_paintrow P4C(screenrow, row,
00137                              pixelcolor, init_color,
00138                              register transspec, transition_vector,
00139                              register screencol, vector_size)
00140 {
00141       register int            blank = !init_color;
00142 #if 0
00143       /* This is the basic */
00144       DARK();
00145       VECTOR(*transition_vector++, row);      /* move to first transition */
00146       do {
00147               INK(blank ^= 1);
00148               VECTOR(*transition_vector++ - 1, row);
00149       } while (--vector_size > 0);
00150 #endif
00151       register screencol      col;
00152       /* However, we optimize the amount of output a bit by blanking
00153          out the row first (since each INK command takes 4 bytes) */
00154       DARK();
00155       if (blank) {
00156               VECTOR(transition_vector[((vector_size-1)&~1)+1] - 1, row);
00157               INK(0);
00158               VECTOR(*transition_vector++, row);
00159               INK(1);
00160               if (vector_size==1)
00161                       return;
00162       }
00163       else {
00164               if (vector_size > 1) {
00165                       VECTOR(transition_vector[vector_size & ~1] - 1, row);
00166                       INK(0);
00167                       VECTOR(transition_vector[1], row);
00168                       INK(1);
00169                       DARK();
00170               }
00171               VECTOR(*transition_vector++, row);
00172       }
00173       do {
00174               col = *transition_vector++;
00175               if ((blank ^= 1) == 0)
00176                       DARK();   /* white -> black; move to first black pixel */
00177               else
00178                       col--;    /* black -> white; blacken to col-1 */
00179               VECTOR(col, row);
00180       } while (--vector_size > 0);
00181 }
00182 #else
00183 int   uniterm_dummy;
00184 #endif /* UNITERMWIN */