h54225
s 00002/00001/01603
d D 1.2 83/03/17 17:03:44 tes 2 1
c update
e
s 01604/00000/00000
d D 1.1 83/03/17 15:34:09 tes 1 0
c date and time created 83/03/17 15:34:09 by tes
e
u
4
U
t
T
I 1
#define INT32 long
#define INT16 int
#define BYTE char

#include "ratdef.c"
#include "gksdef.c"
#include "ddcom.c"

INT16 actred[8], actgrn[8], actblu[8], reqred[8], reqgrn[8], reqblu[8];
INT16 clrreg[3], alpharow, alphacol;

static INT16 solpat[] = {0xffff, 0xffff, 0xffff,0xffff};

static INT16 pattern[] = {0x3333, 0x3333, 0x3333, 0x3333, /* vertical lines */
			  0x0000, 0x0000, 0xffff, 0xffff, /* horizontal lines */
			  0xcccc, 0x6666, 0x3333, 0x9999, /* +45 degrees */
			  0x3333, 0x6666, 0xcccc, 0x9999, /* -45 degrees */
                          0xaaaa, 0x5555, 0xaaaa, 0x5555};/* dithered */
   

ddtipg ()
/*####################################################################*/
/*                                                                    */
/*         THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER       */
/*         A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,          */
/*         COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE         */
/*         WITH THE TERMS OF THAT AGREEMENT.                          */
/*                                                                    */
/*         COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.           */
/*         ALL RIGHTS RESERVED.                                       */
/*                                                                    */
/*    Function: GIOS for TI Pegasus                                   */
/*                                                                    */
/*    NOTE: All parameters are passed as 32 bit pointers.  Since      */
/*          Computer Innovations C can't handle 32 bit pointers,      */
/*          parameters are accessed via assembler routines and        */
/*          are not passed via c.                                     */
/*                                                                    */
/*    Input Parameters:                                               */
/*           contrl      - An int array with following information    */
/*                         contrl[1] - opcode for driver function     */
/*                         contrl[2] - number of vertices in array    */
/*                                     ptsin. Each vertex consists of */
/*                                     an x and a y coordinate so the */
/*                                     length of this array is twice a*/
/*                                     long as the number of vertices */
/*                                     specified.                     */
/*                         contrl[4] - length of int array intin      */
/*           contrl(6-n) - Opcode dependent information               */
/*                                                                    */
/*           intin   -     Array of int input parameters              */
/*           ptsin   -     Array of input coordinate data             */
/*                                                                    */
/*    Output Parameters:                                              */
/*           contrl[3]   - number of vertices in array ptsout         */
/*                         Each vertex consists of an x and a y       */
/*                         coordinate so the length of this array is  */
/*                         twice as long as the number of vertices    */ 
/*                         specified.                                 */
/*           contrl[5]   - length of int array intout                 */
/*           contrl(6-n) - Opcode dependent information               */
/*                                                                    */
/*           intout  -     Array of int output parameters             */
/*           ptsout  -     Array of output coordinate data            */
/*                                                                    */
/*    Routines Called:                                                */
/*           ddline - draw a line on the graphic device               */
/*           ddtext - display graphic text                            */
/*           detipg - erase screen                                    */
/*           ddmark - marker emulation routine                        */
/*           dctipg - set color on TI Pegasus                         */
/*           ddfill - Fill polygon                                    */
/*           ddflin - fill part of raster line with given pattern     */ 
/*           gimnmx - bound an int variable                           */
/*           eralpha - erase alpha plane on TI Pegasus                */
/*           bitblt - turn on bits on TI Pegasus                      */
/*           rdpixel - read color value of pixel                      */
/*           ttyin  - get character from console unechoed             */
/*           ttyout - output character to console                     */
/*           ttysot - output character string to console              */
/*           getctl - get element of contrl array                     */
/*           getini - get element of intin array                      */
/*           getpti - get element of ptsin array                      */
/*           putctl - put element into contrl array                   */
/*           putino - put element into intout array                   */
/*           putpto - put element into ptsout array                   */
/*                                                                    */
/*####################################################################*/
{
 
#define X_LIMITS_DEVICE 719
D 2
#define Y_LIMITS_DEVICE 299
E 2
I 2
#define Y_LIMITS_DEVICE 287               /* Really 299, but use 287 to */
					  /*   avoid status line        */
E 2
#define MAX_COLOR 7                       /* Color indices in range 0-7 */
#define DEFAULT 1                         /* Default input device */
#define CROSSHAIRS 2                      /* Crosshairs input device */
#define NONE 0
#define REQUEST 1                         /* Request mode */
#define SAMPLE 2                          /* Sample mode */
#define REPLACE 1
#define OVERSTRIKE 2
#define XOR 3
#define ERASE 4
#define ANDMODE 5
#define HOLLOW 0
#define SOLID 1
#define PATTERN 2
#define HATCH 3
#define ROWS_FILL 4
#define COLS_FILL 16
#define HALF_WIDTH 8
#define HALF_HEIGHT 4
#define UP_ARROW BIGA                    /* Last char of up arrow seq- ESC A */
#define DOWN_ARROW BIGB                  /* Last char of down arrow  - ESC B */
#define LEFT_ARROW BIGD                  /* Last char of left arrow  - ESC C */
#define RIGHT_ARROW BIGC                 /* Last char of right arrow - ESC D */
#define CHANGE_RATE BIGH                 /* Last char of home sequence-ESC H */
#define SLOW_RATE 1
#define FAST_RATE 10


   static INT16 chrwid[5] = {  5, 10, 15, 20, 25 };
   static INT16 chrhgt[5] = {  7, 14, 21, 28, 35 };
   static INT16 celwid[5] = {  6, 12, 18, 24, 30 };
   static INT16 celhgt[5] = {  8, 16, 24, 32, 40 };

   static INT16 inired[8] = { 0, 1000,    0,    0,    0, 1000, 1000, 1000 };
   static INT16 inigrn[8] = { 0,    0, 1000,    0, 1000, 1000,    0, 1000 };
   static INT16 iniblu[8] = { 0,    0,    0, 1000, 1000,    0, 1000, 1000 };

   static INT16 iniino[45] = {
      X_LIMITS_DEVICE,    /* Addressable width in rasters of screen */
      Y_LIMITS_DEVICE,    /* Addressable height in rasters of screen */
      1,                  /* Device coordinates in raster units */

      /* micrometers per raster along the x axis */
      /*   the screen has about 80 dots/inch horizontally (.0125 inch/pixel) */
      /*   the vertical dimension is 1.8 * horizontal                        */
      318,                /* Width of a pixel in micrometers */
      572,                /* Height of a pixel in micrometers */
      5,                  /* Number of character heights */
      7,                  /* Number of line types */
      1,                  /* Number of line widths */
      5,                  /* Number of marker types */
      1,                  /* Number of marker height */
      1,                  /* Number of fonts */
      5,                  /* Number of patterns */
      5,                  /* Number of hatch styles */
      8,                  /* Number of predefined colors */
      1,                  /* Number of GDPs       */
      1,                  /* Bar GDP available    */
      -1,                 /* No other GDPs available */
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      3,                  /* Bar GDP uses fill area attributes */
      -1,                 /* List of associated bundle tables */
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      -1,
      YES,                /* Color capability flag */
      YES,                /* Text rotation capability flag */
      YES,                /* Fill area capability flag */
      YES,                /* Pixel operation capability flag */
      8,                  /* Number of available colors */
      1,                  /* Number of locator devices */
      0,                  /* Number of valuator devices */
      1,                  /* Number of choice devices */
      1,                  /* Number of string devices */
      2 } ;               /* Workstation type  */

      static INT16 ptsino[12] = {
         0,
         7,               /* Minimum character height in device coordinates */
         0,
         35,              /* Maximum character height in device coordinates */
         1,               /* Minimum line width in NDC space */
         0,
         1,               /* Maximum line width in NDC space */
         0,
         0,
         8,               /* Minimum marker height in NDC space */
         0,
         8 } ;            /* Maximum marker height in NDC space */

   static BYTE curup[]  = { ESC, BIGA };
   static BYTE curdwn[] = { ESC, BIGB };
   static BYTE currgt[] = { ESC, BIGC };
   static BYTE curlft[] = { ESC, BIGD };
   static BYTE curhom[] = { ESC, BIGH };
   static BYTE erscrn[] = { ESC, BIGJ };
   static BYTE erslin[] = { ESC, BIGK };
   static BYTE poscur[] = { ESC, BIGY };
   static BYTE revon[]  = { ESC, LETP };
   static BYTE revoff[] = { ESC, LETQ };

   static BYTE inikeys[] = { ESC, ':', ';', ESC, 'p', 0,   /* PFK 1 = ESC p */
                             ESC, ':', '<', ESC, 'q', 0,   /* PFK 2 = ESC q */
                             ESC, ':', '=', ESC, 'r', 0,   /* PFK 3 = ESC r */
                             ESC, ':', '>', ESC, 's', 0,   /* PFK 4 = ESC s */
                             ESC, ':', '?', ESC, 't', 0,   /* PFK 5 = ESC t */
                             ESC, ':', '@', ESC, 'u', 0,   /* PFK 6 = ESC u */
                             ESC, ':', 'A', ESC, 'v', 0,   /* PFK 7 = ESC v */
                             ESC, ':', 'B', ESC, 'w', 0,   /* PFK 8 = ESC w */
                             ESC, ':', 'C', ESC, 'x', 0,   /* PFK 9 = ESC x */
                             ESC, ':', 'D', ESC, 'y', 0,   /* PFK 10= ESC y */
                             ESC, ':', 'H', ESC, 'A', 0,   /* up arrow      */
                             ESC, ':', 'K', ESC, 'D', 0,   /* left arrow    */
                             ESC, ':', 'M', ESC, 'C', 0,   /* right arrow   */
                             ESC, ':', 'P', ESC, 'B', 0,   /* down arrow    */
                             ESC, ':', 'G', ESC, 'H', 0 }; /* home key      */

   INT16 gimnmx(), mult(), divid();
   INT16 getctl(), getini(), getpti(), gitoch(), rdpixel();
   INT16 *iptr;
   INT16 opcode, i, j, k, index, done, ginok, line[7], hgtin;
   INT16 m, nx, ny, xrpt, yrpt, colptr, xincr, yincr, incr;
   INT16 y, xlo, xhi, ylo, yhi, xold, yold;
   INT16 *rowbeg, *rowptr, rowcnt;
   register INT16 x, colcnt, itemp;
   BYTE c;

   putctl (2,0);         /* Initialize ptsout count to zero (0) */

   opcode = getctl(0);   /* Obtain a local copy of the current opcode */

   switch (opcode) {

   /*  opcode open workstation */
   case OPEN_WORKSTATION:
 
      putctl (2, 6);        /* Set to number of vertices in ptsout */
      putctl (4, 45);       /* Set to number of output parameters  */
      
      iptr = iniino;
      for (i=0; i < 45; i++) {   /* Initialize intout array */
	 putino (i, *iptr++);
	 } 

      iptr = ptsino;
      for (i=0; i < 12; i++) {   /* Initialize ptsout array */
	 putpto (i, *iptr++);
	 }

      ndlntp = getini(1);         /* Set current device line style */
      if (ndlntp < 1 || ndlntp > 7) ndlntp = 1;
      ndclrl = gimnmx (getini(2), 0, MAX_COLOR);   /* current polyline color */
      ndmktp = getini(3);                          /* Set polymarker type */
      if (ndmktp < 1 || ndmktp > 5) ndmktp = 3;    /* use default */
      ndclrm = gimnmx (getini(4), 0, MAX_COLOR);   /* current polymarker clr*/
      ndclrt = gimnmx (getini(6), 0, MAX_COLOR);   /* current text color */ 
      ndfstl = getini(7);                          /* fill interior style */
      if (ndfstl < HOLLOW || ndfstl > HATCH) ndfstl = HOLLOW;
      if (ndfstl == HATCH) ndfstl = PATTERN;
      ndflpt = getini(8);                          /* fill style index */
      if (ndflpt < 1 || ndflpt > 5) ndflpt = 1;    /* style 1 is default */
      ndclrf = gimnmx (getini(9), 0, MAX_COLOR);   /* current fill area clr */

      /* initialize predefined color table */
      /* set the requested colors to be the same as the actual colors */
      for (i=0; i<=MAX_COLOR; i++) {
	 actred[i] = inired[i];
	 reqred[i] = inired[i];
	 actgrn[i] = inigrn[i];
	 reqgrn[i] = inigrn[i];
	 actblu[i] = iniblu[i];
	 reqblu[i] = iniblu[i];
	 }

      /* initialize predefined colors on device */
      clrreg [0] = 0xe2;                           /* Red color register */
      clrreg [1] = 0xb4;                           /* Green color register */
      clrreg [2] = 0xd8;                           /* Blue color register  */
      dctipg (clrreg [0], clrreg [1], clrreg [2]);

      ndtxrt = 0;           /* default rotation is 0 degrees */
      ndtxsz = 1;           /* default size is the smallest  */
      ndlcmd = REQUEST;     /* default locator mode is request */
      ndvlmd = REQUEST;     /* default valuator mode is request */
      ndstmd = REQUEST;     /* default string mode is request */
      ndwrmd = REPLACE;     /* default writing mode is replace */

      ttysot (90, inikeys); /* initialize function keys and arrow keys */
      eralpha ();           /* erase alpha plane */
      detipg ();            /* erase graphics plane */
      break;

/*  opcode CLOSE_WORKSTATION */
case CLOSE_WORKSTATION:
      break;

/*  opcode CLEAR_WORKSTATION */
case CLEAR_WORKSTATION:
      detipg ();      /* erase graphics planes */
      eralpha ();     /* erase alpha plane just in case */
      break;

/*  opcode UPDATE_WORKSTATION */
case UPDATE_WORKSTATION:
      break;

/*  opcode ESCAPE */
case ESCAPE:
   opcode = getctl(5);             /* Get function id */

   switch (opcode) {

   case INQ_ADDRESSABLE_CELLS:
      putino (0, 24);              /* 24 rows */
      putino (1, 80);              /* 80 cols */
      break;

   case EXIT_GRAPHICS_MODE:
      detipg ();                   /* erase graphics planes */
      eralpha ();                  /* erase alpha plane     */
      ttysot (2, curhom);          /* home alpha cursor     */
      alpharow = 1;
      alphacol = 1;
      break;

   case ENTER_GRAPHICS_MODE:
      detipg ();                   /* erase graphics planes */
      eralpha ();                  /* erase alpha plane     */
      break;
     
   case CURSOR_UP:
      alpharow = gimnmx (++alpharow, 1, 24);
      ttysot (2, curup);
      break;

   case CURSOR_DOWN:
      alpharow = gimnmx (--alpharow, 1, 24);
      ttysot (2, curdwn);
      break;

   case CURSOR_RIGHT:
      alphacol = gimnmx (++alphacol, 1, 80);
      ttysot (2, currgt);
      break;

   case CURSOR_LEFT:
      alphacol = gimnmx (--alphacol, 1, 80);
      ttysot (2, curlft);
      break;

   case HOME_CURSOR:
      ttysot (2, curhom);
      break;

   case ERASEEOS:
      ttysot (2, erscrn);
      break;

   case ERASEEOL:
      ttysot (2, erslin);
      break;

   case DIRECT_CURSOR_ADDRESS:
      ttysot (2, poscur);
      i = gimnmx (getini (0), 1, 24);  /* set the row */
      alpharow = i;
      ttyout (i+31);
      i = gimnmx (getini (1), 1, 80);  /* set the column */
      alphacol = i;
      ttyout (i+31);
      break;

   case OUTPUT_CURSOR_ADDRESSABLE_TEXT:
      k = getctl (3);                  /* get character count */
      for (i=0; i<k; i++) {
	 c = getini (i);
	 ttyout (c);                   /* ttyout takes char parameters */
	 }
      break;

   case REV_ON:
      ttysot (2, revon);
      break;

   case REV_OFF:
      ttysot (2, revoff);
      break;

   case INQ_CURRENT_CURSOR_ADDRESS:
      putino (0, alpharow);
      putino (1, alphacol);
      break;

      }
   break;

/*  opcode POLYLINE */
case LINE:

   k = (getctl(1) - 1) << 1;
   for (i=0; i<k; i += 2) {
      ddline (getpti (i), getpti (i+1), getpti (i+2), getpti (i+3), ndclrl);
      }
   break;

/*  opcode polymarker  */
case MARKER:
      
   k = ndlntp;               /* Save current line style */
   ndlntp = SOLID;           /* Set line type to solid */
   m = getctl (1) << 1;      /* Get number of vertices */
   for (i=0; i<m; i +=2) {
      ddmark (getpti (i), getpti (i+1));  /* Output marker at each point */
      }

   ndlntp = k;               /* Restore current line style */
   break;

/*  opcode text */
case TEXT:

   /* This is not the optimum way to do this but since the ptr to intin */
   /* which contains the character string is a 32 bit ptr and Computer  */
   /* Innovations C can't handle this, ddtext must access intin directly*/
   /* using the assembler function getini.                              */

   /*         x           y        length       size  rotation  */
   ddtext (getpti (0), getpti (1), getctl (3), ndtxsz, ndtxrt);
   break;

/*  opcode fill area */
case FILL_AREA:

   if (ndfstl != HOLLOW) ddfill (getctl (1));          /* Fill area */

   j = ndlntp;                   /* Save line style and change to solid */
   ndlntp = SOLID;

   k = (getctl (1) - 1) << 1;    /* Determine # of lines to draw */
   for (i=0; i<k; i += 2) {      /* Outline area                 */
      ddline (getpti (i), getpti (i+1), getpti (i+2), getpti (i+3), ndclrf);
      }

   /* Make sure area is closed */
   ddline (getpti (k), getpti (k+1), getpti (0), getpti (1), ndclrf);

   ndlntp = j;                   /* Restore line style */
   break;

/*  opcode cell array */
case CELL_ARRAY:

   xlo = getpti (0);                   /* get corners of defining rectangle */
   ylo = getpti (1);
   xhi = getpti (2);
   yhi = getpti (3);

   colcnt = getctl (5);               /* get length of each row */
   nx = getctl (6);                   /* get number elements used per row */
   ny = getctl (7);                   /* get number of rows */
   m = getctl (8);                    /* get writing mode for cell array */
   if (m < 1 || m > 4) m = 1;         /* out of range mode goes to replace */

   i = xhi - xlo + 1;                 /* determine width of rectangular area */
   nx = gimnmx (nx, 1, i);            /* make sure not more cols than width  */
   i = i + nx - 1;                    /* determine repeat count for each  */
   xrpt = divid (i, nx, &j);          /*    color across a row            */

   i = yhi - ylo + 1;                 /* determine height of rectangular area*/
   ny = gimnmx (ny, 1, i);            /* make sure not more rows than height */
   i = i + ny - 1;                    /* determine repeat count for each row */
   yrpt = divid (i, ny, &j);

   y = yhi;                           /* start at top of rectangular area */
   for (i=0; i<ny; i++) {             /* loop over rows */
      for (rowcnt=1; rowcnt<=yrpt; rowcnt++) {   /* repeat rows appropriately*/
	 if (y >= ylo) {              /* make sure y-coordinate in range  */
	    x = xlo;                     /* initialize x coordinate          */
	    colptr = mult (i, colcnt);   /* initialize index into color array*/
	    for (j=1; j<=nx; j++) {      /* loop over color indices in row   */
               itemp = gimnmx (getini (colptr++), 0, MAX_COLOR);

	       /* output each pixel the appropriate number of times */
	       for (k=1; k<=xrpt; k++) {
	          if (x <= xhi) bitblt (x++, y, itemp, m);
	          }

               }
	    }
         y--;                         /* decrement y-coordinate */
	 }
      }

   break;

/*  opcode generalized drawing primitive */
case GDP:
   opcode = getctl (5);                /* Get function id */
   if (opcode == BAR) {
      xlo = getpti (0);
      ylo = getpti (1);
      xhi = getpti (2);
      yhi = getpti (3);

      if (ndfstl != HOLLOW) {

	 /* set up pointer to fill pattern */
         if (ndfstl == SOLID) rowbeg = &solpat[0];
         else                 rowbeg = &pattern[(ndflpt-1) << 2];
	 rowptr = rowbeg;

         rowcnt = 1;
	 for (y=ylo; y<=yhi; y++) {
	    ddflin (xlo, xhi, y, *rowptr, 0, ndclrf, ndwrmd);
            if (rowcnt < ROWS_FILL){ 
	       rowcnt++;
	       rowptr++;                  /* move to next row of fill mask */
	       }
            else {
	       rowcnt = 1;
	       rowptr = rowbeg;           /* start row over again */
	       }
            }
         }

      /* outline bar in all cases */
      k = ndlntp;                         /* Save current line style */
      ndlntp = SOLID;                     /* Set line style to solid */

      ddline (xlo, ylo, xhi, ylo, ndclrf);
      ddline (xhi, ylo, xhi, yhi, ndclrf);
      ddline (xhi, yhi, xlo, yhi, ndclrf);
      ddline (xlo, yhi, xlo, ylo, ndclrf);

      ndlntp = k;                         /* Restore line style */
      }
   break;

/*  opcode set character height */
case CHAR_HEIGHT:
      hgtin = getpti (1);              /* Get requested height */
      ndtxsz = 0;
      iptr = &chrhgt[0];
      do {
         if (*iptr > hgtin) break;
	 ndtxsz++;                     /* Update size */
	 iptr++;                       /* Update pointer to char height */
         } while (ndtxsz <= 4);
      ndtxsz = gimnmx (ndtxsz, 1, 5);
      i = ndtxsz - 1;

      putctl (2, 2);                    /* Set the number vertices */
      putpto (0, chrwid[i]);            /* Return values selected */
      putpto (1, chrhgt[i]);
      putpto (2, celwid[i]);
      putpto (3, celhgt[i]);
   break;

/*  opcode set character up vector */
case CHAR_UP_VECTOR:
   j = divid ((getini (0) +450), 900, &i);/* Round angle up to nearest 90 */
   i = divid (j, 4, &ndtxrt);             /* Make sure between 0 & 3 */
   putino (0, mult (ndtxrt, 900));        /* Return angle selected in tenths */
					  /* of degrees                      */
   break;

/*  opcode color */
case COLOR_REPRESENTATION:
      i = gimnmx (getini (0), 0, MAX_COLOR);      /* 8 colors available 0-7 */

      iptr = line;                                /* Init ptr to array      */
      j = getini (1);                             /* Get requested clr vals */
      reqred [i] = j;
      *iptr++ = j;                                /* Also save in line array*/
      j = getini (2);
      reqgrn [i] = j;
      *iptr++ = j;
      j = getini (3);
      reqblu [i] = j;
      *iptr++ = j;

      /* Determine actual color to be set.  The TI only has 1 bit per    */
      /* so if a color has more than 50 % of a primary (red, green,      */
      /* blue) turn the primary on.                                      */
      iptr = line;
      for (j=0; j<3; j++) {
	 k = *iptr;
	 if (k <= 500) k = 0;
	 else          k = 1000;
	 *iptr++ = k;
	 }
      actred [i] = line [0];
      actgrn [i] = line [1];
      actblu [i] = line [2];

      /* set color on device */
      iptr = clrreg;                        /* iptr = ptr to clrreg array   */
      rowptr = line;                        /* rowptr = ptr to line array   */
					    /*   containing r,g,b components*/
					    /*   of color                   */
      k = 1 << i;                           /* create mask based on clr ind */
      for (j=0; j<3; j++) {
	 *iptr &= ~k;                       /* clear index bit in color reg */
	 if (*rowptr++ != 0) *iptr |= k;    /* set bit if primary on  */
	 iptr++;                            /* update color register pointer */
	 }

      dctipg (clrreg[0], clrreg[1], clrreg[2]); /* tell device about new clr*/

      break;

/*  opcode set polyline linetype */
case LINE_TYPE:
      ndlntp = getini (0);

      /* If line type out of range, set to default of solid */
      if (ndlntp < 1 || ndlntp > 7) ndlntp = 1;
      putino (0, ndlntp);             /* Return linestyle seleced */
      break;

/*  opcode set polyline colour index */
case LINE_COLOR:
      ndclrl = gimnmx (getini (0), 0 ,MAX_COLOR);  /* Map index to 0 - 7 */
      putino (0, ndclrl);                          /* Return index selected */
      break;

/*  opcode set polymarker type */
case MARKER_TYPE:
      ndmktp = getini (0);
      if (ndmktp < 1 || ndmktp > 5) ndmktp = 3; /* Out of range defaults */
                                                /* to 3                  */
      putino (0, ndmktp);
      break;

/*  opcode set polymarker colour index */
case MARKER_COLOR:
      ndclrm = gimnmx (getini (0), 0 ,MAX_COLOR);   /* Map index to 0 - 7 */
      putino (0, ndclrm);                           /* Return index selected */
      break;

/*  opcode set text color index */
case TEXT_COLOR:
      ndclrt = gimnmx (getini (0), 0 ,MAX_COLOR);   /* Map index to 0 - 7 */
      putino (0, ndclrt);                           /* Return index selected */
      break;

/*  opcode set fill interior style */
case FILL_INTERIOR_STYLE:
   ndfstl = getini (0);

   /* Out of range fill interior style defaults to hollow */

   if (ndfstl < HOLLOW || ndfstl > HATCH) ndfstl = HOLLOW;
   if (ndfstl == HATCH) ndfstl = PATTERN;
   putino (0, ndfstl);
   break;

/*  opcode set fill style index */
case FILL_STYLE_INDEX:
   ndflpt = getini (0);                          /* fill style index */
   if (ndflpt < 1 || ndflpt > 5) ndflpt = 1;     /* style 1 is default */
   putino (0, ndflpt);
   break;

/*  opcode set fill area color index */
case FILL_COLOR_INDEX:
      ndclrf = gimnmx (getini (0), 0 ,MAX_COLOR);   /* Map index to 0 - 7 */
      putino (0, ndclrf);                           /* Return index selected */
      break;

/*  opcode inquire colour representation */
case INQ_COLOR_REPRESENTATION:
   i = gimnmx (getini (0), 0, MAX_COLOR);  /* Map index to 0-7 */
   putino (0, i);                          /*  This is what we inquired on */
   if (getini (1) == 0) {                  /* Inquiry type,0=set,1=realized */
      putino (1, reqred[i]);    /* Return r, g, b components originally     */
      putino (2, reqgrn[i]);    /*     requested                            */
      putino (3, reqblu[i]);
      }
   else {
      putino (1, actred[i]);    /* Return r, g, b components actually       */
      putino (2, actgrn[i]);    /*     realized                             */
      putino (3, actblu[i]);
      }
   break;
 
/*  opcode inquire pixel array */
case INQ_CELL_ARRAY:
   xlo = getpti (0);               /* get corners of rectangular area */
   ylo = getpti (1);
   xhi = getpti (2);
   yhi = getpti (3);
   nx = getctl (5);                /* save length of each row and */
   ny = getctl (6);                /*    number of rows in color index array */
   putctl (9, 0);                  /* assume valid inquiry request */

   itemp = xhi - xlo + 1;          /* determine number of elements per row */
   j = gimnmx (nx, 1, itemp);
   xincr = divid (itemp + nx - 1, j, &k);     
   putctl (7, j);                  /* return elements used per row */

   itemp = yhi - ylo + 1;          /* determine number of rows to use */
   i = gimnmx (ny, 1, itemp);
   yincr = divid (itemp + ny - 1, i, &k);
   putctl (8, i);                  /* return number of rows used */

   y = yhi;                        /* start at top of rectangular area */
   for (rowcnt=0; rowcnt < i; rowcnt++) {
      x = xlo;                     /* start each row at leftmost pixel */
      colptr = mult (rowcnt, nx);  /* compute index to start of row in */
				   /*    output color index array      */
      for (colcnt=0; colcnt < j; colcnt++) {
	 putino (colptr++, rdpixel (x, y));        /* read color index */
	 x += xincr;               /* move to next pixel in row */
	 }
      y -= yincr;                  /* move to next row */
      }
   break;

/*  opcode input locator  */
case INPUT_LOCATOR:
   putctl (4, NONE);          /* Initialize status to not successful */
   i = getini (0);            /*  Check locator device for validity */
   if (i != DEFAULT && i !=CROSSHAIRS) return;

   x = getpti (0);            /* Get initial point for GIN */
   y = getpti (1);
   incr = FAST_RATE;          /* Initialize cursor increment to fast */

   done = NO;
   do {

      /* determine endpoints of crosshair */
      xlo = gimnmx (x - HALF_WIDTH, 0, X_LIMITS_DEVICE);
      ylo = gimnmx (y - HALF_HEIGHT, 0, Y_LIMITS_DEVICE);
      xhi = gimnmx (x + HALF_WIDTH, 0, X_LIMITS_DEVICE);
      yhi = gimnmx (y + HALF_HEIGHT, 0, Y_LIMITS_DEVICE);

      /* draw crosshair in color index 7 using xor writing mode */
      for (i=xlo; i<=xhi; i++) {
	 bitblt (i, y, 7, XOR);
	 }
      for (i=ylo; i<=yhi; i++) {
	 bitblt (x, i, 7, XOR);
	 }
      xold = x;                          /* save x,y coordinate of cursor */
      yold = y;

      ttyin (&c);                        /* read a character */
      itemp = c & 0xff;
      if (itemp == ESC) {                /* check for special key     */
	 ttyinw (&c);                    /* get char if one available */
	 if (c != -1) itemp = c & 0xff;
	 }

      switch (itemp) {                   /* update status based on keystroke */

      case UP_ARROW:
	 y += incr;
	 break;

      case DOWN_ARROW:
	 y -= incr;
	 break;

      case LEFT_ARROW:
	 x -= incr;
	 break;

      case RIGHT_ARROW:
	 x += incr;
	 break;

      case CHANGE_RATE:
	 if (incr == FAST_RATE) incr = SLOW_RATE;
	 else                   incr = FAST_RATE;
	 break;

      default:                       /* non cursor movement key struck   */
         done = YES;
         break;
      }

   x = gimnmx (x, 0, X_LIMITS_DEVICE);  /* make sure cursor still on screen */
   y = gimnmx (y, 0, Y_LIMITS_DEVICE);

   /* remove cursor at current position in color index 7 using xor mode */
   for (i=xlo; i<=xhi; i++) {
      bitblt (i, yold, 7, XOR);
      }
   for (i=ylo; i<=yhi; i++) {
      bitblt (xold, i, 7, XOR);
      }

   } while (! done);


   putctl (4, 1);          /* Set successful flag  */
   putctl (2, 1);          /* Set the number of output vertices  */

   putpto (0, x);          /* Return the locator point */
   putpto (1, y);
 
   putino (0, itemp);      /* Return the locator input character */

   break;

/*  opcode input choice */
case INPUT_CHOICE:
   putctl (4, NO);                    /* Assume invalid choice */
   putino (0, getini (1));
   ttyin (&c);                        /* Get a character       */
   itemp = c & 0xff;
   if (itemp == ESC) {                /* Char was function key lead in   */
      ttyinw (&c);                    /* Get next char if one available  */
      i = c & 0xff;
      if (i >= LETP && i <= LETY) {   /* Valid function key was struck   */
	 putino (0, i - 111);         /* Return function key struck      */
				      /*   Map p-z to 1-10               */
	 putctl (4, YES);             /* Valid choice                    */
         }
      }
   break;

/*  opcode input string */
case INPUT_STRING:
   if (getini (0) != DEFAULT) {       /* Check for valid string device */
      putctl (4, NONE);
      return;
      }
   ginok = NONE;
   i = 0;
   k = getini (1);                    /* Save maximum size */
   m = getini (2);                    /* Save echo status  */
   do {
      ttyin (&c);                     /* Get a character  */
      if (m !=0) ttyout (c);          /* Echo character if necessary */
      itemp = c & 0xff;               /* Move char to std length int */
      if (itemp == NEWLINE) break;
      if (itemp == CR) break;
      if (i+1 > k) break;             /* No room in output array */
      putino (i, itemp);
      i++;
      } while (i <= k);
   putctl (4, i);                     /* Return request status */
   break;

/*  opcode set writing mode */
case SET_WRITING_MODE:
   ndwrmd = getini (0);

   /* if writing mode requested is out of range, use replace mode */
   if (ndwrmd < REPLACE || ndwrmd > ERASE) ndwrmd = REPLACE;
   putino (0, ndwrmd);                /* Return mode selected */
   break;

/*  opcode set input mode */
case SET_INPUT_MODE:
   putino (0, REQUEST);               /* Only request mode input available */
   break;

}                                     /* end of opcode switch */

return;
}

