home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / contribu / byu_tel2.hqx / tek / vgtek.c < prev    next >
Text File  |  1989-11-10  |  28KB  |  1,294 lines

  1. /*
  2.  
  3. vgtek.c by Aaron Contorer 1987 for NCSA
  4. bugfixes by Tim Krauskopf 1988
  5.  
  6. Takes Tektronix codes as input; sends output to real graphics devices.
  7.  
  8. CHANGES TO MAKE:
  9. Create a function to make sure a window is attached to a real window.
  10.   Calling program will call this whenever switching between active windows.
  11. Pass virtual window number to RG driver so it can call back.
  12.  
  13.  
  14. */
  15.  
  16. #define FALSE 0
  17. #define TRUE 1
  18. #define MAXVG 20 /* maximum number of VG windows */
  19.  
  20. /* temporary states */
  21. #define HIY 0        /* waiting for various pieces of coordinates */
  22. #define EXTRA 1
  23. #define LOY 2
  24. #define HIX 3
  25. #define LOX 4
  26.  
  27. #define DONE 5        /* not waiting for coordinates */
  28. #define ENTERVEC 6    /* entering vector mode */
  29.  
  30. #define CANCEL 7    /* done but don't draw a line */
  31. #define RS 8        /* RS - incremental plot mode */
  32. #define ESCOUT 9    /* when you receive an escape char after a draw command */
  33. #define CMD0 50        /* got esc, need 1st cmd letter */
  34. #define SOMEL 51    /* got esc L, need 2nd letter */
  35. #define IGNORE 52    /* ignore next char */
  36. #define SOMEM 53    /* got esc M, need 2nd letter */
  37. #define IGNORE2 54
  38. #define INTEGER 60    /* waiting for 1st integer part */
  39. #define INTEGER1 61    /* waiting for 2nd integer part */
  40. #define INTEGER2 62    /* waiting for 3rd (last) integer part */
  41. #define COLORINT 70
  42. #define GTSIZE0 75
  43. #define GTSIZE1 76
  44. #define SOMET 80
  45. #define JUNKARRAY 81
  46. #define STARTDISC 82
  47. #define DISCARDING 83
  48.  
  49. /* output modes */
  50. #define ALPHA 0
  51. #define DRAW 1
  52. #define MARK 3
  53. #define TEMPDRAW 101
  54. #define TEMPMOVE 102
  55. #define TEMPMARK 103
  56.  
  57. /* stroked fonts */
  58. #define CHARWIDE 51        /* total horz. size */
  59. #define CHARTALL 76        /* total vert. size */
  60. #define CHARH 10        /* horz. unit size */
  61. #define CHARV 13        /* vert. unit size */
  62.  
  63. /* RG coordinate space dimensions */
  64. #define RGXSIZE 4096
  65. #define RGYSIZE 4096
  66.  
  67. typedef struct {
  68.     int 
  69.     (*init)(), (*point)(), (*drawline)(), (*newwin)(),
  70.     (*clrscr)(), (*pagedone)(), (*dataline)(), (*pencolor)(),
  71.     (*charmode)(), (*showcur)(), (*lockcur)(), (*hidecur)(),
  72.     (*close)(), (*uncover)(), (*info)(),
  73.     (*gmode)(), (*tmode)(), (*gin)();
  74.     char *(*devname)();
  75.     int (*bell)();
  76. } RGLINK;
  77.  
  78. extern char *malloc();
  79. int donothing();
  80.  
  81. struct VGWINTYPE {
  82.     int RGdevice, RGnum;
  83.     char mode,modesave; /* current output mode */
  84.     char loy,hiy,lox,hix,ex,ey; /* current graphics coordinates */
  85.     char nloy,nhiy,nlox,nhix,nex,ney; /* new coordinates */
  86.     int curx,cury;                /* current composite coordinates */
  87.     int winbot,wintop,winleft,winright,wintall,winwide; 
  88.         /* position of window in virutal space */
  89.     int textcol;    /* text starts in 0 or 2048 */
  90.     int intin;        /* integer parameter being input */
  91.     int pencolor;    /* current pen color */
  92.     int fontnum,charx,chary; /* char size */
  93.     int count; /* for temporary use in special state loops */
  94. };
  95.  
  96. #include <stdio.h>
  97. #include "vgtek.h"
  98. #include "vgfont.h"
  99. #include "tekstor.h"
  100.  
  101. static struct VGWINTYPE *VGwin[MAXVG];        /* BYU mod - virtual window descriptors */
  102. static char state[MAXVG],savstate[MAXVG];
  103.     /* save state in a parallel array for speed */
  104. static STOREP VGstore[MAXVG]; /* the store where data for this widow is kept */
  105. static char storing[MAXVG]; /* are we currently saving data from this window */
  106. static int drawing[MAXVG]; /* redrawing or not? */
  107.  
  108. #define NUMSIZES 6 /* number of char sizes */
  109. static int charxset[NUMSIZES] = {56,51,34,31,112,168};
  110. static int charyset[NUMSIZES] = {88,82,53,48,176,264};
  111.  
  112. /*******************************************************************/
  113.  
  114. static donothing()
  115. { }
  116.  
  117.  
  118. static fontnum(vw,n)
  119. int vw,n;
  120. /*
  121.     Set font for window 'vw' to size 'n'.
  122.     Sizes are 0..3 in Tek 4014 standard.
  123.     Sizes 4 & 5 are used internally for Tek 4105 emulation.
  124. */
  125. {
  126.     if (n<0 || n>=NUMSIZES) return(-1);
  127.     VGwin[vw]->fontnum=n;
  128.     VGwin[vw]->charx=charxset[n];
  129.     VGwin[vw]->chary=charyset[n];
  130.     return(0);
  131. }
  132.  
  133.  
  134. static storexy(vw,x,y)
  135. int vw,x,y;
  136. /* set graphics x and y position */
  137. {
  138.     VGwin[vw]->curx = x;
  139.     VGwin[vw]->cury = y;
  140.  
  141. }
  142.  
  143.  
  144. static joinup(hi,lo,e)
  145. int hi,lo,e;
  146. /* returns the number represented by the 3 pieces */
  147. {
  148.     return (((hi & 31 ) << 7) | ((lo & 31 ) << 2) | (e & 3));    /* BYU mod */
  149. } /* end joinup() */
  150.  
  151.  
  152. static newcoord(vw)
  153. int vw;
  154. /*
  155.     Replace x,y with nx,ny
  156. */
  157. {
  158.     VGwin[vw]->hiy = VGwin[vw]->nhiy;
  159.     VGwin[vw]->hix = VGwin[vw]->nhix;
  160.     VGwin[vw]->loy = VGwin[vw]->nloy;
  161.     VGwin[vw]->lox = VGwin[vw]->nlox;
  162.     VGwin[vw]->ey  = VGwin[vw]->ney;
  163.     VGwin[vw]->ex  = VGwin[vw]->nex;
  164.  
  165.     VGwin[vw]->curx = joinup(VGwin[vw]->nhix,VGwin[vw]->nlox,VGwin[vw]->nex);
  166.     VGwin[vw]->cury = joinup(VGwin[vw]->nhiy,VGwin[vw]->nloy,VGwin[vw]->ney);
  167. }
  168.  
  169.  
  170. static linefeed(vw)
  171. /* 
  172.     Perform a linefeed & cr (CHARTALL units) in specified window.
  173. */
  174. {
  175. /*    int y=joinup(VGwin[vw]->hiy,VGwin[vw]->loy,VGwin[vw]->ey);*/
  176.     int y=VGwin[vw]->cury;
  177.     int x;
  178.  
  179.     if (y>VGwin[vw]->chary) y -= VGwin[vw]->chary;
  180.     else {
  181.         y=  3119 - VGwin[vw]->chary;
  182.         VGwin[vw]->textcol = 2048 - VGwin[vw]->textcol;
  183.     }
  184.     x = VGwin[vw]->textcol;
  185.     storexy(vw,x,y);
  186. }
  187.     
  188.  
  189. #ifdef DEBUG
  190. static drawc(vw,c)
  191. int vw;
  192. char c; /* character to draw */
  193. {
  194.     putchar(c);
  195. }
  196. #else
  197. static drawc(vw,c)
  198. int vw;
  199. char c; /* character to draw */
  200. /*
  201.     Draw a stroked character at the current cursor location.
  202.     Uses simple 8-directional moving, 8-directional drawing.
  203. */
  204. {
  205.     int x,y,savex,savey,strokex,strokey;
  206.     int n; /* number of times to perform command */
  207.     char *pstroke; /* pointer into stroke data */
  208.     int hmag,vmag;
  209.  
  210.     if (c==10) {
  211.         linefeed(vw);
  212.         return(0);
  213.     }
  214.  
  215.     if (c==7) {
  216.         (*RG[VGwin[vw]->RGdevice].bell) (VGwin[vw]->RGnum);
  217.         unstore(VGstore[vw]);
  218.         return(0);
  219.     }
  220.  
  221.     savey=y=VGwin[vw]->cury;
  222.     savex=x=VGwin[vw]->curx;
  223.  
  224.     if (c==8) {
  225.         if (savex<=VGwin[vw]->textcol) return(0);
  226.         savex -= VGwin[vw]->charx;
  227.         if (savex < VGwin[vw]->textcol) savex = VGwin[vw]->textcol;
  228.         VGwin[vw]->cury=savey;
  229.         VGwin[vw]->curx=savex;
  230.         return(0);
  231.     }
  232.  
  233.     hmag = VGwin[vw]->charx / 10;
  234.     vmag = VGwin[vw]->chary / 10;
  235.  
  236.     if (3119 - savey < VGwin[vw]->chary) {
  237.         savey=y=  3119 - VGwin[vw]->chary;
  238.     }
  239.  
  240.     if (c<32 || c>126) 
  241.         return(0);
  242.     c -= 32;
  243.     pstroke = VGfont[c];
  244.     while (*pstroke) {
  245.         strokex=x;
  246.         strokey=y;
  247.         n = (*(pstroke++) - 48);    /* run length */
  248.         c = *(pstroke++);            /* direction code */
  249.  
  250.         switch(c) { /* horizontal movement: positive = right */
  251.         case 'e': case 'd': case 'c': case 'y': case 'h': case 'n':
  252.             x += n * hmag;
  253.             break;
  254.  
  255.         case 'q': case 'a': case 'z': case 'r': case 'f': case 'v':
  256.             x -= n * hmag;
  257.         }
  258.  
  259.         switch(c) { /* vertical movement: positive = up */
  260.         case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
  261.             y += n * vmag;
  262.             break;
  263.         case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
  264.             y -= n * vmag;
  265.         }
  266.  
  267.         switch(c) { /* draw or move */
  268.         case 'r': case 't': case 'y': case 'f': case 'h':
  269.         case 'v': case 'b': case 'n':
  270.             clipvec (vw,strokex,strokey,x,y);
  271.             break;
  272.         }
  273.     
  274.     } /* end while not at end of string */
  275.  
  276.     /* Update cursor location to next char position */
  277.     if (savex + 2 * VGwin[vw]->chary <= 4096) savex += VGwin[vw]->charx;
  278.     else {
  279.         savey -= VGwin[vw]->chary;
  280.         if (savey<0) {
  281.             savey=  3119 - VGwin[vw]->chary; 
  282.             VGwin[vw]->textcol = 2048 - VGwin[vw]->textcol;
  283.         }
  284.         savex = VGwin[vw]->textcol;
  285.     }
  286.  
  287.     VGwin[vw]->cury=savey;
  288.     VGwin[vw]->curx=savex;
  289.  
  290. } /* end drawc() */
  291. #endif
  292.  
  293. static clipt(p,q,t0,t1)
  294. float p,q,*t0,*t1;
  295. /* To be called only by clipvec() */
  296. {
  297.     float r;
  298.     int accept = TRUE;
  299.  
  300.     if (p<0.0) {
  301.         r = q/p;
  302.         if (r>*t1) accept = FALSE;
  303.         else if (r>*t0) *t0 = r;
  304.     }
  305.     else if (p>0.0) {
  306.         r = q/p;
  307.         if (r<*t0) accept = FALSE;
  308.         else if (r<*t1) *t1 = r;
  309.     }
  310.     else if (q<0.0) accept = FALSE;
  311.     return(accept);
  312. }
  313.  
  314. #ifdef DEBUG
  315. clipvec(vw,xa,ya,xb,yb)
  316. int vw;
  317. int xa,ya,xb,yb;
  318. {
  319.     printf("%d,%d to %d,%d\n",xa,ya,xb,yb);
  320. }
  321. #else
  322. static clipvec(vw,xa,ya,xb,yb)
  323. int vw;
  324. int xa,ya,xb,yb;
  325.  
  326. /*
  327.     Draw a vector in vw's window from x0,y0 to x1,y1.
  328.     Zoom the vector to the current visible window,
  329.     and clip it before drawing it.
  330.     Uses Liang-Barsky algorithm from ACM Transactions on Graphics,
  331.         Vol. 3, No. 1, January 1984, p. 7.
  332. */
  333. {
  334.     int t,b,l,r;
  335.     float x0,y0,x1,y1,t0,t1,deltay,deltax;
  336.     struct VGWINTYPE *vp;
  337.     vp = VGwin[vw];        /* BYU mod */
  338.  
  339.     t=vp->wintop;
  340.     b=vp->winbot;
  341.     l=vp->winleft;
  342.     r=vp->winright;
  343.  
  344.     /* totally visible */
  345.     if (xa<=r && xb<=r && xa>=l && xb>=l
  346.     &&  ya<=t && yb<=t && ya>=b && yb>=b) {
  347.         (*RG[vp->RGdevice].drawline) (vp->RGnum,
  348.         (int) ((long)((xa - l) * RGXSIZE) / vp->winwide),
  349.         (int) ((long)((ya- b) * RGYSIZE) / vp->wintall),
  350.         (int) ((long)((xb - l) * RGXSIZE) / vp->winwide),
  351.         (int) ((long)((yb- b) * RGYSIZE) / vp->wintall));
  352.         return;
  353.     }
  354.  
  355.     /* trivially invisible */
  356.     if ((xa>r && xb>r) || (xa<l && xb<l) 
  357.     || (ya<b && yb<b) || (ya>t && yb>t)) {
  358.         return;
  359.     }
  360.     
  361.     /* the clipping algorithm */
  362.     x0=(float) xa;
  363.     y0=(float) ya;
  364.     x1=(float) xb;
  365.     y1=(float) yb;
  366.  
  367.     t0=0.0;
  368.     t1=1.0;
  369.     deltax = x1-x0;
  370.  
  371.     if(clipt(-deltax, x0 - l, &t0, &t1)) {
  372.         if (clipt(deltax, r - x0, &t0, &t1)) {
  373.             deltay = y1 - y0;
  374.             if (clipt(-deltay, y0 - b, &t0, &t1)) {
  375.                 if (clipt(deltay, t - y0, &t0, &t1)) {
  376.                     if (t1<1.0) {
  377.                         x1 = x0 + t1*deltax;
  378.                         y1 = y0 + t1*deltay;
  379.                     }
  380.                     if (t0>0.0) {
  381.                         x0 += t0*deltax;
  382.                         y0 += t0*deltay;
  383.                     }
  384. /* draw the line, it is at least partially visible */
  385.     (*RG[vp->RGdevice].drawline) (vp->RGnum,
  386.     (int) ((long)((int)x0 - l) * RGXSIZE / vp->winwide),
  387.     (int) ((long)((int)y0- b) * RGYSIZE / vp->wintall),
  388.     (int) ((long)((int)x1 - l) * RGXSIZE / vp->winwide),
  389.     (int) ((long)((int)y1- b) * RGYSIZE / vp->wintall));
  390.  
  391.                 } 
  392.             } 
  393.         } 
  394.     } /* end if */
  395.  
  396.  
  397. } /* end clipvec() */
  398. #endif
  399.  
  400. /*******************************************************
  401. ********************************************************
  402.  
  403. All routines given below may be called by the user
  404. program.  No routines given above may be called from
  405. the user program.
  406.  
  407. ********************************************************
  408. *******************************************************/
  409.  
  410. VGalloc()        /* BYU mod - allocate this structure to save global space */
  411. {                /* BYU mod */
  412.     int i;        /* BYU mod */
  413.                                     /* BYU mod */
  414.     for (i=0; i<MAXVG; i++) {        /* BYU mod */
  415.         VGwin[i] = (struct VGWINTYPE *) malloc(sizeof(struct VGWINTYPE));    /* BYU mod */
  416.     }            /* BYU mod */
  417. }                /* BYU mod */
  418.  
  419.  
  420. VGinit()
  421. /*
  422.     Initialize the whole VG environment.  Should be called ONCE
  423.     at program startup before using the VG routines.
  424. */
  425. {
  426.     int i;
  427.     for (i=0; i<MAXVG; i++) {
  428.         VGwin[i]->RGdevice = -1; /* no device */
  429.     }
  430. #ifndef DEBUG
  431.     for (i=0; i<MAXRG; i++) { (*RG[i].init)(); }
  432. #endif
  433. }
  434.  
  435.  
  436. VGuncover(vw)
  437. /*
  438.     Make sure window is completely visible, rather than partly or
  439.     completely invisible.
  440.     This function is to be called whenever a window is made active,
  441.     to ensure that the user can see it.
  442. */
  443. {
  444. #ifndef DEBUG
  445.     (*RG[VGwin[vw]->RGdevice].uncover)(VGwin[vw]->RGnum);
  446. #endif
  447. }
  448.  
  449.  
  450. VGdevice(vw,dev)
  451. int vw,dev;
  452. /*
  453.     Detach window from its current device and attach it to the
  454.     specified device.  Returns negative number if unable to do so.
  455.     Sample application:  switching an image from #9 to Hercules.
  456.     Must redraw after calling this.
  457. */
  458. {
  459.     int newwin;
  460.  
  461.     newwin = (*RG[dev].newwin)();
  462.     if (newwin<0) return(newwin); /* unable to open new window */
  463.  
  464.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  465.     VGwin[vw]->RGdevice = dev;
  466.     VGwin[vw]->RGnum = newwin;
  467.     VGwin[vw]->pencolor = 1;
  468.     fontnum(vw,1);
  469.     return(0);
  470. }
  471.  
  472.  
  473. VGnewwin(device)
  474. int device; /* number of RG device to use */
  475. /*
  476.     Create a new VG window and return its number.
  477.     New window will be attached to specified real device.
  478.     Returns -1 if unable to create a new VG window.
  479. */
  480. {
  481.     int vw=0;
  482.     while (vw<MAXVG && VGwin[vw]->RGdevice != -1) vw++;
  483.     if (vw == MAXVG) {
  484.         return(-1);
  485.     }
  486.     VGstore[vw] = newstore();
  487.     if (VGstore[vw] == NULL) {
  488.         return(-1); /* no memory */
  489.     }
  490.     VGwin[vw]->RGdevice=device;
  491.  
  492.     VGwin[vw]->RGnum = (*RG[device].newwin)();
  493.     if (VGwin[vw]->RGnum< 0) {
  494.         /* no windows available on device */
  495.         freestore(VGstore[vw]);
  496.         return(-1);
  497.     }
  498.             
  499.     VGwin[vw]->mode=ALPHA;
  500.     state[vw]=DONE;
  501.     storing[vw]=TRUE;
  502.     VGwin[vw]->textcol=0;
  503.     drawing[vw]=1;
  504.     fontnum(vw,0);
  505.     (*RG[device].pencolor)(VGwin[vw]->RGnum,1);
  506.  
  507.     storexy(vw,0,3071);
  508.     VGzoom(vw,0,0,4095,3119);
  509.     return(vw);
  510. }
  511.  
  512.  
  513. VGclrstor(vw)
  514. int vw;
  515. /* 
  516.     Clear the store associated with window vw.  
  517.     All contents are lost.
  518.     User program can call this whenever desired.
  519.     Automatically called after receipt of Tek page command.
  520. */
  521. {
  522.     freestore(VGstore[vw]);
  523.     VGstore[vw] = newstore();
  524.         /* Don't have to check for errors; there was definitely
  525.         enough memory. */
  526. }
  527.  
  528.  
  529. VGdumpstore(vw,func)
  530. int vw;
  531. int (*func)();
  532. /*
  533.     Successively call the function pointed to by 'func' for each
  534.     character stored from window vw.  Each character will
  535.     be passed in integer form as the only parameter.  A value of -1
  536.     will be passed on the last call to indicate the end of the data.
  537. */
  538. {
  539.     int data;
  540.     STOREP st=VGstore[vw];
  541.  
  542.     topstore(st);
  543.     while ((data=nextitem(st)) != -1) (*func)(data);
  544.     (*func)(-1);
  545. }
  546.  
  547.  
  548. VGdraw(vw,c)
  549. int vw;
  550. char c; /* the latest input char */
  551. /*
  552.     This is the main Tek emulator process.  Pass it the window and
  553.     the latest input character, and it will take care of the rest.
  554.     Calls RG functions as well as local zoom and character drawing
  555.     functions.
  556. */
  557. {
  558.     char cmd;
  559.     char value;
  560.     char goagain; /* true means go thru the function a second time */
  561.     struct VGWINTYPE *vp;
  562.     vp = VGwin[vw];            /* BYU mod */
  563.  
  564.  
  565.     /*** MAIN LOOP ***/
  566.      do {
  567.  
  568.         cmd=(c >> 5) & 0x03;
  569.         value=c & 0x1f;
  570.         goagain=FALSE;
  571.  
  572.         switch(state[vw]) {
  573.  
  574.         case HIY: /* beginning of a vector */
  575.             vp->nhiy = vp->hiy;
  576.             vp->nhix = vp->hix;
  577.             vp->nloy = vp->loy;
  578.             vp->nlox = vp->lox;
  579.             vp->ney  = vp->ey;
  580.             vp->nex  = vp->ex;
  581.     
  582.             switch(cmd) {
  583.             case 0:
  584.                 if (value == 27) {        /* escape sequence */
  585.                     state[vw] = ESCOUT;
  586.                     savstate[vw] = HIY;
  587.                 }
  588.                 else if (value < 27) {    /* ignore */
  589.                     break;
  590.                 }
  591.                 else {
  592.                     state[vw]=CANCEL;
  593.                     goagain=TRUE;
  594.                 }
  595.                 break;
  596.             case 1: /* hiy */
  597.                 vp->nhiy=value;
  598.                 state[vw]=EXTRA;
  599.                 break;
  600.             case 2: /* lox */
  601.                 vp->nlox=value;
  602.                 state[vw]=DONE;
  603.                 break;
  604.             case 3: /* extra or loy */
  605.                 vp->nloy=value;
  606.                 state[vw]=LOY;
  607.                 break;
  608.             }
  609.             break;        
  610.     
  611.         case ESCOUT:
  612.             if (value != 13 && value != 10
  613.                 && value != 27 && value != '~') {/* skip all EOL-type characters */
  614.                 state[vw] = savstate[vw];
  615.                 goagain = TRUE;
  616.             }
  617.             break;
  618.  
  619.         case EXTRA:    /* got hiy; expecting extra or loy */
  620.             switch(cmd) {
  621.             case 0:
  622.                 if (value == 27) {        /* escape sequence */
  623.                     state[vw] = ESCOUT;
  624.                     savstate[vw] = EXTRA;
  625.                 }
  626.                 else if (value < 27) {    /* ignore */
  627.                     break;
  628.                 }
  629.                 else {
  630.                     state[vw]=DONE;
  631.                     goagain=TRUE;
  632.                 }
  633.                 break;
  634.             case 1: /* hix */
  635.                 vp->nhix=value;
  636.                 state[vw]=LOX;
  637.                 break;
  638.             case 2: /* lox */
  639.                 vp->nlox=value;
  640.                 state[vw]=DONE;
  641.                 break;
  642.             case 3: /* extra or loy */
  643.                 vp->nloy=value;
  644.                 state[vw]=LOY;
  645.                 break;
  646.             }
  647.             break;
  648.     
  649.         case LOY: /* got extra or loy; next may be loy or something else */
  650.             switch(cmd) {
  651.             case 0:
  652.                 if (value == 27) {        /* escape sequence */
  653.                     state[vw] = ESCOUT;
  654.                     savstate[vw] = LOY;
  655.                 }
  656.                 else if (value < 27) {    /* ignore */
  657.                     break;
  658.                 }
  659.                 else {
  660.                     state[vw]=DONE;
  661.                     goagain=TRUE;
  662.                 }
  663.                 break;
  664.             case 1: /* hix */
  665.                 vp->nhix=value;
  666.                 state[vw]=LOX;
  667.                 break;
  668.             case 2: /* lox */
  669.                 vp->nlox=value;
  670.                 state[vw]=DONE;
  671.                 break;
  672.             case 3: /* this is loy; previous loy was really extra */
  673.                 vp->ney = (vp->nloy >> 2) & 3;
  674.                 vp->nex = (vp->nlox) & 3;
  675.                 vp->nloy=value;
  676.                 state[vw]=HIX;
  677.                 break;
  678.             }
  679.             break;
  680.     
  681.         case HIX: /* hix or lox */
  682.             switch(cmd) {
  683.             case 0:
  684.                 if (value == 27) {        /* escape sequence */
  685.                     state[vw] = ESCOUT;
  686.                     savstate[vw] = HIX;
  687.                 }
  688.                 else if (value < 27) {    /* ignore */
  689.                     break;
  690.                 }
  691.                 else {
  692.                     state[vw]=DONE;
  693.                     goagain=TRUE;
  694.                 }
  695.                 break;
  696.             case 1: /* hix */
  697.                 vp->nhix=value;
  698.                 state[vw]=LOX;
  699.                 break;
  700.             case 2: /* lox */
  701.                 vp->nlox=value;
  702.                 state[vw]=DONE;
  703.                 break;
  704.             }
  705.              break;
  706.     
  707.         case LOX: /* must be lox */
  708.             switch(cmd) {
  709.             case 0:
  710.                 if (value == 27) {        /* escape sequence */
  711.                     state[vw] = ESCOUT;
  712.                     savstate[vw] = LOX;
  713.                 }
  714.                 else if (value < 27) {    /* ignore */
  715.                     break;
  716.                 }
  717.                 else {
  718.                     state[vw]=DONE;
  719.                     goagain=TRUE;
  720.                 }
  721.                 break;
  722.             case 2:
  723.                 vp->nlox=value;
  724.                 state[vw]=DONE;
  725.                 break;
  726.             }
  727.             break;
  728.     
  729.         case ENTERVEC:
  730.             if (c==7) vp->mode = DRAW;
  731.             if (c < 27)
  732.                 break;
  733.             state[vw] = HIY;
  734.             vp->mode = TEMPMOVE;
  735.             vp->modesave = DRAW;
  736.             goagain = TRUE;
  737.             break;
  738.  
  739.         case RS:
  740.             switch (c) {
  741.             case ' ':                /* pen up */
  742.                 vp->modesave = vp->mode;
  743.                 vp->mode = TEMPMOVE;
  744.                 break;
  745.             case 'P':                /* pen down */
  746.                 vp->mode = DRAW;
  747.                 break;
  748.             case 'D':                /* move up */
  749.                 vp->cury++;
  750.                 break;
  751.             case 'E':
  752.                 vp->cury++;
  753.                 vp->curx++;
  754.                 break;
  755.             case 'A':
  756.                 vp->curx++;
  757.                 break;
  758.             case 'I':
  759.                 vp->curx++;
  760.                 vp->cury--;
  761.                 break;
  762.             case 'H':
  763.                 vp->cury--;
  764.                 break;
  765.             case 'J':
  766.                 vp->curx--;
  767.                 vp->cury--;
  768.                 break;
  769.             case 'B':
  770.                 vp->curx--;
  771.                 break;
  772.             case 'F':
  773.                 vp->cury++;
  774.                 vp->curx--;
  775.                 break;
  776.             case 27:
  777.                 savstate[vw] = RS;
  778.                 state[vw] = ESCOUT;
  779.                 break;
  780.  
  781.             default:
  782. /*                storexy(vw,vp->curx,vp->cury);*/
  783.                 state[vw] = CANCEL;
  784.                 goagain = TRUE;
  785.                 break;
  786.             }
  787.             if (vp->mode == DRAW)
  788.                 clipvec(vw,vp->curx,vp->cury,vp->curx,vp->cury);
  789. #ifdef DEBUG
  790.             printf("RS: %d,%d\n",vp->curx,vp->cury);
  791. #endif
  792.             break;
  793.  
  794.         case CMD0: /* get 1st letter of cmd */
  795.             switch(c) {
  796.             case 29:                    /* GS, start draw */
  797.                 state[vw] = DONE;
  798.                 goagain = TRUE;
  799.                 break;
  800.             case '8':
  801.                 fontnum(vw,0);
  802.                 state[vw]=DONE;
  803.                 break;
  804.             case '9':
  805.                 fontnum(vw,1);
  806.                 state[vw]=DONE;
  807.                 break;
  808.             case ':':
  809.                 fontnum(vw,2);
  810.                 state[vw]=DONE;
  811.                 break;
  812.             case ';':
  813.                 fontnum(vw,3);
  814.                 state[vw]=DONE;
  815.                 break;
  816.             case 12: /* form feed = clrscr */
  817.                 if (isclearenabled(vw)) {    /* BYU mod */
  818.                     VGpage(vw);                /* BYU mod */
  819.                     VGclrstor(vw);            /* BYU mod */
  820.                     }                        /* BYU mod */
  821.                 break;
  822.             case 'L':
  823.                 state[vw] = SOMEL;
  824.                 break;
  825.             case 'K':
  826.                 state[vw] = IGNORE;
  827.                 break;
  828.             case 'M':
  829.                 state[vw] = SOMEM;
  830.                 break;
  831.             case 'T':
  832.                 state[vw] = SOMET;
  833.                 break;
  834.             case 26:
  835.                 (*RG[vp->RGdevice].gin)(vp->RGnum);
  836.                 unstore(VGstore[vw]);
  837.                 unstore(VGstore[vw]);
  838.                 break;
  839.             case 10:
  840.             case 13:
  841.             case 27:
  842.             case '~':
  843.                 savstate[vw] = DONE;
  844.                 state[vw] = ESCOUT;
  845.                 break;            /* completely ignore these after ESC */
  846.             default:
  847.                 state[vw] = DONE;
  848.             } /* end switch */
  849.             break;
  850.     
  851.         case SOMET:
  852.             /* Got ESC T; now handle 3rd char. */
  853.             switch(c) {
  854.             case 'G': /* set surface color map */
  855.                 state[vw]=INTEGER;
  856.                 savstate[vw]=JUNKARRAY;
  857.                 break;
  858.             case 'F': /* set dialog area color map */
  859.                 state[vw]=JUNKARRAY;
  860.                 break;
  861.             default:
  862.                 state[vw]=DONE;
  863.             }            
  864.             break;
  865.  
  866.         case JUNKARRAY:
  867.             /* This character is the beginning of an integer array
  868.             to be discarded.  Get array size. */
  869.             savstate[vw]=STARTDISC;
  870.             state[vw]=INTEGER;
  871.             break;                    
  872.  
  873.         case STARTDISC:
  874.             /* Begin discarding integers. */
  875.             vp->count = vp->intin + 1;
  876.             goagain=TRUE;
  877.             state[vw]=DISCARDING;
  878.             break;
  879.  
  880.         case DISCARDING:
  881.             /* We are in the process of discarding an integer array. */
  882.             goagain=TRUE;
  883.             if (!(--(vp->count))) state[vw]=DONE;
  884.             else if (vp->count==1) {
  885.                 state[vw]=INTEGER;
  886.                 savstate[vw]=DONE;
  887.             } else {
  888.                 state[vw]=INTEGER;
  889.                 savstate[vw]=DISCARDING;
  890.             }
  891.             break;
  892.  
  893.         case INTEGER:
  894.             if (c & 0x40) {
  895.                 vp->intin = c & 0x3f;
  896.                 state[vw] = INTEGER1;
  897.             } else {
  898.                 vp->intin = c & 0x0f;
  899.                 if (!(c & 0x10)) vp->intin *= -1;
  900.                 state[vw] = savstate[vw];
  901.             }
  902.             break;
  903.  
  904.         case INTEGER1:
  905.             if (c & 0x40) {
  906.                 vp->intin = (vp->intin << 6) | (c & 0x3f);
  907.                 state[vw] = INTEGER2;
  908.             } else {
  909.                 vp->intin = (vp->intin << 4) | (c & 0x0f);
  910.                 if (!(c & 0x10)) vp->intin *= -1;
  911.                 state[vw] = savstate[vw];
  912.             }
  913.             break;
  914.  
  915.         case INTEGER2:
  916.             vp->intin = (vp->intin << 4) | (c & 0x0f);
  917.             if (!(c & 0x10)) vp->intin *= -1;
  918.             state[vw] = savstate[vw];
  919.             break;
  920.  
  921.         case IGNORE: /* ignore next char; it's not supported */
  922.             state[vw]=DONE;
  923.             break;
  924.     
  925.         case IGNORE2: /* ignore next 2 chars */
  926.             state[vw]=IGNORE;
  927.             break;
  928.  
  929.         case SOMEL: /* now process 2nd letter */
  930.             switch(c) {
  931.             case 'F': /* move */
  932.                 vp->modesave = vp->mode;
  933.                 vp->mode = TEMPMOVE;
  934.                 state[vw] = HIY;
  935.                 break;
  936.             case 'G': /* draw */
  937.                 vp->modesave = vp->mode;
  938.                 vp->mode = TEMPDRAW;
  939.                 state[vw] = HIY;
  940.                 break;
  941.             case 'H': /* marker */
  942.                 vp->modesave = vp->mode;
  943.                 vp->mode = TEMPMARK;
  944.                 state[vw] = HIY;
  945.                 break;    
  946.             default:
  947.                 state[vw]=DONE;
  948.             } /* end switch */
  949.             break;
  950.     
  951.         case SOMEM:
  952.             switch(c) {
  953.             case 'C': /* set graphtext size */
  954.                 savstate[vw]=GTSIZE0;
  955.                 state[vw]=INTEGER;
  956.                 break;
  957.             case 'L': /* set line index */
  958.                 savstate[vw]=COLORINT;
  959.                 state[vw]=INTEGER;
  960.                 break;
  961.             default:
  962.                 state[vw]=DONE;
  963.             } /* end switch */
  964.             break;
  965.     
  966.         case COLORINT: /* set line index; have integer */
  967.             vp->pencolor=vp->intin;
  968.             (*RG[vp->RGdevice].pencolor)
  969.                 (vp->RGnum,vp->intin);
  970.             state[vw]=CANCEL;
  971.             goagain=TRUE; /* we ignored current char; now process it */
  972.             break;
  973.  
  974.         case GTSIZE0:
  975.             /* discard the first integer; get the 2nd */
  976.             state[vw]=INTEGER; /* get the important middle integer */
  977.             savstate[vw]=GTSIZE1;
  978.             goagain=TRUE;
  979.             break;
  980.  
  981.         case GTSIZE1:
  982.             /* integer is the height */
  983.             if (vp->intin < 88) fontnum(vw,0);
  984.             else if (vp->intin < 149) fontnum(vw,4);
  985.             else fontnum(vw,5);
  986.             state[vw]=INTEGER; /* discard last integer */
  987.             savstate[vw]=DONE;
  988.             goagain=TRUE;
  989.             break;
  990.  
  991.         case DONE: /* ready for anything */
  992.             switch(c) {
  993.             case 31:
  994.                 vp->mode=ALPHA; 
  995.                 state[vw]=CANCEL;
  996.                 break;
  997.             case 30:
  998.                 state[vw]=RS;
  999.                 break;
  1000.             case 28:
  1001.                 if (!cmd) {
  1002.                     vp->mode=MARK;
  1003.                     state[vw]=HIY;
  1004.                     }
  1005.                 break;
  1006.             case 29:
  1007.                 state[vw]=ENTERVEC;
  1008.                 break;
  1009.             case 27:
  1010.                 state[vw]=CMD0;
  1011.                 break;
  1012.             default:
  1013.                 if (vp->mode==ALPHA) { 
  1014.                     drawc(vw,c);
  1015.                     state[vw]=CANCEL;
  1016.                 }
  1017.                 else if (vp->mode==DRAW && cmd) {
  1018.                     state[vw]=HIY;
  1019.                     goagain=TRUE;
  1020.                 }
  1021.                 else if (vp->mode==MARK && cmd) {
  1022.                     state[vw]=HIY;
  1023.                     goagain=TRUE;
  1024.                 }
  1025.                 else if (vp->mode==DRAW && (c == 13 || c == 10)) {
  1026.                     /* break drawing mode on CRLF */
  1027.                     vp->mode=ALPHA; 
  1028.                     state[vw]=CANCEL;
  1029.                 }
  1030.                 else
  1031.                     state[vw] = CANCEL;    /* do nothing */                
  1032.             } /* end switch(c) */
  1033.         } /* end switch(state) */
  1034.     
  1035.         if (state[vw]==DONE) {
  1036.             if (vp->mode==TEMPMOVE) {
  1037.                 vp->mode=vp->modesave;
  1038.                 newcoord(vw);
  1039.                 }
  1040.             else if (vp->mode==DRAW || vp->mode==TEMPDRAW) {
  1041.                 clipvec(vw,vp->curx,vp->cury,
  1042.                     joinup(vp->nhix,vp->nlox,vp->nex),
  1043.                     joinup(vp->nhiy,vp->nloy,vp->ney));
  1044.  
  1045.                 if (vp->mode==TEMPDRAW) vp->mode=vp->modesave;
  1046.                 newcoord(vw);
  1047.                 }
  1048.             else if (vp->mode==MARK || vp->mode==TEMPMARK) {
  1049.                 /* draw marker */
  1050.                 newcoord(vw);
  1051.                 }
  1052.             } /* end if done */
  1053.  
  1054.         if (state[vw]==CANCEL) state[vw]=DONE;
  1055.  
  1056.     } while (goagain);
  1057.     /*** END OF MAIN LOOP ***/
  1058.  
  1059. } /* end VGdraw() */
  1060.  
  1061.  
  1062. VGpage(vw)
  1063. int vw;
  1064. /*  Clear screen and have a few other effects:
  1065.     - Return graphics to home position (0,3071)
  1066.     - Switch to alpha mode
  1067.     This is a standard Tek command; don't look at me.
  1068. */
  1069. {
  1070. #ifndef DEBUG
  1071.     (*RG[VGwin[vw]->RGdevice].clrscr)(VGwin[vw]->RGnum);
  1072.     (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,1);
  1073. #endif
  1074.     VGwin[vw]->mode=ALPHA;
  1075.     state[vw] = DONE;
  1076.     VGwin[vw]->textcol=0;
  1077.     fontnum(vw,0);
  1078.     storexy(vw,0,3071);
  1079. } /* end page */
  1080.  
  1081.  
  1082. VGpred(vw,dest)
  1083. int vw,dest;
  1084. /*
  1085.     Redraw window 'vw' in pieces to window 'dest'.
  1086.     Must call this function repeatedly to draw whole image.
  1087.     Only draws part of the image at a time, to yield CPU power.
  1088.     Returns 0 if needs to be called more, or 1 if the image
  1089.     is complete.  Another call would result in the redraw beginning again.
  1090.     User should clear screen before beginning redraw.
  1091. */
  1092. {
  1093.     int data;
  1094.     STOREP st=VGstore[vw];
  1095.     int count=0;
  1096.  
  1097.     if (drawing[vw]) {        /* wasn't redrawing */
  1098.         topstore(st);
  1099.         drawing[vw] = 0;    /* redraw incomplete */
  1100.     }
  1101.  
  1102.     while ( ++count < PREDCOUNT && ((data=nextitem(st)) != -1) ) {
  1103.         VGdraw(dest,data);
  1104.     }
  1105.  
  1106.     if (data == -1) drawing[vw] = 1; /* redraw complete */
  1107.     return(drawing[vw]);
  1108. }
  1109.  
  1110.  
  1111. VGstopred(vw,dest)
  1112. /*
  1113.     Abort VGpred redrawing of specified window.
  1114.     Must call this routine if you decide not to complete the redraw.
  1115. */
  1116. {
  1117.     drawing[vw]=1;
  1118. }
  1119.  
  1120.  
  1121. VGredraw(vw,dest)
  1122. int vw,dest;
  1123. /*
  1124.     Redraw the contents of window 'vw' to window 'dest'.
  1125.     Does not yield CPU until done.
  1126.     User should clear the screen before calling this, to avoid 
  1127.     a messy display.
  1128. */
  1129. {
  1130.     int data;
  1131.     STOREP st=VGstore[vw];
  1132.  
  1133.     topstore(st);
  1134.     while ((data=nextitem(st)) != -1) {
  1135.         VGdraw(dest,data);
  1136.     }
  1137. }
  1138.  
  1139.  
  1140. VGzoom(vw,x0,y0,x1,y1)
  1141. /*
  1142.     Set new borders for zoom/pan region.
  1143.     x0,y0 is lower left; x1,y1 is upper right.
  1144.     User should redraw after calling this.
  1145. */
  1146. {
  1147.     VGwin[vw]->winbot=y0;
  1148.     VGwin[vw]->winleft=x0;
  1149.     VGwin[vw]->wintop=y1;
  1150.     VGwin[vw]->winright=x1;
  1151.     VGwin[vw]->wintall = y1-y0+1;
  1152.     VGwin[vw]->winwide = x1-x0+1;
  1153.     VGgiveinfo(vw);
  1154. }
  1155.  
  1156. VGwhatzoom(vw,px0,py0,px1,py1)
  1157.     int vw,*px0,*py0,*px1,*py1;
  1158.     {
  1159.     *py0 = VGwin[vw]->winbot;
  1160.     *px0 = VGwin[vw]->winleft;
  1161.     *py1 = VGwin[vw]->wintop;
  1162.     *px1 = VGwin[vw]->winright;
  1163. }
  1164.  
  1165. VGzcpy(src,dest)
  1166. /*
  1167.     Set zoom/pan borders for window 'dest' equal to those for window 'src'.
  1168.     User should redraw window 'dest' after calling this.
  1169. */
  1170. {
  1171.     VGzoom(dest,VGwin[src]->winleft, VGwin[src]->winbot,
  1172.     VGwin[src]->winright, VGwin[src]->wintop);
  1173. }
  1174.  
  1175.  
  1176. VGclose(vw)
  1177. /*
  1178.     Close virtual window.
  1179.     Release its real graphics device and its store.
  1180. */
  1181. {
  1182.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  1183.     freestore(VGstore[vw]);
  1184.     VGwin[vw]->RGdevice = -1;
  1185. }
  1186.  
  1187.  
  1188. VGwrite(vw,data,count)
  1189. int vw, count;
  1190. char *data;
  1191. /*
  1192.     Draw the data pointed to by 'data' of length 'count'
  1193.     on window vw, and add it to the store for that window.
  1194.     This is THE way for user program to pass Tektronix data.
  1195. */
  1196. {
  1197.     char *c = data;
  1198.     char *end = &(data[count]);
  1199.  
  1200.     if (VGwin[vw]->RGdevice == -1 || vw >= MAXVG || vw < 0) return(-1);
  1201.         /* window not open */
  1202.  
  1203.     if (storing[vw]) {
  1204.         while (c != end) {
  1205.             if (*c == 24)                /* ASC CAN character */
  1206.                 return(c-data+1);
  1207.             addstore(VGstore[vw], *c);
  1208.             VGdraw(vw,*c++);
  1209.         }
  1210.     } else {
  1211.         while (c != end) {
  1212.             if (*c == 24)
  1213.                 return(c-data+1);
  1214.             else
  1215.                 VGdraw(vw,*c++);
  1216.         }
  1217.     }
  1218.     return(count);
  1219. }
  1220.  
  1221.  
  1222. VGgiveinfo(vw)
  1223. int vw;
  1224. /*
  1225.     Send interesting information about the virtual window down to
  1226.     its RG, so that the RG can make VG calls and display zoom values
  1227. */
  1228. {
  1229.     (*RG[VGwin[vw]->RGdevice].info)(VGwin[vw]->RGnum,
  1230.     vw,
  1231.     VGwin[vw]->winbot,
  1232.     VGwin[vw]->winleft,
  1233.     VGwin[vw]->wintop,
  1234.     VGwin[vw]->winright);
  1235. }
  1236.  
  1237.  
  1238. char *
  1239. VGrgname(rgdev)
  1240. int rgdev;
  1241. /*
  1242.     Return a pointer to a human-readable string
  1243.     which describes the specified real device
  1244. */
  1245. {
  1246.     return(*RG[rgdev].devname)();
  1247. }
  1248.  
  1249.  
  1250. VGgmode(rgdev)
  1251. int rgdev;
  1252. /* Put the specified real device into graphics mode */
  1253. {
  1254. #ifndef DEBUG
  1255.     (*RG[rgdev].gmode)();
  1256. #endif
  1257. }
  1258.  
  1259.  
  1260. VGtmode(rgdev)
  1261. int rgdev;
  1262. /* Put the specified real device into text mode */
  1263. {
  1264.     (*RG[rgdev].tmode)();
  1265. }
  1266.  
  1267.  
  1268. VGgindata(vw,x,y,c,a)
  1269. int vw,x,y;
  1270. char c;
  1271. char *a;
  1272. /*
  1273.     Translate data for output as GIN report.
  1274.  
  1275.     User indicates VW number and x,y coordinates of the GIN cursor.
  1276.     Coordinate space is 0-4095, 0-4095 with 0,0 at the bottom left of
  1277.     the real window and 4095,4095 at the upper right of the real window.
  1278.     'c' is the character to be returned as the keypress.
  1279.     'a' is a pointer to an array of 5 characters.  The 5 chars must
  1280.     be transmitted by the user to the remote host as the GIN report.
  1281. */
  1282. {
  1283.     long x2,y2;
  1284.  
  1285.     x2 = ((x * VGwin[vw]->winwide) / RGXSIZE + VGwin[vw]->winleft) >> 2;
  1286.     y2 = ((y * VGwin[vw]->wintall) / RGYSIZE + VGwin[vw]->winbot) >> 2;
  1287.  
  1288.     a[0] = c;
  1289.     a[1] = 0x20 | ((x2 & 0x03E0) >> 5);
  1290.     a[2] = 0x20 | (x2 & 0x001F);
  1291.     a[3] = 0x20 | ((y2 & 0x03E0) >> 5);
  1292.     a[4] = 0x20 | (y2 & 0x001F);
  1293. }
  1294.