	
#include "ratdef.h";
#define MAXxHPxBUFFER  80
#define MOVE  1
#define DRAW  2
#define YES  1
#define NO  0
#define UNSUCCESSFUL  0
				/* Unsuccessful GIN operation    */
#define SUCCESSFUL  1
				/* Unsuccessful GIN operation    */
#define DEFAULT  1
				/* Default GIN device number     */
#define PLOTTER  6
				/* Plotter device number for GIN */
int max0(), min0();
unsigned int wxmin, wymin, wxmax, wymax;
int x_fetch(), y_fetch();

DD747X (paraseg,paraoff)
int paraoff,paraseg;
 
{
/************************************************************************
*                                                                      *
*     Function: Device Driver for Hewlett Packard 747x pen plotter     *
*                                                                      *
*     Input Parameters:                                                *
*            paraseg - parameter segment                               *
*            paraoff - parameter offset                                *
*                                                                      *
*     Output Parameters:                                               *
*            none                                                      *
*								       *
*     Routines Called:                                                 *
*             Dbufhp - buffered output for HP plotter                  *
*             Gznfpl - prompt the user for a new sheet of paper        *
*             Dr747x - move/draw for HP plotter                        *
*             Dp747x - Change pens on the HP 747x plotter              *
*             Dt747x - Set text size on HP 747x plotter                *
*             Gitoch  - convert integer to characters                  *
*             Gchtoi  - convert character string to integer            *
*             Gimnmx - Function to place integer value in a range      *
*                                                                      *
************************************************************************/
 
#include "ddcom.h"
int     opcode;
int     i, i2, j, gimnmx(), ierror, ival, istop,
	tries,
	ginok, icnvt[6], ibuf[50];
unsigned int xy[2], savexy[2];
int     temp, gitoch(), length;
unsigned int x1, y1, x2, y2;
unsigned int hlfsiz, fulsiz;
 
extern int     pens[6], clrred[6], clrgrn[6], clrblu[6];

/*           Start arc definition /PD;AA/  */
static int arcstart[] = {BIGP, BIGD, SEMICOL, BIGA, BIGA};

/*           End arc definition /,5;/   */
static int arcend[] = {COMMA, DIG7, SEMICOL};

/*           Set up for solid fill /FT1;PT;/  */
static int solfill[] = {BIGF,BIGT,DIG1,SEMICOL,BIGP,BIGT,SEMICOL};

/*           Set up for hatching /FT3,90,   ;/  */
static int hatfill[] = {BIGF,BIGT,DIG3,COMMA,DIG9,DIG0,COMMA,0,0,0,SEMICOL};

/*           Wedge command /WG/  */
static int wedge[] = {BIGW,BIGG};
 
/*           Eedge wedge command /EW/  */
static int edgewedge[] = {BIGE,BIGW};
 
/*           Set label(text) font  /CS<font>SS;;/  */
static int setfnt[8] = {BIGC, BIGS, DIG0, DIG0, SEMICOL, BIGS, BIGS, SEMICOL};
 
/*           Set rotation /DI/    */
static int rotate[2] ={BIGD, BIGI};

/*           Text output set up /LB/  */
static int txtout[2] = {BIGL, BIGB};
 
/*           Marker size, output /SM<0>;/  */
static int mrkout[4] = {BIGS, BIGM, DIG0, SEMICOL};
 
/*           Set line style to solid /LT;/ */
static int solid[3] ={BIGL, BIGT, SEMICOL};

/*           Line style /LT<0>,2;/ */
static int lstyle[6] ={BIGL, BIGT, DIG0, COMMA, DIG2, SEMICOL};

/*           Set up -
 		Turn plotter on  <ESC>.(
 		Set handshake mode 2        <ESC>.I81;5;6:
                Initialize the plotter:      DF;
								*/
static int setup[] = {BIGI,BIGN,SEMICOL,ESC, PERIOD, LPAREN, ESC, PERIOD, BIGR,
             ESC,PERIOD,BIGI,DIG8,DIG1,SEMICOL,DIG5,SEMICOL,DIG6,COLON,ENQ };
 
static int setup2[] = {BIGD,BIGF,SEMICOL,BIGD,BIGI,DIG0,COMMA,MINUS,DIG1,SEMICOL,
             ESC,PERIOD,ATSIGN,SEMICOL,DIG0,DIG0,COLON,ESC,PERIOD,BIGM,DIG1,
             DIG0,COLON,ESC,PERIOD,BIGN,DIG1,DIG0,COLON };

/*           Stop graphics - /<ESC>.)/   */
static int stopgr[3] = {ESC, PERIOD, RPAREN};
 
static int mrktbl[5] = {PERIOD, PLUS, STAR, BIGO, BIGX};
 
static int gogin[4] = {BIGD, BIGP, SEMICOL, NEWLINE};
 
static int inqsta[4] = {BIGO, BIGS, SEMICOL, NEWLINE};
 
static int getgin[4] = {BIGO, BIGD, SEMICOL, NEWLINE};
 
static int comma = COMMA;
 
static int endtxt = ETX;
 
static int semcol = SEMICOL;

static int home[2] = {0, 0};
 
static int iniino[45] = {	/* initial intout array for open workstation*/
   0,0,
   METERS,         /* Device coordinates are meters     */
   25,             /* Step size in micrometers on x axis       */
   25,             /* Step size in micrometers on y axis       */
   0,              /* Number of character heights (continuous) */
   7,              /* Number of line types                     */
   1,              /* Number of line widths                    */
   5,              /* Number of marker types                   */
   0,              /* Number of marker sizes (continuous)      */
   5,              /* Number of text fonts                     */
   0,              /* Number of patterns                       */
   6,              /* Number of hatch styles                   */
   6,              /* Number of predefined colors              */
   1,              /* Number of GDPs                           */
   1,-1,-1,-1,-1,  /* GDPs, except BARS,  do not exist         */
   -1,-1,-1,-1,-1,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,
   1,              /* Device is capable of color               */
   1,              /* Device is capable of text rotation       */
   1,              /* Device is capable of filled area         */
   0,              /* Device is not capable of pixel operations*/
   0,              /* Number of colors available (continuous   */
			       /* pen colors)                  */
   1,              /* Number of locator devices available      */
   0,              /* Number of valuator devices available     */
   0,              /* Number of choice devices available       */
   0,              /* Number of string devices available       */
   2};             /* Workstation type (input/output)          */

static int inipto[12] = {	   /* initial ptsout array for open workstation */
   0,
   60,             /* Minimum character height in DC space      */
			       /* .15cm = 60 steps              */
   0,
   0,
   1,              /* Minimum line width in DC space            */
   0,
   1,              /* Maximum line width in DC space            */
   0,
   0,
   80,             /* Minimum marker height in DC space         */
			       /* .20cm = 80 steps              */
   0,
   0};

static getwindw[] = {BIGO, BIGP, SEMICOL};  /* Get window command OW; */
static getid[] = {BIGO, BIGI, SEMICOL}; /* Get plotter ID (7470 or 7475) */

extern int conoff, iinoff, pinoff, ioutoff, poutoff, LFETCH();
extern int conseg, iinseg, pinseg, ioutseg, poutseg;

conoff=LFETCH(paraseg,paraoff,0); conseg=LFETCH(paraseg,paraoff,1);
iinoff=LFETCH(paraseg,paraoff,2); iinseg=LFETCH(paraseg,paraoff,3);
pinoff=LFETCH(paraseg,paraoff,4); pinseg=LFETCH(paraseg,paraoff,5);
ioutoff=LFETCH(paraseg,paraoff,6); ioutseg=LFETCH(paraseg,paraoff,7);
poutoff=LFETCH(paraseg,paraoff,8); poutseg=LFETCH(paraseg,paraoff,9);
 
opcode=LFETCH(conseg,conoff,OPCODE);
LSTORE(conseg,conoff,2,0);                 /*Assume no vertices are being passed back*/

/* opcode open workstation */

switch (opcode) {

 case OPENxWORKSTATION:
   LSTORE(conseg,conoff,2,6);             /* Set to number of output vertices */
   LSTORE(conseg,conoff,4,45);            /* Length of array intout           */

   /* set up output capability array */
   for (i=0;i<45;++i) LSTORE(ioutseg,ioutoff,i,iniino[i]);

   for (i=0;i<12;++i) LSTORE(poutseg,poutoff,i,inipto[i]);

   ndlntp = max0 (LFETCH(iinseg,iinoff,1)-1, 0);   /*Set current device line style*/
   if (ndlntp > 6) ndlntp = 0; ndlntp = ndlntp + DIG0;
   ndclrl = max0 (LFETCH(iinseg,iinoff,2), 0);          /*Set current polyline color index*/
   ndmktp = LFETCH(iinseg,iinoff,3);                    /*Set current marker type*/
   if (ndmktp < 1 | ndmktp > 5) ndmktp=3;
   ndclrm = max0 (LFETCH(iinseg,iinoff,4), 0);          /*Set current polymarker color index*/
                                                        /*Set current text font*/
   ndclrt = max0 (LFETCH(iinseg,iinoff,6), 0);          /*Set current text color index*/
   ndclrf = max0 (LFETCH(iinseg,iinoff,9),0);           /*Set current fill area color index*/
   ndstyf = max0 (LFETCH(iinseg,iinoff,8),1);           /*Set current fill style index*/
   if (ndstyf > 6)ndstyf = 1;
   ndistyf = max0 (LFETCH(iinseg,iinoff,7),0);          /*Set current fill interior style*/
   if (ndistyf > 3)ndistyf = 0;
   ndmkht = 20;                          /*Set default marker height .2cm*/
   ndtxsz = 15;                          /*Set default character width .15 cm*/
   ndtysz = 15;                          /*Set default character height .15cm*/
   ndtxrt = 0;                           /*Set default rotation to 0 degrees*/

   ndclrp = -1;                          /*Set current device color */
 
   /*initialize plotter */

   ndotkt = 0;               /*Initialize the plotter ouput counter. This  */
                             /*   counter is used by the routine 'dbufhp'  */
   outstr (20, setup);       /*Must use outstr because block mode is set   */
                             /*in initialization sequence.                 */
   RDRIN(&i);
   dbufhp (29, setup2);
   if (ndlntp == DIG0)       /*Set line type to initial value              */
      dbufhp (3, solid);     /*Solid                                       */
   else {                    /*Dashed                                      */
      lstyle[2] = ndlntp;
      dbufhp (6, lstyle);
      }

   dt747x (ndtxsz, ndtysz);  /*Set initial text size */

   dbufhp (-1,setup);
   dbufhp (3, getwindw);	/*Get the current window size*/
   instr (50,ibuf,&i);
   for (i=0;(i<50)&&((ibuf[i]<DIG0 || ibuf[i]>DIG9));++i);
   gchtoi (ibuf,i,&wxmin,&i); 
   gchtoi (ibuf,i+1,&wymin,&i); 
   gchtoi (ibuf,i+1,&wxmax,&i); 
   gchtoi (ibuf,i+1,&wymax,&i);
   LSTORE (ioutseg,ioutoff,1,wxmax-wxmin);
   LSTORE (ioutseg,ioutoff,0,wymax-wymin);
   inipto[3] = inipto[11] = (wxmax-wxmin)/2;
   LSTORE (poutseg,poutoff,3,inipto[3]);
   LSTORE (poutseg,poutoff,11,inipto[3]);
   
   dbufhp (3, getid);       /* Get the plotter id */
   instr (30,ibuf,&i);
   gchtoi (ibuf,0,&temp,&i);
   nmbrpens = (temp==7475) ? 6 : 2;
   nmbrfonts = (temp==7475) ? 19 : 5;
   i = gimnmx (LFETCH(iinseg,iinoff,5), 1, nmbrfonts) - 1;
   if (i>4) i=i+1;
   if (i>9) i=i+20;
   setfnt[2] = i/10 + DIG0;
   setfnt[3] = (i%10) + DIG0;
   dbufhp (8, setfnt);           /*Output command        */

   LSTORE (ioutseg,ioutoff,13,nmbrpens);
   LSTORE (ioutseg,ioutoff,10,nmbrfonts);

   for (i=0; i<nmbrpens; ++i) pens[i] = i; /*Station 1 holds index 1 */
 
   clrred[0] = 0;                        /*Define color index 0 to black */
   clrgrn[0] = 0;
   clrblu[0] = 0;
   for (i=1;i<nmbrpens;++i) {
      clrred[i] = 1;                        /*Define color index 1 to white */
      clrgrn[i] = 1;
      clrblu[i] = 1;
      }

   if (nmbrpens==6) {                /*Declare GDP's for 7475 */
      LSTORE(ioutseg,ioutoff,14,4);
      for (i=1;i<5;++i) {
         LSTORE(ioutseg,ioutoff,i+14,i);
         LSTORE(ioutseg,ioutoff,i+24,3);
     }
     LSTORE(ioutseg,ioutoff,26,0);
   }

   break;


/* opcode close workstation  */

  case CLOSExWORKSTATION:
   dr747x (MOVE, home);
   break;


/* opcode clear workstation  */

  case CLEARxWORKSTATION:
   dr747x (MOVE, home);  /*Home the plotter  */
   dbufhp (-1, semcol);  /*Dump buffer       */
   gznfpl();             /*prompt user for new paper (new frame on plotter) */
   ndclrp = -1;          /*Force plotter to pick up pen again */
   break;
 

/* opcode update workstation  */

  case UPDATExWORKSTATION:
   dbufhp (-1, semcol);
   break;


/* opcode escape  */

  case ESCAPE:
   if (LFETCH(conseg,conoff,5) == INQxADDRESSABLExCELLS) {
     LSTORE(ioutseg,ioutoff,0,-1);
     LSTORE(ioutseg,ioutoff,1,-1);
     }
   break;


/* opcode polyline  */

  case POLYLINE:
   dp747x (ndclrl);                         /*Change color to line color  */
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (MOVE, xy);                 /*Move to first point         */
   j = 2;
   for (i=2; i<=LFETCH(conseg,conoff,1); ++i) {/*Draw between subsequent pts */
      xy[0]=x_fetch(j);
      xy[1]=y_fetch(j);
      dr747x (DRAW, xy);
      j += 2;
      }
   j -= 2;
   xy[0]=x_fetch(j);
   xy[1]=y_fetch(j);
   dr747x (MOVE, xy);   /*Move to pick up the pen */
   break;
 

/* opcode polymarker  */

  case POLYMARKER:
   dp747x (ndclrm);                /*Change color if necessary    */
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (MOVE, xy);        /*Move to center point         */
 
   dt747x (ndmkht, ndmkht);        /*set marker size              */
   mrkout[2] = mrktbl[ndmktp-1];   /*Get proper marker from table */
   dbufhp (4, mrkout);             /*Enter marker mode            */

   /* Set sizes used for marker clipping */
   fulsiz = ndmkht * 4;          /*4 steps per .01 cm  */
   hlfsiz = ndmkht * 2;

   j = 0;
   for (i=1; i<=LFETCH(conseg,conoff,1); ++i) {/*Output marker at each point  */

      xy[0] = x_fetch(j);
      xy[1] = y_fetch(j);

      /*Clip marker to device limits                                          */
      /*Marker height is stored in .01 cm units. Since there are 4 plotter    */
      /*steps per .01 cm, multiply by 4 to get plotter coords                 */

      x1 = xy[0] - hlfsiz;
      x2 = x1 + fulsiz;
      y1 = xy[1] - hlfsiz;
      y2 = y1 + fulsiz;
      if ((min0(x1,y1) >= 0) && (x2 <= wxmax) && /* watch out for portrait mode changes*/
	 (y2 <= wymax))             /*Marker fits on device */
           dr747x (MOVE, xy); /*Move to center point and display */
      j += 2;                              /*Increment ptr to coords  */
      }
 
   mrkout[2] = SEMICOL;
   dbufhp (3,mrkout);              /*Exit marker mode  */

   /*restore the user's text size */
   dt747x (ndtxsz, ndtysz);
   break;
 

/* opcode text  */

  case TEXT:
   dp747x (ndclrt);           /*Change color to text color  */
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (MOVE, xy);   /*Move to start point   */

   j = LFETCH(conseg,conoff,INTEGERxINxLENGTH);/*Get the string length  */
   dbufhp (-1, &endtxt);       /*Force the buffer to be cleared */
   dbufhp (2, txtout);        /*Text command  */
   for (i = 0; i < j; ++i) {  /*Loop to keep buffer from overflowing*/
       xy[0]=LFETCH(iinseg,iinoff,i);
       dbufhp (1, xy);
       }
   dbufhp (1, &endtxt);        /*terminate string  */
   break;
 

/* opcode fill area */

  case FILLxAREA:
   dp747x (ndclrf);                      /*Change color to fill color  */
   gsxfill (ndistyf, ndstyf, ndlntp, LFETCH(conseg,conoff,1));
   break;


/* opcode cell array */

  case CELLxARRAY:
   savexy[0] = x_fetch(0);                          /*Save boundary points  */
   savexy[1] = y_fetch(0);
   x2 = x_fetch(2);
   y2 = y_fetch(2);

   dp747x (ndclrl);                      /*Change color to line color */
   dr747x (MOVE, savexy);                /*Move to first point   */

   dbufhp (3, solid);                    /*Set solid line type   */

   xy[0] = x2;                          /*Draw boundary around area */
   xy[1] = savexy[1];
   dr747x (DRAW, xy);
   xy[1] = y2;
   dr747x (DRAW, xy);
   xy[0] = savexy[0];
   dr747x (DRAW, xy);
   dr747x (DRAW, savexy);

   if (ndlntp != DIG0) {             /*restore line type if not solid */
      lstyle[2] = ndlntp;
      dbufhp (6, lstyle);
      }
   break;


/* opcode GDP's */

  case GENERALIZEDxDRAWINGxPRIMITIVE:
   i=LFETCH(conseg,conoff,5);

   if(i==1) {         /* BARS - supported by both plotters */
      dp747x (ndclrf);                      /*Change color to fill color  */
      for (j=2; j<8; ++j) ibuf[j-2] = LFETCH(pinseg,pinoff,j);
      x1 = LFETCH(pinseg,pinoff,0); y1 = LFETCH(pinseg,pinoff,1);
      x2 = LFETCH(pinseg,pinoff,2); y2 = LFETCH(pinseg,pinoff,3);

      LSTORE(pinseg,pinoff,2,x2);  LSTORE(pinseg,pinoff,3,y1);
      LSTORE(pinseg,pinoff,4,x2);  LSTORE(pinseg,pinoff,5,y2);
      LSTORE(pinseg,pinoff,6,x1);  LSTORE(pinseg,pinoff,7,y2);

      gsxfill(ndistyf,ndstyf,ndlntp,4);

      for (j=2; j<8; ++j) LSTORE(pinseg,pinoff,j,ibuf[j-2]);
   }
   if (i>1 && nmbrpens==6) {
      switch (i) {
      case 2:              /*ARC */
        dp747x (ndclrl);                /*Change color to line color  */
        xy[0] = x_fetch(2);
        xy[1] = y_fetch(2);
        dr747x (MOVE, xy);             /*Move to first point of arc */
        dbufhp (5,arcstart);
        length = gitoch(x_fetch(0), icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (1, &comma);
        length = gitoch(y_fetch(0), icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (1, &comma);
        length = gitoch((LFETCH(iinseg,iinoff,1)-LFETCH(iinseg,iinoff,0))/10, icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (3, arcend);
        break;
      case 3:              /*Pie Slices */
      case 4:              /*Circles */
        dp747x (ndclrf);                /*Change color to line color  */
        xy[0] = x_fetch(0);
        xy[1] = y_fetch(0);
        dr747x (MOVE, xy);             /*Move to center of slice */
        if (ndistyf==1 || ndistyf==3) {
           for (j=0;j<2;++j) {
              if (ndistyf==1 ) dbufhp (7,solfill);
              else {
                 ival = ndstyf; if (ndstyf > 4) ival -= 3;
                 if (j==1) ival = (ndstyf==6) ? 4 : 1;
                 switch (ival) {
                    case 1: hatfill[7]=SP; hatfill[8]=DIG9; hatfill[9]=DIG0; break;
                    case 2: hatfill[7]=hatfill[8]=SP; hatfill[9]=DIG0; break;
                    case 3: hatfill[7]=SP; hatfill[8]=DIG4; hatfill[9]=DIG5; break;
                    case 4: hatfill[7]=DIG1; hatfill[8]=DIG3; hatfill[9]=DIG5; break;
                 }
                 dbufhp (11, hatfill);
              }   
              dbufhp (2, wedge);
              temp = (i==3) ? 6 : 4;
              length = gitoch(max0(2,LFETCH(pinseg,pinoff,temp)), icnvt, 6, &ierror);
              dbufhp (length,icnvt);
              dbufhp (1, &comma);
              temp = (i==3) ? (LFETCH(iinseg,iinoff,0)/10 + 270) : 0;
              length = gitoch(temp, icnvt, 6, &ierror);
              dbufhp (length,icnvt);
              dbufhp (1, &comma); 
              temp = (i==3) ? (LFETCH(iinseg,iinoff,1)/10 + 270 - temp) : 360;
              length = gitoch(temp, icnvt, 6, &ierror);
              dbufhp (length,icnvt);
              dbufhp (3, arcend);
              if (ndistyf==1 || ndstyf<5) break;
           }
        }
        dbufhp (2, edgewedge);   
        temp = (i==3) ? 6 : 4;
        length = gitoch(max0(2,LFETCH(pinseg,pinoff,temp)), icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (1, &comma);
        temp = (i==3) ? (LFETCH(iinseg,iinoff,0)/10 + 270) : 0;
        length = gitoch(temp, icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (1, &comma);
        temp = (i==3) ? (LFETCH(iinseg,iinoff,1)/10 + 270 - temp) : 360;
        length = gitoch(temp, icnvt, 6, &ierror);
        dbufhp (length,icnvt);
        dbufhp (3, arcend);
        break;
     }
   }
        
   break;


/* opcode set character height */

  case SxCHxHEIGHT:

 
   /*The input parameters represent the text height of a character             */
   /*cell excluding gap.  The 747x plotter command for text size only requires */
   /*the character width and height itself and does its own inter-line         */
   /*inter-character spacing.  The plotter sets the character cell width       */
   /*to 1.5 * character width and the character cell height to 2 * character   */
   /*height.

   /*To avoid using real numbers we store the height and width in              */
   /*.01 cm units with an implied decimal point two places to                  */
   /*the left (100 = 1 cm).  4 plotter steps = .01 cm                          */

   /*Make sure not too small >=.15cm and not too large                         */
   ndtysz = gimnmx (LFETCH(pinseg,pinoff,1), 60, inipto[3]);
   ndtxsz = (ndtysz * 6)/10;          /*Pick appropriate width w = .6 * h */
   ndtxsz = max0 (ndtxsz, 60);               /*Make sure not too small >=.15cm   */

   /*Convert text width in dcs to .01 centimeters  */
   /*  width = dc / (steps per .01 cm = 4)         */

   ndtxsz = ndtxsz/4;

   /*Convert text height dcs to .01 centimeters  */
   /*  height = dc / (steps per .01 cm = 4)      */

   ndtysz = ndtysz/4;
   
   dt747x (ndtxsz, ndtysz);             /*Set the text size */

   LSTORE(conseg,conoff,2,2);                       /*One output coordinate pair*/
   LSTORE(poutseg,poutoff,0,savexy[0] = ndtxsz * 4);
   LSTORE(poutseg,poutoff,1,savexy[1] = ndtysz * 4);

   /*cell width = 1.5 * char width  */
   /*cell height = 2 * char heght   */
   LSTORE(poutseg,poutoff,2,(savexy[0]*300)/200);
   LSTORE(poutseg,poutoff,3,savexy[1]*2);


   break;
 

/* opcode set character up vector */

  case SxCHxUPxVECTOR:
   ndtxrt = LFETCH(iinseg,iinoff,0);               /*Device can rotate continuously */
   dbufhp (2,rotate);
   length = gitoch (LFETCH(iinseg,iinoff,2), icnvt, 6, &ierror);
   dbufhp (length, icnvt);     /*Output run*/
   dbufhp (1, &comma);
   length = gitoch (-1*LFETCH(iinseg,iinoff,1), icnvt, 6, &ierror);
   dbufhp (length,icnvt);      /*Output rise (remember portrait mode) */
                               /*New run = old rise, New rise = -1 * old run */
   dbufhp (1,&semcol);          /*End that command*/
   LSTORE(ioutseg,ioutoff,0,ndtxrt);         /*Inform upper level of angle */
   break;


/* opcode set color  */

  case SxCOLORxREPRESENTATION:
   /*Save 2 or 6 color indices, 1 for each pen station.  The requested  */
   /*value is the same as the realized value                       */
   i = gimnmx (LFETCH(iinseg,iinoff,0)-1, 0, nmbrpens-1);           /*Get color index in range  */
   clrred[i] = LFETCH(iinseg,iinoff,1);
   clrgrn[i] = LFETCH(iinseg,iinoff,2);
   clrblu[i] = LFETCH(iinseg,iinoff,3);
   break;


/* opcode set line type */

  case SxPLxLINETYPE:
   ndlntp =  LFETCH(iinseg,iinoff,0);
   if (ndlntp < 1 | ndlntp > 7) ndlntp = 1;
   LSTORE(iinseg,iinoff,0,ndlntp);                     /*Return linetype selected */
   ndlntp = ndlntp - 1 + DIG0;             /*Map to device parameter  */
   if (ndlntp == DIG0)                     /*Line type solid          */
      dbufhp(3, solid);
   else {                                  /*Line type not solid      */
      lstyle[2] = ndlntp;
      dbufhp(6, lstyle);
      }
   break;
 

/* opcode polyline color index  */

  case SxPLxCOLORxINDEX:
   ndclrl = max0 ( 0, LFETCH(iinseg,iinoff,0));
   LSTORE(ioutseg,ioutoff,ndclrl);              /*Return color index selected */
   break;
 

/* opcode set marker type   */

  case SxPMxTYPE:
   ndmktp = LFETCH(iinseg,iinoff,0);
   if (ndmktp < 1 | ndmktp > 5) ndmktp = 3; /*Marker type 3 is default */
   LSTORE(ioutseg,ioutoff,ndmktp);                      /*Return type selected     */
   break;


/* opcode polymarker scale  */

  case SxPMxSCALE:
   ndmkht = gimnmx (LFETCH(pinseg,pinoff,1), 60, inipto[11]);/*Make sure size not too        */
						   /*small or too large       */
   LSTORE(conseg,conoff,2,1);                      /*Return 1 coordinate pair */
   LSTORE(poutseg,poutoff,0,0);
   LSTORE(poutseg,poutoff,1,ndmkht);             /*Return size selected     */

   /*convert height in dcs to .01 centimeters   */
   /* height = dc / (steps per .01 cm = 4)      */

   ndmkht = ndmkht/4;

   break;


/* opcode polymarker color index  */

  case SxPMxCOLORxINDEX:
   LSTORE(ioutseg,ioutoff,0,ndclrm = max0 ( 0, LFETCH(iinseg,iinoff,0)));
   break;
 

/* opcode set text font  */

  case SxTXxFONT:
   i = j = gimnmx (LFETCH(iinseg,iinoff,0), 1, nmbrfonts) - 1;
   if (i>4) i=i+1;
   if (i>9) i=i+20;
   setfnt[2] = i/10 + DIG0;
   setfnt[3] = (i%10) + DIG0;
   dbufhp (8, setfnt);           /*Output command        */
 
   LSTORE(ioutseg,ioutoff,0,j);                /*Return actual font selected  */
   break;
 

/* opcode text color index   */

  case SxTXxCOLORxINDEX:
   LSTORE(ioutseg,ioutoff,0,ndclrt = max0(0,LFETCH(iinseg,iinoff,0)));
   break;
 

/* opcode set fill color index  */

  case SxFxCOLORxINDEX:
   LSTORE(ioutseg,ioutoff,0,ndclrf = max0(0,LFETCH(iinseg,iinoff,0)));
   break;
 

/* opcode set fill interior sytle index  */

  case SxFxINTERIORxSTYLE:
   ndistyf = max0(LFETCH(iinseg,iinoff,0),0);
   if (ndistyf > 3) ndistyf = 0;
   LSTORE(ioutseg,ioutoff,0,ndistyf);
   break;

/* opcode set fill style index  */

  case SxFxSTYLExINDEX:
   ndstyf = max0(LFETCH(iinseg,iinoff,0),1);
   if (ndstyf > 6) ndstyf = 1;
   LSTORE(ioutseg,ioutoff,0,ndstyf);
   break;

/* opcode inquire color representation  */

  case INQxCOLORxREPRESENTATION:
   i = gimnmx (LFETCH(iinseg,iinoff,0)-1, 0, nmbrpens-1);     /*Map index 0-5 to 1-6 */
   LSTORE(ioutseg,ioutoff,0,i + 1);               /*Color index selected             */
   LSTORE(ioutseg,ioutoff,1,clrred[i]);           /*Set values are same as realized  */
   LSTORE(ioutseg,ioutoff,2,clrgrn[i]);
   LSTORE(ioutseg,ioutoff,3,clrblu[i]);
   break;


/* opcode input locator  */

  case INPxLOCATOR:
   LSTORE(poutseg,poutoff,0,0);
   LSTORE(poutseg,poutoff,1,0);
   LSTORE(conseg,conoff,4,UNSUCCESSFUL);
   i = LFETCH(iinseg,iinoff,0);                       /*check input device number  */
   if (i != DEFAULT && i != PLOTTER) return;
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (MOVE, xy);       /*move to initial point*/

   dbufhp (-1, gogin);  /*First flush the buffer  */
   outstr (4, gogin);                /*Arm to do a point input      */
   for (;;) {                          /*Go until the key was pressed */
      outstr (4, inqsta);            /*Ask for a status byte        */
      instr (40, ibuf,  &temp);       /*Get the answer               */
      for (j=0; (j<40) && (ibuf[j]==0);++j);
      gchtoi (ibuf, j, &ival, &istop);
      j = (ival>>2) % 2;
      if (j == 1) break;             /*the third bit was on         */
      }
   outstr (4, getgin);       /*Ask for the gin report       */
   instr (18, ibuf,  &temp); /*Get the gin report           */
 
   LSTORE(conseg,conoff,4,SUCCESSFUL);                      /*Request was successful   */
   LSTORE(conseg,conoff,2,1);                               /*Output 1 coordinate pair */
   gchtoi (ibuf, 0, &i, &istop);
   LSTORE(poutseg,poutoff,1,i-wxmin);
   gchtoi (ibuf, istop+1, &i, &istop);
   LSTORE(poutseg,poutoff,0,wymax-i);
   LSTORE(ioutseg,ioutoff,0,ibuf[istop+1] - DIG0 + SP);     /*Return SP or ! (pen up/down)*/
   break;
 

/* opcode set input mode */

  case SxINPUTxMODE:
   LSTORE(ioutseg,ioutoff,0,1);    /*Default mode is request */
   break;
  }
  dbufhp (-1, stopgr);     /*Dump buffer  */
  dbufhp (3, stopgr);      /*Terminate graphics */

}


dr747x (opcode, xy)
int opcode, xy[];
{
/***********************************************************************
*                                                                      *
*     Function: Device Driver move/draw for HP747x                     *
*                                                                      *
*     Input Parameters:                                                *
*           opcode - driver function, either move/draw                 *
*           xy     - coordinates to move or draw to                    *
*                    xy [0] = x-coordinate                             *
*                    xy [1] = y-coordinate                             *
*                                                                      *
*     Output Parameters: none                                          *
*                                                                      *
*     Routines Called:                                                 *
*            dbufhp - output a string to the HP747x plotter            *
*            gitoch - convert integer to character string              *
*                                                                      *
************************************************************************/
 
int length, iconvt[10], ierror, gitoch();
 
static int movdrw[5] = {BIGP, BIGU, SEMICOL, BIGP, BIGA};
static int semcol[1] = {SEMICOL};
static int comma[1] = {COMMA};
 
   movdrw[1] = BIGU;                       /*Always prepare to do a move */
   if (opcode == DRAW) movdrw[1] = BIGD;   /*Change it for a draw        */
   dbufhp (5, movdrw);
   length = gitoch (xy[0],iconvt,5,&ierror);
   dbufhp (length,iconvt);
   dbufhp (1,comma);
   length = gitoch (xy[1],iconvt,5,&ierror);
   dbufhp (length,iconvt);
   dbufhp (1,semcol);
}

dt747x (wid, hgt)
unsigned int wid,hgt;
{
/***********************************************************************
*                                                                      *
*     Function: Set text size on HP 747x plotter                       *
*                                                                      *
*     Input Parameters:                                                *
*            wid   - width of character in .01 cm units (1cm =100units)*
*            hgt   - height of character in .01 cm units (1cm=100units)*
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            gitoch  - convert integer to character string             *
*            dbufhp - output a command to a hp plotter                 *
***********************************************************************/

int icnvt[10], j, ierror, length; unsigned int i;
int gitoch();
 
/*           Set label(text) size  /SI/  */
static int txtsiz[2] = {BIGS, BIGI};
 
static int comma[1] = {COMMA};
static int period[1] = {PERIOD};
static int semcol[1] = {SEMICOL};
static int zero[1] = {DIG0};
   

   dbufhp (2, txtsiz);   /*Put out text size command  */
 
   /*To avoid using real numbers we store the height and width in  */
   /*.01 cm units with an implied decimal point two places to      */
   /*the left (100 = 1 cm).  4 plotter steps = .01 cm              */

   j = wid % 100; i = wid / 100;              /*Get whole number of centimeters  */
                                             /*and remainder  j=mod(wid,100)    */
   length = gitoch (i, icnvt, 6, &ierror);    /*Output whole # of centimeters    */
   dbufhp (length, icnvt);
   dbufhp (1, period);
   if (j < 10) dbufhp (1, zero);             /*Output tenths digit if 0         */
   length = gitoch (j, icnvt, 6, &ierror);    /*Output fractional centimeters    */
   dbufhp (length, icnvt);
   dbufhp (1,comma);
 
   j = hgt % 100; i = hgt / 100;                  /*Get whole # of centimeters       */
					     /*and remainder j=mod(hgt,100)     */
   length = gitoch (i, icnvt, 6, &ierror);    /*Output whole # of centimeters    */
   dbufhp (length, icnvt);
   dbufhp (1, period);
   if (j < 10) dbufhp (1, zero);             /*Output tenths digit if 0         */
   length = gitoch (j, icnvt, 6, &ierror);    /*Output fractional centimeters    */
   dbufhp (length, icnvt);
   dbufhp (1,semcol);

}

dp747x (color)
int color;
{
/***********************************************************************
*                                                                      *
*     Function: Change the color on the H P 747x plotter               *
*                                                                      *
*     Input Parameters:                                                *
*            color - color to change to                                *
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            gznppl - prompt for new pen on plotter                    *
*            dbufhp - output a command to a hp plotter                 *
***********************************************************************/
 
int newsta;
extern int pens[], clrred[], clrgrn[], clrblu[];
 
#include "ddcom.h";
 
/*   Change pens   */
static int penclr[4] = { BIGS, BIGP, DIG0, SEMICOL };  /*  SP0; */
 
if (ndclrp != color) {
   /*prompt for new pen on plotter if necessary  */
   gznppl (color, nmbrpens, pens, &newsta);
 
   ndclrp = color;   /*Set the current color  */
 
   penclr[2] = newsta + DIG0; /*Load this pen station  */
   dbufhp (4, penclr);
   }
}

dbufhp (icount, iarray)
int icount, iarray[];
{
/***********************************************************************
*                                                                      *
*     Function: HP747x buffered output handler                         *
*                                                                      *
*     Input Parameters:                                                *
*           icount - number of characters in iarray to be output       *
*                    -1 flushes the buffer                             *
*                                                                      *
*           iarray - Array of characters to be output                  *
*                                                                      *
*     Output Parameters: none                                          *
*                                                                      *
*     Routines Called:                                                 *
*            RDRIN - get a character from the plotter                  *
*            PCHOUT - output a character to the plotter                *
*            outstr - output a string to the plotter                   *
*                                                                      *
***********************************************************************/
 
int adechar, k;
 
#include "ddcom.h";
 
   k = icount;
   if (k < 0) k = 0;
   if (((ndotkt+k) > MAXxHPxBUFFER) || (icount < 0)) {
      PCHOUT (ENQ);               /*Output buffer terminating character  */
      ndotkt = 0;               /*Reset the plotter buffer counter     */
      /*Wait for prompt response from device. The prompt in most cases is */
      /*   the ack (6) character.                                      */
      adechar = 0;
      do RDRIN (&adechar);
        while ((adechar != NEWLINE) && (adechar != ACK));
      }
   outstr (k, iarray);
   ndotkt = ndotkt + k;         /*Update the plotter buffer counter    */
}

gznfpl()
{
/***********************************************************************
*                                                                      *
*     Function: Issue prompt to change paper and wait for input        *
*                                                                      *
*     Input Parameters:                                                *
*            none                                                      *
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            TTYIN - get keyboard input                                *
*            TTYOUT - output text to console                           *
***********************************************************************/

   int i;
   static int string[] = {
     BIGC,BIGH,BIGA,BIGN,BIGG,BIGE,SP,BIGP,BIGA,BIGP,BIGE,BIGR,COMMA,
     SP,BIGT,BIGH,BIGE,BIGN,SP,BIGP,BIGR,BIGE,BIGS,BIGS,SP,BIGR,BIGE,
     BIGT,BIGU,BIGR,BIGN,CR,LF };

   i=0; do TTYOUT(string[i]); while (string[i++]!=LF);
   TTYIN(&i);
}

gznppl(color, npens, pens, newstat)
int color, npens, pens[], *newstat;
{
/***********************************************************************
*                                                                      *
*     Function: Issue prompt to change pens and wait for input         *
*                                                                      *
*     Input Parameters:                                                *
*            color - new color                                         *
*            npens - number of pens on plotter                         *
*            pens - pen station array                                  *
*                                                                      *
*     Output Parameters:                                               *
*            newstat - new station                                     *
*                                                                      *
*     Routines Called:                                                 *
*            TTYIN - get keyboard input                                *
*            TTYOUT - output text to console                           *
***********************************************************************/

   int i,j;
   static string[] = {
    BIGP,BIGL,BIGA,BIGC,BIGE,SP,BIGP,BIGE,BIGN,SP,SP,SP,SP,SP,SP,SP,BIGI,BIGN,SP,BIGD,BIGE,
    BIGS,BIGI,BIGR,BIGE,BIGD,SP,BIGP,BIGE,BIGN,SP,BIGS,BIGT,BIGA,BIGT,BIGI,
    BIGO,BIGN,COMMA,SP,BIGT,BIGH,BIGE,BIGN,SP,BIGE,BIGN,BIGT,BIGE,BIGR,SP,
    BIGS,BIGT,BIGA,BIGT,BIGI,BIGO,BIGN,SP,BIGN,BIGU,BIGM,BIGB,BIGE,BIGR,COLON,
    SP,-1 };

   *newstat=-1;
   for (i=0; i<npens; ++i) if (pens[i]==color) *newstat=i+1;
   if (*newstat==-1) {
      for (i=10;i<14;++i) string[i]=SP; gitoch(color,&string[10],5,&i);
      i=0; do TTYOUT(string[i]); while (string[++i]>=0);
      TTYIN(&i); TTYOUT(i); 
      TTYOUT(CR); TTYOUT(LF);
      *newstat = gimnmx(i-'0',1,npens);
      pens[*newstat-1]=color;
      }
   }


instr (lenin,string,lenout)
int lenin, string[], *lenout;
{
/***********************************************************************
*                                                                      *
*     Function: Input a string from the plotter                        *
*                                                                      *
*     Input Parameters:                                                *
*            lenin - maximum length of string                          *
*                                                                      *
*     Output Parameters:                                               *
*            string - array of ADE values received from plotter        *
*            lenout - actual length of string                          *
*                                                                      *
*     Routines Called:                                                 *
*            RDRIN - get plotter input                                 *
***********************************************************************/

   int i, tmplen;

   /* check for valid length */

   *lenout = 1; 
   if (lenin>0) {
      tmplen = min0(lenin,81);
      i=-1;
      do {
      RDRIN(&(string[++i]));
         *lenout = i;
         } while (i<lenin && string[i]!=CR);
      }
   /* put the 'new line' character at the end of the string */
   string[*lenout] = LF;
   }

outstr (len, string)
int len, string[];
{
/***********************************************************************
*                                                                      *
*     Function: Output a string to the plotter                         *
*                                                                      *
*     Input Parameters:                                                *
*            len - length of string                                    *
*            string - array of ADE values                              *
*                                                                      *
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            RDROUT - send character to plotter                        *
***********************************************************************/

   int i;

   for (i=0; i<len; ++i) PCHOUT (string[i]);
   }

int gitoch (value, string, max, ierror)
int string[], max, value, *ierror;
{
/*********************************************************************
* 			  				             *
* 	FUNCTION: CONVERT AN INTEGER TO AN ADE STRING                *
* 							             *
* 	INPUT PARAMETERS:				             *
* 		VALUE - INTEGER TO BE CONVERTED                      *
*		MAX - MAXIMUM LENGTH OF STRING                       *
* 			  				             *
* 	OUTPUT PARAMETERS:				             *
* 		STRING - ARRARY TO HOLD THE ADE VALUES               *
*    		IERROR - ERROR FLAG                                  *
* 							             *
* 	ROUTINES CALLED:				             *
*               NONE                                                 *
*********************************************************************/

    int l;

    *ierror=-1;
    nb2ade(value,string,&l);
    if ((l<=0) || (l>max)) return(0);
    else {*ierror=0; return(l);}
   }

int gimnmx (value, min, max)
int value, min, max;
{
/*********************************************************************
* 			  				             *
* 	FUNCTION: CHECK THAT AN INTEGER IS WITHIN A GIVEN RANGE      *
* 							             *
* 	INPUT PARAMETERS:				             *
* 		VALUE - INTEGER TO CHECK                             *
*		MIN - MINIMUM LEGAL VALUE                            *
*		MAX - MAXIMUM LEGAL VALUE                            *
* 			  				             *
* 	OUTPUT PARAMETERS:				             *
*               GIMNMX - VALUE RETURNED                              *
* 							             *
* 	ROUTINES CALLED:				             *
*               NONE                                                 *
*********************************************************************/

    return (min0(max0(min,value),max));
    }

nb2ade(number,chars,number_char)
int number,*number_char;
int *chars;

/***********************************************************************
*                                                                      *
*     Function: Convert a number to an ade-string                      *
*                                                                      *
*     Input Parameters:                                                *
*            number - value to convert                                 *
*                                                                      *
*     Output Parameters:                                               *
*            chars - array of ade values                               *
*            number_char - length of chars                             *
*                                                                      *
*     Routines Called:                                                 *
*            none                                                      *
***********************************************************************/

{
	int digit,i,first,tens[5];
	tens[0]=10000; tens[1]=1000; tens[2]=100; tens[3]=10;
	tens[4]=1;
	if (number==0) {
		*number_char=1;
		*(chars++)='0';
	}
	else {
		*number_char=0;
		first=0;
		if (number<0) {
			*number_char=1;
			*(chars++)='-';
			number*=-1;
		}
		for (i=0;i<=4;++i) {
			digit=number/tens[i];
			if (digit>0 || first!=0)  {
				*(chars++)=digit + '0';
				++*number_char;
				number-=digit*tens[i];
				first=1;
			}
		}
	}
}

gchtoi (string, start, value, stop)
int string[], start, *value, *stop;
{
/*********************************************************************
* 			  				             *
* 	FUNCTION: CONVERT AN ADE STRING TO AN INTEGER                *
* 							             *
* 	INPUT PARAMETERS:				             *
* 		STRING - ARRAY CONTAINING THE STRING                 *
*		START - POSITION IN STRING TO START CONVERSION       *
* 			  				             *
* 	OUTPUT PARAMETERS:				             *
* 		VALUE - THE INTEGER VALUE                            *
*    		STOP - THE LAST POSITION OF THE STRING IN THE ARRAY  *
* 							             *
* 	ROUTINES CALLED:				             *
*               NONE                                                 *
*********************************************************************/

    int sign;


    sign = 1;
    for (*stop=start; string[*stop]==' '; *stop++);
    if (string[*stop] == '+' || string[*stop] == '-' )     /* sign */
       sign = (string[(*stop)++]=='+') ? 1 : -1;
    for (*value = 0; string[*stop] >= '0' && string[*stop] <= '9'; (*stop)++)
       *value = 10 * *value + string[*stop] - '0';
    *value = sign * *value;
    }

int min0 (a,b)
int a,b;
{
/*********************************************************************
* 			  				             *
* 	FUNCTION: RETURN THE MINIMUM OF A AND B                      *
* 							             *
* 	INPUT PARAMETERS:				             *
* 		A, B - VALUES TO FIND THE MINIMUM OF                 *
* 			  				             *
* 	OUTPUT PARAMETERS:				             *
* 		MIN0 - FUNCTION VALUE RETURNED                       *
* 							             *
* 	ROUTINES CALLED:				             *
*               NONE                                                 *
*********************************************************************/

    return((a<b) ? a : b);
    }

int max0 (a,b)
int a,b;
{
/*********************************************************************
* 			  				             *
* 	FUNCTION: RETURN THE MAXIMUM OF A AND B                      *
* 							             *
* 	INPUT PARAMETERS:				             *
* 		A, B - VALUES TO FIND THE MAXIMUM OF                 *
* 			  				             *
* 	OUTPUT PARAMETERS:				             *
* 		MIN0 - FUNCTION VALUE RETURNED                       *
* 							             *
* 	ROUTINES CALLED:				             *
*               NONE                                                 *
*********************************************************************/

    return((a>b) ? a : b);
    }

gsxfill (int_style, style_index, line_style, length)
int int_style, style_index, length;
/***********************************************************************
*                                                                      *
*     Function: Prepare data for polygon-fill routine                  *
*                                                                      *
*     Input Parameters:                                                *
*            int_style - interior style                                *
*            style_index - interior style index                        *
*            line_style - current line style                           *
*            length - number of points in polygon                      *
*                                                                      *
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            LSTORE - long store                                       *
*            LFETCH - long fetch                                       *
*            plyfill - polygon fill                                    *
*            dr747x - move/draw on plotter                             *
*            dbufhp - send string to plotter                           *
***********************************************************************/

{
   int savexy[2], xy[2], ival, i, j, distance;

/*           Set line style to solid /LT;/ */
   static int solid[3] ={BIGL, BIGT, SEMICOL};

/*           Line style /LT<0>,2;/ */
   static int lstyle[6] ={BIGL, BIGT, DIG0, COMMA, DIG2, SEMICOL};

   dbufhp (3, solid);                    /*Set linetype to solid       */
   if (ndistyf==1 || ndistyf==3) {
      savexy[0]=LFETCH(pinseg,pinoff,2*length);
      savexy[1]=LFETCH(pinseg,pinoff,2*length+1);
      LSTORE(pinseg,pinoff,2*length,LFETCH(pinseg,pinoff,0));
      LSTORE(pinseg,pinoff,2*length+1,LFETCH(pinseg,pinoff,1));

      distance = (ndistyf==1) ? 12 : 120;
      if (ndistyf==1) ival = 2;
      else {
         ival = ndstyf;
         if (ndstyf > 4) ival -= 3;
      }   
      plyfill (ival, distance, length+1);
      if (ndistyf==3 && ndstyf>4) {   
         ival = (ndstyf==5) ? 1 : 4;
         plyfill (ival, distance, length+1);
      }
      LSTORE(pinseg,pinoff,2*length,savexy[0]);
      LSTORE(pinseg,pinoff,2*length+1,savexy[1]);
   }
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (MOVE, xy);              /*Move to first point         */

   dr747x (MOVE, xy);              /*Move to repostion pen       */

   j = 2;
   for (i=2; i<=length; ++i) {  /*draw between subsequent points    */
      xy[0]=x_fetch(j);
      xy[1]=y_fetch(j);
      dr747x (DRAW, xy);
      j += 2;
      }
   xy[0]=x_fetch(0);
   xy[1]=y_fetch(0);
   dr747x (DRAW, xy);     /*draw to first point to make sure     */
				     /*polygon closed                  */
   dr747x (MOVE, xy);     /*Move to the point to pick the pen up */

   if (ndlntp != DIG0) {             /*restore line type if not solid       */
      lstyle[2] = ndlntp;
      dbufhp (6, lstyle);
      }
}

int x_fetch(position) {return(LFETCH(pinseg,pinoff,position+1)+wxmin);}

int y_fetch(position) {return(wymax-LFETCH(pinseg,pinoff,position));}

plyfill(pattern,distance,length)
int pattern, distance, length;
/***********************************************************************
*                                                                      *
*     Function: Fill a polygon                                         *
*                                                                      *
*     Input Parameters:                                                *
*            pattern - fill pattern                                    *
*            distance - distance between fill lines                    *
*            length - number of points in polygon                      *
*                                                                      *
*     Output Parameters:                                               *
*            none                                                      *
*                                                                      *
*     Routines Called:                                                 *
*            LSTORE - long store                                       *
*            LFETCH - long fetch                                       *
*            MULDIV - muliply and divide using 32-bits                 *
*            INTERCPT - calculate intercept formula in 32 bits         *
*            dr2x0 - move/draw on plotter                             *
***********************************************************************/

{
   int incr, i, j, raster, intx[50], LFETCH(), MULDIV(), INTERCPT(), wmin, wmax;
   int x1, x2, y1, y2, j2, xy[2], temp, oldx, oldy;
   int oxmin, oxmax, oymin, oymax, intercept, sign, evenodd;
   int x_fetch(),y_fetch();

   incr = distance;
   if (pattern > 2) incr = (distance*7)/5;
   sign = (pattern == 4) ? -1 : 1;
   oxmax = oymax = -1; oxmin = oymin = 32767;
   x1 = x_fetch(0);  y1 = y_fetch(0);
   for (i=2*length-4; i>0; i-=2) {
      oldx = x_fetch(i);
      oldy = y_fetch(i);
      if (pattern==1 && oldy!=y1) break;
      if (pattern==2 && oldx!=x1) break;
      if (pattern>2 && (oldx-oldy)!=(-1*sign*(x1-y1))) break;
      }
   for (i=0; i<2*length; i+=2) {
      x1 = x_fetch(i);
      y1 = y_fetch(i);
      if (oxmax < x1) oxmax = x1;
      if (oxmin > x1) oxmin = x1;
      if (oymax < y1) oymax = y1;
      if (oymin > y1) oymin = y1;
   }
   switch (pattern) {
      case 2: wmin = oxmin; wmax = oxmax; break;
      case 1: wmin = oymin; wmax = oymax; break;
      case 4: wmin = oymin - oxmax; wmax = oymax - oxmin; break;
      case 3: wmax = oxmax + oymax; wmin = oxmin + oymin; break;
   }
   evenodd=0;
   for (raster=wmax; raster>=wmin; raster-=incr) {
      j = 0;
      evenodd = (++evenodd)%2;
      for (i=0; i<(2*length-2); i+=2) {
         x1 = x_fetch(i);
         y1 = y_fetch(i);
         x2 = x_fetch(i+2);
         y2 = y_fetch(i+2);
         intercept = -1;
         switch (pattern) {
            case 2:
              if ((x1<=raster && x2>=raster) || (x1>=raster && x2<=raster))
                 if (x1!=x2) {
                    intercept = y1 + MULDIV(raster-x1,y1-y2,x1-x2);
                    if ((x1==raster) && ((x2<raster && oldx>raster) ||
                                     (x2>raster && oldx<raster))) 
                       intercept=-1;
                 }
              if (x1!=x2) {oldx=x1; oldy=y1;}
              break;
            case 1:
              if ((y1<=raster && y2>=raster) || (y1>=raster && y2<=raster))
                 if (y1!=y2) {
                    intercept = x1 + MULDIV(raster-y1,x1-x2,y1-y2);
                    if ((y1==raster) && ((y2<raster && oldy>raster) ||
                                     (y2>raster && oldy<raster))) 
                       intercept=-1;
                 }
              if (y1!=y2) {oldx=x1; oldy=y1;}
              break;
            case 3: 
            case 4:
              if (((sign*x1+y1)<=raster && (sign*x2+y2)>=raster) ||
                  ((sign*x1+y1)>=raster && (sign*x2+y2)<=raster))
                 if (((x1!=x2) || (y1!=y2)) && (((y1-y2)+sign*(x1-x2))!=0)) {
                    intercept = INTERCPT(raster,sign,x1,y1,x2,y2);
                    if (((sign*x1+y1)==raster) && (((sign*x2+y2)<raster && (sign*oldx+oldy)>raster) ||
                                     ((sign*x2+y2)>raster && (sign*oldx+oldy)<raster))) 
                       intercept=-1;
                 }
              if ((x1-x2)!=(-1*sign*(y1-y2))) {oldx=x1; oldy=y1;}
              break;
            }
            if (intercept>=0) {
               intx[j++]=intercept;
               l_insert(intx,j-1,intx[j-1],evenodd);
            }
      }
      i = 0;
      for (j2=0; j2<j; ++j2) {
         switch (pattern) {
            case 2:
              xy[0] = raster; xy[1] = intx[j2]; break;
            case 1:
              xy[0] = intx[j2]; xy[1] = raster; break;
            case 3:
            case 4:
              xy[0] = intx[j2];  xy[1] = raster - sign*intx[j2]; break;
         }
         dr747x ((i++ % 2) + 1, xy);
      }
   }
}

l_insert(array,length,value,evenodd)
int array[], length, value, evenodd;
{
   int j, j2;

   for (j=0; j<length; ++j) 
      if ((array[j] > value && evenodd==0) || (array[j] < value && evenodd!=0)) {
         for (j2=length-1; j2>=j; --j2) array[j2+1]=array[j2];
         array[j]=value;
         break;
      }
}