ddmark (x, y)
/*#####################################################################*/
/*                                                                     */
/*          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER       */
/*          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,          */
/*          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE         */
/*          WITH THE TERMS OF THAT AGREEMENT.                          */
/*                                                                     */
/*          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.           */
/*          ALL RIGHTS RESERVED.                                       */
/*                                                                     */
/*     Function: Place a marker at the current location                */
/*                                                                     */
/*     Input Parameters:                                               */
/*            x,y     - x/y location for marker                        */
/*     Output Parameters:                                              */
/*            none                                                     */
/*                                                                     */
/*     Routines Called:                                                */
/*            ddline - draw line on the device                         */
/*                                                                     */
/*#####################################################################*/
INT16 x,y;
 
{
#define MARK_PERIOD   1  
#define MARK_PLUS 2
#define MARK_STAR 3
#define MARK_O 4
#define MARK_X 5
#define FULLSZ 6
#define HALFSZ 3
#define FPERSZ 2
#define HPERSZ 1
 
   INT16 fsize, hsize, x1, x2, y1, y2;
   INT16 xytemp;
 
   if (ndmktp == MARK_PERIOD) {
      fsize = FPERSZ;
      hsize = HPERSZ;
      }
   else {
      fsize = FULLSZ;
      hsize = HALFSZ;
      }
 
   x1 = x - hsize;        /*clip marker to device limits */
   x2 = x1 + fsize;
   y1 = y - hsize;
   y2 = y1 + fsize;
   if ((x1 < 0) || (y1 < 0) || (x2 > X_LIMITS_DEVICE) || 
       (y2 > Y_LIMITS_DEVICE)) return;
 
   /* output appropriate marker centered on location */
 
   if (ndmktp == MARK_PERIOD || ndmktp == MARK_O) {
      ddline (x1, y1, x2, y1, ndclrm);
      ddline (x2, y1, x2, y2, ndclrm);
      ddline (x2, y2, x1, y2, ndclrm);
      ddline (x1, y2, x1, y1, ndclrm);
      }
   else {
      if (ndmktp == MARK_X || ndmktp == MARK_STAR) {
	 ddline (x1, y1, x2, y2, ndclrm);
	 ddline (x1, y2, x2, y1, ndclrm);
         }
      if (ndmktp == MARK_PLUS || ndmktp == MARK_STAR) {
         xytemp = y1 + hsize;
	 ddline (x1, xytemp, x2, xytemp, ndclrm);
	 xytemp = x1 + hsize;
	 ddline (xytemp, y1, xytemp, y2, ndclrm);
         }
      }
   return;
}

ddfill (icnt)
/*########################################################################*/
/*#                                                                      #*/
/*#          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER        #*/
/*#          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,           #*/
/*#          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE          #*/
/*#          WITH THE TERMS OF THAT AGREEMENT.                           #*/
/*#                                                                      #*/
/*#          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.            #*/
/*#          ALL RIGHTS RESERVED.                                        #*/
/*#                                                                      #*/
/*#     Function: Fill polygon                                           #*/
/*#                                                                      #*/
/*#     Input Parameters:                                                #*/
/*#            icnt - number of points in polygon                        #*/
/*#     Output Parameters:                                               #*/
/*#            none                                                      #*/
/*#                                                                      #*/
/*#     Routines Called:                                                 #*/
/*#            ddint - compute intersection of lines                     #*/
/*#            ddsort - sort values in ascending order                   #*/
/*#            getpti - get element from ptsin array                     #*/
/*#            ddflin - fill part of raster line with given pattern      #*/ 
/*#                                                                      #*/
/*########################################################################*/
INT16 icnt;
{
INT16 getpti(), xvert[50], xcount, i, j, k, currow, x1, y1, x2, y2;
INT16 xint, yprev, delta, first, qint, *rowptr, *rowbeg, rowcnt;
INT16 ymin, ymax, last;
register INT16 x, colcnt, temp;

/* determine min and max x,y of polygon */
ymin = 32767;
ymax = -32767;

for (i=1; i < (icnt << 1) ; i += 2 ) {
   temp = getpti (i);             /* get y-coordinate */
   if (temp < ymin) ymin = temp;  /* check for min */
   if (temp > ymax) ymax = temp;  /* check for max */
   }

/* set up pointer to fill pattern */
if (ndfstl == SOLID) rowbeg = &solpat[0];
else                 rowbeg = &pattern[(ndflpt-1) << 2];
i = ymin & 0x3;      /* determine correct row of fill pattern - keyed to 0,0 */
rowcnt = i + 1;
rowptr = rowbeg + i;

/* loop over rows from ymin to ymax */
for (currow=ymin; currow <= ymax; currow++) {

   xcount = 0;      /* initialize intersection count */
   first = -1;      /* initialize pointer to first edge with intersection */
   last = icnt - 1; /* index of last edge */

   /* loop over edges of polygon computing intersections with scan line */
   for (j=0; j <= icnt; j++) {
      temp = j;                          /* doing normal point */
      if (temp == icnt) temp = first;    /* special - doing first intersec */
					 /*   point for the second time    */
      k = (temp << 1);                   /* compute index in ptsin array   */
      x1 = getpti (k++);                 /* get first pt                   */
      y1 = getpti (k++);
      if (temp == last) {                /* doing last edge                */
	 x2 = getpti (0);                
	 y2 = getpti (1);
	 }
      else {                             /* not doing last edge            */
	 x2 = getpti (k++);              
	 y2 = getpti (k);
	 }
      
      ddint (currow, x1, y1, x2, y2, &qint, &xint);  /* intersection ? */

      if (qint == YES) {
	 delta = y2 - y1;
	 if (delta > 0) {                /* positive slope */
	    if (first < 0) {             /* this is first intersection-used */
					 /*   to initialize algorithm. It   */
					 /*   must be saved and run through */
					 /*   a second time to get correct  */
					 /*   intersecton point.            */
               first = j;
	       yprev = currow;           /* seed pt for algorithm           */
	       qint = NO;
	       }
            else {                       /* not first intersection          */
	       if (currow == yprev+1) yprev = currow;/* dir change - keep pt*/
	       else                   qint = NO;     /* don't keep pt       */
	       }
            }
         else {                          /* negative slope */
	    if (first < 0) {             /* this is first intersection-used */
					 /*   to initialize algorithm. It   */
					 /*   must be saved and run through */
					 /*   a second time to get correct  */
					 /*   intersecton point.            */
               first = j;
	       yprev = currow - 1;       /* seed pt for algorithm           */
	       qint = NO;
	       }
            else {                       /* not first intersection          */
	       if (currow == yprev) yprev = currow-1;/* dir change - keep pt*/
	       else                 qint = NO;       /* don't keep pt       */
	       }
            }

         if (qint == YES) {              /* intersection valid */
	    xvert[xcount++] = xint;
	    }
         }
      }                                  /* end of loop over edges         */

   ddsort (xcount, xvert);               /* sort x-vertices                */

   /* fill between pairs of vertices */

   xcount &= ~1;                         /* number of vertices must be even */
   for (i=0; i < xcount ; i += 2) {
      j = xvert[i];
      ddflin (j, xvert[i+1], currow, *rowptr, (j & 0xf), ndclrf, ndwrmd);
      }

   if (rowcnt < ROWS_FILL){ 
      rowcnt++;
      rowptr++;                  /* move to next row of fill mask */
      }
   else {
      rowcnt = 1;
      rowptr = rowbeg;           /* start row over again */
      }

   }              /* End of a scan line */
}
ddsort (count, array)
/*########################################################################*/
/*#                                                                      #*/
/*#          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER        #*/
/*#          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,           #*/
/*#          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE          #*/
/*#          WITH THE TERMS OF THAT AGREEMENT.                           #*/
/*#                                                                      #*/
/*#          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.            #*/
/*#          ALL RIGHTS RESERVED.                                        #*/
/*#                                                                      #*/
/*#     Function: Bubble sort integer array in ascending order           #*/
/*#                                                                      #*/
/*#     Input Parameters:                                                #*/
/*#            count - number of elements in array                       #*/
/*#            array - integer array to be sorted                        #*/
/*#                                                                      #*/
/*#     Output Parameters:                                               #*/
/*#            array - integer array in sorted order                     #*/
/*#                                                                      #*/
/*#     Routines Called:                                                 #*/
/*#            none                                                      #*/
/*#                                                                      #*/
/*########################################################################*/
INT16 count, *array;
{
INT16 i, j, k, *ptr1, *ptr2;

for (i = count-1; i > 0; i--) {
   ptr1 = array;
   ptr2 = ptr1;
   ptr2++;
   for (j = 0; j < i; j++) {
      if (*ptr1 > *ptr2) {   /* switch pair of values */
	 k = *ptr1;
	 *ptr1 = *ptr2;
	 *ptr2 = k;
	 }
      ptr1++;
      ptr2++;
      }
   }
}
ddint (yscan, x1, y1, x2, y2, qint, xint)
/*########################################################################*/
/*#                                                                      #*/
/*#          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER        #*/
/*#          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,           #*/
/*#          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE          #*/
/*#          WITH THE TERMS OF THAT AGREEMENT.                           #*/
/*#                                                                      #*/
/*#          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.            #*/
/*#          ALL RIGHTS RESERVED.                                        #*/
/*#                                                                      #*/
/*#     Function: Determine intersection of scan line with polygon edge  #*/
/*#                                                                      #*/
/*#     Input Parameters:                                                #*/
/*#            yscan - horizontal scan line                              #*/
/*#            x1,y1 - first point of line                               #*/
/*#            x2,y2 - second point of line                              #*/
/*#     Output Parameters:                                               #*/
/*#            qint - 1 if lines intersect, else 0                       #*/
/*#            xint - x-coordinate of intersection                       #*/
/*#                                                                      #*/
/*#     Routines Called:                                                 #*/
/*#            none                                                      #*/
/*#                                                                      #*/
/*########################################################################*/
INT16 yscan, x1, y1, x2, y2, *qint, *xint;
{

INT16 dx, dy, adx, ady, adx2, ady2, i, itemp;
INT16 xtemp1, xtemp2, ytemp1, ytemp2, xend, temp, temp2, xincr;
INT16 qchang;
register INT16 x, y, d, ytest;

*qint = NO;
xtemp1 = x1;
xtemp2 = x2;
ytemp1 = y1;
ytemp2 = y2;
 
dx = xtemp2 - xtemp1;
dy = ytemp2 - ytemp1;
if (dy == 0) return;               /* throw away horizontal lines */
temp  = (yscan - ytemp1) & 0x8000; /* test if line crosses scan line */
temp2 = (yscan - ytemp2) & 0x8000;
if ((temp & temp2) == 0) {
   if (ytemp1 == yscan) {    /* test for intersection at endpoints */
      *xint = xtemp1;
      *qint = YES;
      return;
      }
   else if (ytemp2 == yscan) {
      *xint = xtemp2;
      *qint = YES;
      return;
      }
   }
if (temp == temp2) return;  /* no intersection with scan line */

adx = (dx >= 0) ? dx : -dx;   /* adx = abs (dx) */
ady = (dy >= 0) ? dy : -dy;   /* ady = abs (dy) */
qchang = NO;
 
if (ady > adx) {     /* switch x and y if slope > 1 */
   temp = xtemp1;
   xtemp1 = ytemp1;
   ytemp1 = temp;
   temp = xtemp2;
   xtemp2 = ytemp2;
   ytemp2 = temp;
   temp = adx;
   adx = ady;
   ady = temp;
   qchang = YES;
   }
 
adx2 = adx << 1;     /* adx2 = adx * 2 */
ady2 = ady << 1;     /* ady2 = ady * 2 */
temp = ady2 - adx2;
 
/* reverse step direction if delta x and delta y not in same direction */
xincr = 1;
if ((dx & 0x8000) != (dy & 0x8000)) xincr = -1;
 
if (ytemp1 <= ytemp2) {   /* Determine start point */
   x = xtemp1;
   y = ytemp1;
   xend = xtemp2;
   }
else {
   x = xtemp2;
   y = ytemp2;
   xend = xtemp1;
   }
 
d = ady2 - adx;              /* Compute initial error */

while (x != xend) {      /* loop until done with line */
   if (d < 0) {
      d += ady2;
      }
   else {
      d += temp;         /* temp = ady2 - adx2 */
      y++;               /* move up to next raster line */
      }

   x += xincr;                          /* move over one pixel */

   /* test for intersection */
   if (qchang == YES) {     /* x & y switched */
      ytest = x;
      *xint = y;
      }
   else {                   /* x & y not switched */
      *xint = x;
      ytest = y;
      }
   if (ytest == yscan) {    /* report intersection pt */
      *qint = YES;
      return;
      }
   } 
}
ddline (x1, y1, x2, y2, lcolor)
/*########################################################################*/
/*#                                                                      #*/
/*#          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER        #*/
/*#          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,           #*/
/*#          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE          #*/
/*#          WITH THE TERMS OF THAT AGREEMENT.                           #*/
/*#                                                                      #*/
/*#          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.            #*/
/*#          ALL RIGHTS RESERVED.                                        #*/
/*#                                                                      #*/
/*#     Function: Line drawing routine                                   #*/
/*#                                                                      #*/
/*#     Input Parameters:                                                #*/
/*#            x1,y1 - first point of line                               #*/
/*#            x2,y2 - second point of line                              #*/
/*#            lcolor - color for line                                   #*/
/*#     Output Parameters:                                               #*/
/*#            none                                                      #*/
/*#                                                                      #*/
/*#     Routines Called:                                                 #*/
/*#            bitblt - turn on a pixel in the bit map                   #*/
/*#                                                                      #*/
/*########################################################################*/
INT16 x1, y1, x2, y2, lcolor;
{

/* dash pattern definitions */
static INT16 pattern[] ={0xffff,         /* solid        ---------------- */
			 0xf00f,         /* long dash    ----        ---- */
			 0x8888,         /* dots         -   -   -   -    */
                         0xe10f,         /* dash dot     ---    -    ---- */
			 0xc3c3,         /* medium dash  --    ----    -- */
			 0xe247,         /* two dots     ---   -  -   --- */
			 0x9999,         /* short dash   -  --  --  --  - */
			 };

INT16 x, y, dx, dy, d, adx, ady, adx2, ady2, i, itemp, dshpat;
INT16 xtemp1, xtemp2, ytemp1, ytemp2, xend, temp, xincr;
INT16 numpnt; 
INT16 qchang;

xtemp1 = x1;
xtemp2 = x2;
ytemp1 = y1;
ytemp2 = y2;
 
dx = xtemp2 - xtemp1;
dy = ytemp2 - ytemp1;
adx = (dx >= 0) ? dx : -dx;   /* adx = abs (dx) */
ady = (dy >= 0) ? dy : -dy;   /* ady = abs (dy) */
qchang = NO;
 
if (ady > adx) {     /* switch x and y if slope > 1 */
   temp = xtemp1;
   xtemp1 = ytemp1;
   ytemp1 = temp;
   temp = xtemp2;
   xtemp2 = ytemp2;
   ytemp2 = temp;
   temp = adx;
   adx = ady;
   ady = temp;
   qchang = YES;
   }
 
adx2 = adx << 1;     /* adx2 = adx * 2 */
ady2 = ady << 1;     /* ady2 = ady * 2 */
temp = ady2 - adx2;
 
/* reverse step direction if delta x and delta y not in same direction */
xincr = 1;
if ((dx & 0x8000) != (dy & 0x8000)) xincr = -1;
 
if (ytemp1 <= ytemp2) {   /* Determine start point */
   x = xtemp1;
   y = ytemp1;
   xend = xtemp2;
   }
else {
   x = xtemp2;
   y = ytemp2;
   xend = xtemp1;
   }
 
d = ady2 - adx;              /* Compute initial error */

dshpat = pattern[ndlntp-1];  /* Set up current dash pattern */
itemp = dshpat << 1;         /* First pixel always on, so set up for second */
numpnt = 2;

if (qchang == YES) bitblt (y, x, lcolor, ndwrmd); /* turn on first pixel */
else               bitblt (x, y, lcolor, ndwrmd);
 
while (x != xend) {      /* loop until done with line */
   if (d < 0) {
      d += ady2;
      }
   else {
      d += temp;         /* temp = ady2 - adx2 */
      y++;               /* move up to next raster line */
      }

   x += xincr;                          /* move over one pixel */

   /* if pixel in pattern in on, then turn it on in the current line color */
   i = 0;
   if ((itemp & 0x8000) != 0) i = lcolor;

   if (qchang == YES) bitblt (y, x, i, ndwrmd);
   else               bitblt (x, y, i, ndwrmd);

   if (numpnt < 16) {                   /* get next bit of pattern */
      numpnt++;
      itemp <<= 1;
      }
   else {                               /* start pattern over */
      numpnt = 1;
      itemp = dshpat;
      }
   } 
}

ddtext (x, y, length, size, rotat)
/*########################################################################*/
/*#                                                                      #*/
/*#          THIS MATERIAL IS CONFIDENTIAL AND IS FURNISHED UNDER        #*/
/*#          A WRITTEN LICENSE AGREEMENT.  IT MAY NOT BE USED,           #*/
/*#          COPIED OR DISCLOSED TO OTHERS EXCEPT IN ACCORDANCE          #*/
/*#          WITH THE TERMS OF THAT AGREEMENT.                           #*/
/*#                                                                      #*/
/*#          COPYRIGHT (C) 1982 GRAPHIC SOFTWARE SYSTEMS INC.            #*/
/*#          ALL RIGHTS RESERVED.                                        #*/
/*#                                                                      #*/
/*#     Function: Text output routine                                    #*/
/*#                                                                      #*/
/*#     Input Parameters:                                                #*/
/*#            x,y - starting point for text string                      #*/
/*#            length - length of text string                            #*/
/*#            size - scale factor for character size (1-6)              #*/
/*#            rotat - text rotation                                     #*/
/*#                    0 = no rotation  1 = 90 degrees                   #*/
/*#                    2 = 180 degrees  3 = 270 degrees                  #*/
/*#     Output Parameters:                                               #*/
/*#            none                                                      #*/
/*#                                                                      #*/
/*#     Routines Called:                                                 #*/
/*#            bitblt - turn on bit on TI Pegasus                        #*/
/*#            getini - get element from intin array                     #*/
/*#                                                                      #*/
/*########################################################################*/

INT16 x, y, length, size, rotat;
{

#define ROWS 8     /* rows in a character cell */
#define COLUMNS 6  /* columns in a character cell */
 
/* column (x) increment for 90 degree rotations */
static INT16 coltbl[4] = {1, 1, -1, -1};

/* row (y) increment for 90 degree rotations */
static INT16 rowtbl[4] =  {1, -1, -1, 1};

/* row (y) offsets for 1 pixel descenders */
static INT16 descnd[4] =  {-1, 1, 1, -1};

static INT16 width = COLUMNS;          /* character cell width */
 
static BYTE fntary[768] = {
      0,  0,  0,  0,  0,  0,  0,  0,    /*sp */
      0,  4,  0,  0,  4,  4,  4,  4,    /* ! */
      0,  0,  0,  0,  0,  5, 10, 10,    /* " */
      0, 10, 10, 31, 10, 31, 10, 10,    /* # */
      0,  4, 14, 20, 14,  5, 14,  4,    /* $ */
      0, 25, 25,  2,  4,  8, 19, 19,    /* % */
      0, 22,  9, 21, 18,  5,  5,  2,    /* & */
      0,  0,  0,  0,  0,  2,  4,  6,    /* ' */
      0,  8,  4,  2,  2,  2,  4,  8,    /* ( */
      0,  2,  4,  8,  8,  8,  4,  2,    /* ) */
      0,  0, 18, 12, 30, 12, 18,  0,    /* * */
      0,  0,  4,  4, 31,  4,  4,  0,    /* + */
      2,  4,  6,  6,  0,  0,  0,  0,    /* , */
      0,  0,  0,  0, 31,  0,  0,  0,    /* - */
      0,  6,  6,  0,  0,  0,  0,  0,    /* . */
      0,  0,  1,  2,  4,  8, 16,  0,    /* / */
      0, 14, 17, 19, 21, 25, 17, 14,    /* 0 */
      0, 14,  4,  4,  4,  4,  6,  4,    /* 1 */
      0, 31,  2,  4,  8, 16, 17, 14,    /* 2 */
      0, 14, 17, 16,  8,  4,  8, 31,    /* 3 */
      0,  8,  8, 31,  9, 10, 12,  8,    /* 4 */
      0, 14, 17, 16, 16, 15,  1, 31,    /* 5 */
      0, 14, 17, 17, 14,  2,  4,  8,    /* 6 */
      0,  2,  2,  4,  8, 16, 16, 31,    /* 7 */
      0, 14, 17, 17, 14, 17, 17, 14,    /* 8 */
      0,  2,  4,  8, 14, 17, 17, 14,    /* 9 */
      0,  6,  6,  0,  0,  6,  6,  0,    /* : */
      2,  4,  6,  6,  0,  6,  6,  0,    /* ; */
      0,  8,  4,  2,  1,  2,  4,  8,    /* < */
      0,  0,  0, 31,  0, 31,  0,  0,    /* = */
      0,  2,  4,  8, 16,  8,  4,  2,    /* > */
      0,  4,  0,  4,  8, 16, 17, 14,    /* ? */
      0, 30, 1,  29, 21, 29, 17, 14,    /* @ */
      0, 17, 17, 31, 17, 17, 10,  4,    /* A */
      0, 15, 18, 18, 14, 18, 18, 15,    /* B */
      0, 14, 17,  1,  1,  1, 17, 14,    /* C */
      0, 15, 18, 18, 18, 18, 18, 15,    /* D */
      0, 31,  1,  1, 15,  1,  1, 31,    /* E */
      0,  1,  1,  1, 15,  1,  1, 31,    /* F */
      0, 14, 17, 17, 29,  1, 17, 14,    /* G */
      0, 17, 17, 17, 31, 17, 17, 17,    /* H */
      0, 14,  4,  4,  4,  4,  4, 14,    /* I */
      0,  6,  9,  9,  8,  8,  8, 28,    /* J */
      0, 17,  9,  5,  3,  5,  9, 17,    /* K */
      0, 31,  1,  1,  1,  1,  1,  1,    /* L */
      0, 17, 17, 17, 21, 21, 27, 17,    /* M */
      0, 17, 17, 25, 21, 19, 17, 17,    /* N */
      0, 14, 17, 17, 17, 17, 17, 14,    /* O */
      0,  1,  1,  1, 15, 17, 17, 15,    /* P */
      0, 22,  9, 21, 17, 17, 17, 14,    /* Q */
      0, 17, 17,  9, 15, 17, 17, 15,    /* R */
      0, 14, 17, 16, 14,  1, 17, 14,    /* S */
      0,  4,  4,  4,  4,  4,  4, 31,    /* T */
      0, 14, 17, 17, 17, 17, 17, 17,    /* U */
      0,  4, 10, 10, 17, 17, 17, 17,    /* V */
      0, 17, 27, 21, 21, 17, 17, 17,    /* W */
      0, 17, 17, 10,  4, 10, 17, 17,    /* X */
      0,  4,  4,  4,  4, 10, 17, 17,    /* Y */
      0, 31,  1,  2,  4,  8, 16, 31,    /* Z */
      0, 14,  2,  2,  2,  2,  2, 14,    /* [ */
      0,  0, 16,  8,  4,  2,  1,  0,    /* \ */
      0, 14,  8,  8,  8,  8,  8, 14,    /* ] */
      0,  0,  0,  0,  0, 17, 10,  4,    /* ^ */
     31,  0,  0,  0,  0,  0,  0,  0,    /* _ */
      0,  0,  0,  0,  0,  8,  4, 12,    /* ` */
      0, 22,  9, 14,  8,  7,  0,  0,    /* a */
      0,  7,  9,  9,  9,  7,  1,  1,    /* b */
      0, 14,  1,  1,  1, 14,  0,  0,    /* c */
      0, 28, 18, 18, 18, 28, 16, 16,    /* d */
      0, 14,  1, 31, 17, 14,  0,  0,    /* e */
      0,  4,  4,  4, 31,  4, 20, 12,    /* f */
      7,  8, 14,  9,  9, 14,  0,  0,    /* g */
      0,  9,  9,  9,  9,  7,  1,  1,    /* h */
      0, 14,  4,  4,  4,  6,  0,  4,    /* i */
      4,  10, 8,  8,  8, 12,  0,  8,    /* j */
      0,  9,  5,  3,  5,  9,  1,  1,    /* k */
      0, 14,  4,  4,  4,  4,  4,  6,    /* l */
      0, 21, 21, 21, 21, 15,  0,  0,    /* m */
      0, 17, 17, 17, 17, 15,  0,  0,    /* n */
      0, 14, 17, 17, 17, 14,  0,  0,    /* o */
      1,  1,  7,  9,  9,  7,  0,  0,    /* p */
     24,  8, 14,  9,  9, 14,  0,  0,    /* q */
      0,  1,  1,  1, 11,  5,  0,  0,    /* r */
      0, 15, 16, 14,  1, 14,  0,  0,    /* s */
      0, 12,  2,  2,  2, 15,  2,  2,    /* t */
      0, 22,  9,  9,  9,  9,  0,  0,    /* u */
      0,  4, 10, 10, 17, 17,  0,  0,    /* v */
      0, 10, 21, 21, 17, 17,  0,  0,    /* w */
      0, 17, 10,  4, 10, 17,  0,  0,    /* x */
     14, 16, 30, 17, 17, 17,  0,  0,    /* y */
      0, 15,  1,  2,  4, 15,  0,  0,    /* z */
      0, 24,  4,  4,  2,  4,  4, 24,    /* { */
      0,  4,  4,  4,  0,  4,  4,  4,    /* | */
      0,  3,  4,  4,  8,  4,  4,  3,    /* } */
      0,  0,  0,  0,  0,  8, 21,  2,    /* ~ */
      0, 31, 31, 31, 31, 31, 31, 31};   /* rubout */

INT16 rowinc, colinc, colrpt, rowrpt;
INT16 qchang;
INT16 i, j, k, m, itemp;
INT16 xcoord, ycoord, xtemp, ytemp, gimnmx(), mult(), tmpwid;
INT16 getini ();
INT16 xparm, yparm, txtptr;
BYTE *iptr;

xtemp = x;                                 /* save start point */
ytemp = y;

/* exchange x and y on 90 and 270 degree rotation */
qchang = NO;
if ((rotat & 0x0001) != 0) {               /* rotate = 1 or 3 */
   qchang = YES;
   xtemp = y;
   ytemp = x;
   }

colinc = coltbl [rotat];                   /* determine row & column */
rowinc = rowtbl [rotat];                   /*   increments */
tmpwid = mult (width , size);              /* set intercharacter spacing */
if (rotat >= 2) tmpwid = -tmpwid;          /* negate spacing for 180 & 270  */
					   /*   degree rotations */
 
/* modify starting position to account for 1 pixel descender */
if (descnd[rotat] > 0) ytemp += size;
else                   ytemp -= size;

txtptr = 0;                                /* point to start of string */
for (k=1; k<=length; k++) {

   /* The assembler function getini must be used to extract the ade chars  */
   /* from the intin array of the driver since Computer Innovations C      */
   /* can't pass 32 bit pointers (which are passed to the driver).         */

   i = gimnmx(getini (txtptr), 32, 127)-32;/* make sure character in range */
   iptr = &fntary[i << 3];                 /* get pointer to start of pixels */
   xcoord = xtemp;                         /* set initial position */
   ycoord = ytemp;
   for (i=1; i<=ROWS; i++) {
      for (rowrpt=1; rowrpt<=size; rowrpt++) {
 
         itemp = *iptr;                    /* get current row */
 
	 for (j=1; j<=COLUMNS; j++) {      /* loop over cols in current row */
 
	    m = itemp & 0x0001;            /* m = current bit of char def */
					   /*    0 - off, 1 - on */
	    if (m != 0) m = ndclrt;        /* if bit is on, it should be  */
					   /*   current text color        */
	    itemp >>=  1;
 
	    for (colrpt=1; colrpt<=size; colrpt++) {
	       if (qchang == YES) {    /* switch x & y back for bit setting */
		  xparm = ycoord;
		  yparm = xcoord;
		  }
               else {
		  xparm = xcoord;
		  yparm = ycoord;
		  }

	       if (xparm >= 0 && yparm >= 0 && xparm <= X_LIMITS_DEVICE && 
		   yparm <= Y_LIMITS_DEVICE) {

		  bitblt (xparm, yparm, m, ndwrmd);   /* set pixel */
		  }
 
               /* update x,y for next pixel in row */
               xcoord += colinc;
               }
            }
 
         /* update x,y for next row */
         xcoord = xtemp;
         ycoord += rowinc;
         }
      
      iptr++;                /* update ptr to row of character definition */
      }
 
   /* update position for next character */
   xtemp += tmpwid;
   txtptr++;                 /* point to next character in string */
   }
 
return;
}

E 1
