/*******************************************************************
*
*  Task CADPLOT
*
* PARMS[0]: LABEL LOCATIONS <0 NO LABELS
*              100's TITLE,  0-> TOP
*              10's  XLABEL, 0-> BOTTOM
*              1's   YLABEL, 0-> LEFT SIDE
*
* PARMS[1]: X TICS <0 NO TICS
*              100's=0 Inside, 100's >0 Outside
*              10's=0 Double Marks, 10's>0 Single Marks
*              1's=0 BOTTOM, 1's>0 TOP
*
* PARMS[2]: Y TICS <0 NO TICS
*              100's=0 Inside, 100's >0 Outside
*              10's=0 Double Marks, 10's>0 Single Marks
*              1's=0 LEFT, 1's>0 RIGHT
*
* PARMS[3]: <= 0 ->PLOT LINES else PLOT POINTS abs(PARMS[3]) is SYMBOL
*
* PARMS[4]: Layer Name
*
* PARMS[5]: T LOG BASE
* PARMS[6]: Y LOG BASE
* 
* PARMS[7]: T-AXIS END POINT LABELING (1's LOWER, 10's HIGHER)
* PARMS[8]: Y-AXIS END POINT LABELING (1's LOWER, 10's HIGHER)
*
* PARMS[9]: NUMERIC LABEL CONTROL (1's  Y AXIS HORIZONTAL NUMBERS DEFAULT)
*                                 (10's T AXIS HORIZONTAL NUMBERS DEFAULT)]
*                                 (100's INVERT Y AXIS IF SET)
*                                 (1000's INVERT T AXIS IF SET)
*
* CODE != 0 -> 3D Line, else 2D Lines
*                                 
* FACTOR: Data skip interval (2 = every other point, ect.)
*/
#include <malloc.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <io.h>
#include <time.h>
#include <dos.h>
#include <process.h>
#include <ctype.h>
#include <signal.h>

#include "TISAN.H"

#define Tpnt(x) (IITA ? (W0 + W2 - (x)) : (x))    /* Reverse T Axis */
#define Ypnt(y) (IIYA ? (W1 + W3 - (y)) : (y))    /* Reverse Y Axis */

double PLOG(double,short);
short GETRNG(double *,double *,double *,double *,FILE *,struct FILEHDR *,int);
void CHKBRK(void);
void FRAMEIT(void);
void LINE(short,short,short,short);
void MAININIT(void);
void PLTALPHA(char *,short,short,short);
void PLTSYM(double,double);
void PLOT2(void);
void PLOT1(void);
void PTXTICS(short,short);
void PTYTICS(short,short);
void PTSETUP(short *,short *);
void PUTLAB(void);
void PUTTICS(void);
void VECTOR(double,double,double,double,short);
short FPEERROR(void);

char BUFFER[256];
char BUFFER1[sizeof(struct TXData)];
char BUFFER2[sizeof(struct TXData)];
char SBUFF[1280], TMPFILE[_MAX_PATH];
char *SFORMAT="%s\n", *FFORMAT="%f\n", *DFORMAT="%d\n";
double TSLOPE, TINTER, YSLOPE, YINTER, T0, T1;
double TPL1, TPL2, YPL1, YPL2, YSLOPE, YINTER, YDELTA;
double TDELTA, YVT, TVT;
double TCNT;
double TIME, DATA, TOTAL=0.;
FILE *OUTSTR=0;
struct FILEHDR F1Header, F2Header;
short CWIDTH=200, CHEIGHT=200, XTICBASE=200, YTICBASE=200;
short IYV, ITV, IIYA, IITA;
short LUTABLE[] = {1,2,4,5,8,10,10,15,15,20,25};
short SCLIPXL,SCLIPYL,SCLIPXH,SCLIPYH;
short XROT, YROT;
short FLAG=0;
struct RData   *RDataPntr1,  *RDataPntr2;
short W0, W1, W2, W3, T2FLAG=0;
struct TRData *TRDataPntr1, *TRDataPntr2;
struct TXData *TXDataPntr1, *TXDataPntr2;
struct XData   *XDataPntr1,  *XDataPntr2;
short FirstPointFlag;
union REGS REGISTER;
char far CADHDR1[] =
     {
     '0','\n',
     'S','E','C','T','I','O','N','\n',
     '2','\n',
     'H','E','A','D','E','R','\n',
     '9','\n',
     '$','A','C','A','D','V','E','R','\n',
     '1','\n',
     'A','C','1','0','0','3','\n',
     '9','\n',
     '$','I','N','S','B','A','S','E','\n',
     '1','0','\n',
     '0','.','0','\n',
     '2','0','\n',
     '0','.','0','\n',
     '9','\n',
     '$','E','X','T','M','I','N','\n',
     '1','0','\n',
     '-','1','.','0','\n',
     '2','0','\n',
     '-','1','.','0','\n',
     '9','\n',
     '$','E','X','T','M','A','X','\n',
     '1','0','\n',
     '1','8','.','0','\n',
     '2','0','\n',
     '1','2','.','0','\n',
     '9','\n',
     '$','L','I','M','M','I','N','\n',
     '1','0','\n',
     '-','1','.','0','\n',
     '2','0','\n',
     '-','1','.','0','\n',
     '9','\n',
     '$','L','I','M','M','A','X','\n',
     '1','0','\n',
     '1','8','.','0','\n',
     '2','0','\n',
     '1','2','.','0','\n',
     '9','\n',
     '$','V','I','E','W','C','T','R','\n',
     '1','0','\n',
     '9','.','8','3','7','5','2','6','\n',
     '2','0','\n',
     '6','.','0','\n',
     '9','\n',
     '$','V','I','E','W','S','I','Z','E','\n',
     '4','0','\n',
     '1','2','.','0','\n',
     '0','\n',
     'E','N','D','S','E','C','\n',
     '0','\n',
     'S','E','C','T','I','O','N','\n',
     '2','\n',
     'T','A','B','L','E','S','\n',
     '0','\n',
     'T','A','B','L','E','\n',
     '2','\n',
     'L','T','Y','P','E','\n',
     '7','0','\n',
     '1','\n',
     '0','\n',
     'L','T','Y','P','E','\n',
     '2','\n',
     'C','O','N','T','I','N','U','O','U','S','\n',
     '7','0','\n',
     '6','4','\n',
     '3','\n',
     'S','o','l','i','d',' ','l','i','n','e','\n',
     '7','2','\n',
     '6','5','\n',
     '7','3','\n',
     '0','\n',
     '4','0','\n',
     '0','.','0','\n',
     '0','\n',
     'E','N','D','T','A','B','\n',
     '0','\n',
     'T','A','B','L','E','\n',
     '2','\n',
     'L','A','Y','E','R','\n',
     '7','0','\n',
     '2','\n',
     '0','\n',
     'L','A','Y','E','R','\n',
     '2','\n',
     '0','\n',
     '7','0','\n',
     '0','\n',
     '6','2','\n',
     '7','\n',
     '6','\n',
     'C','O','N','T','I','N','U','O','U','S','\n',
     '0','\n',
     'L','A','Y','E','R','\n',
     '2','\n','\0'
     };

/* Layer Name Goes Here */

char far CADHDR2[] =
     {
     '7','0','\n',
     '0','\n',
     '6','2','\n','\0'
     };

/* Layer Color Goes Here */

char far CADHDR3[] =
     {
     '6','\n',
     'C','O','N','T','I','N','U','O','U','S','\n',
     '0','\n',
     'E','N','D','T','A','B','\n',
     '0','\n',
     'T','A','B','L','E','\n',
     '2','\n',
     'S','T','Y','L','E','\n',
     '7','0','\n',
     '3','\n',
     '0','\n',
     'S','T','Y','L','E','\n',
     '2','\n',
     'S','T','A','N','D','A','R','D','\n',
     '7','0','\n',
     '0','\n',
     '4','0','\n',
     '0','.','0','\n',
     '4','1','\n',
     '1','.','0','\n',
     '5','0','\n',
     '0','.','0','\n',
     '7','1','\n',
     '0','\n',
     '4','2','\n',
     '0','.','1','\n',
     '3','\n',
     'T','X','T','\n',
     '0','\n',
     'S','T','Y','L','E','\n',
     '2','\n',
     'S','I','M','P','L','E','X','\n',
     '7','0','\n',
     '0','\n',
     '4','0','\n',
     '0','.','0','\n',
     '4','1','\n',
     '1','.','0','\n',
     '5','0','\n',
     '0','.','0','\n',
     '7','1','\n',
     '0','\n',
     '4','2','\n',
     '0','.','2','\n',
     '3','\n',
     'S','I','M','P','L','E','X','\n',
     '0','\n',
     'S','T','Y','L','E','\n',
     '2','\n',
     'C','O','M','P','L','E','X','\n',
     '7','0','\n',
     '0','\n',
     '4','0','\n',
     '0','.','0','\n',
     '4','1','\n',
     '1','.','0','\n',
     '5','0','\n',
     '0','.','0','\n',
     '7','1','\n',
     '0','\n',
     '4','2','\n',
     '0','.','2','\n',
     '3','\n',
     'C','O','M','P','L','E','X','\n',
     '0','\n',
     'E','N','D','T','A','B','\n',
     '0','\n',
     'T','A','B','L','E','\n',
     '2','\n',
     'V','I','E','W','\n',
     '7','0','\n',
     '0','\n',
     '0','\n',
     'E','N','D','T','A','B','\n',
     '0','\n',
     'E','N','D','S','E','C','\n',
     '0','\n',
     'S','E','C','T','I','O','N','\n',
     '2','\n',
     'E','N','T','I','T','I','E','S','\n',
     '0','\n','\0'
     };

main(argc,argv)
short argc;
char *argv[];
   {
   FILE *INSTR, *IN2STR=0;
   double TMIN, TMAX, YMIN, YMAX;
   double TR1, TR2, YR1, YR2;
   short I;
   unsigned short UI;
   short ERRFLAG=0, NUMDAT, NUM2DAT, CGMODE;
   char INFILE[_MAX_PATH], IN2FILE[_MAX_PATH], OUTFILE[_MAX_PATH];
   unsigned char C;
   struct CATSTRUCT *CatList;
   char *pChar;
   char Drive[_MAX_DRIVE], Dir[_MAX_DIR], Fname[_MAX_FNAME], Ext[_MAX_EXT];
   int AutoAmpScale = 0, AutoTimeScale = 0, SecondFile = 0;

   signal(SIGINT,BREAKREQ);            /* Set up ^C Handler */
   signal(SIGFPE,FPEERROR);  /* Setup Floating Point Error Trap */

   if (Ztskinit("CADPLOT",argv[0])) Zexit(1);   /* Initialize task */

   T0 = TRANGE[0];                     /* Save current TRANGE */
   T1 = TRANGE[1];

   MAININIT();                         /* Main Program Initialization */

   if (YRANGE[0] >= YRANGE[1]) AutoAmpScale = 1;
   if (TRANGE[0] >= TRANGE[1]) AutoTimeScale = 1;

   ZBuildFileName(M_inname,INFILE);
   ZBuildFileName(M_in2name,IN2FILE);
   ZBuildFileName(M_outname,OUTFILE);
   ZBuildFileName(M_tmpname,TMPFILE);

   if (strchr(OUTFILE,'*') || strchr(OUTFILE,'?'))
      {
      Zencode(10,"CADPLOT : Invalid Output File Name '%s'\n",OUTFILE);
      Zexit(1);
      }

   if (strcmp(INFILE,IN2FILE)) SecondFile = 1;

   if (!(CatList = ZCatFiles(INFILE))) Zexit(1); /* Find Matching Files */

   if (AutoAmpScale || AutoTimeScale)
      {
      Zencode(3,"CADPLOT : Determining Primary File Scale(s)\n");
      for (I = 0, pChar = CatList->pList;
           (I < CatList->N) && !ERRFLAG;
           ++I, pChar = strchr(pChar,'\0') + 1)
         {
         _splitpath(pChar,Drive,Dir,Fname,Ext);
         strcpy(INNAME,Fname);
         strcpy(INCLASS,Ext);
         ZBuildFileName(M_inname,INFILE);
         Zencode(2,"CADPLOT : Opening Input File '%s'\n",INFILE);
         if (((INSTR = Zopen(INFILE,O_readb)) == NULL) ||
           (!Zgethead(INSTR,&F1Header))) Zexit(1);
         switch (F1Header.type)
            {
            case R_Data:
            case TR_Data:
            case X_Data:
            case TX_Data:
               break;
            default:
               Zencode(10,"CADPLOT : Invalid File Type.\n");
               Zexit(1);
            }
         if (GETRNG(&YMAX,&YMIN,&TMAX,&TMIN,INSTR,&F1Header,I))
            {
            ERRFLAG = 1;
            goto EXIT;
            }
         Zclose(INSTR);
         }
      if (AutoAmpScale) /* Find Scale */
         {
         YRANGE[0] = YMIN;
         YRANGE[1] = YMAX;
         }
      if (AutoTimeScale)
         {
         TRANGE[0] = TMIN;
         TRANGE[1] = TMAX;
         }
      }


   Zencode(2,"CADPLOT : Opening Scratch File '%s'\n",TMPFILE);
   if ((OUTSTR = Zopen(TMPFILE,O_writet)) == NULL) Zexit(1);

   fprintf(OUTSTR,"%Fs",CADHDR1);      /* Write out CAD DXF Header info */
   I = (short)PARMS[4];
   I = Max(1,Min(I,15));
   fprintf(OUTSTR,DFORMAT,I);       /* Layer Name */
   fprintf(OUTSTR,"%Fs",CADHDR2);
   COLOR = Max(1,Min(COLOR,15));
   fprintf(OUTSTR,DFORMAT,COLOR);   /* Layer Color */
   fprintf(OUTSTR,"%Fs",CADHDR3);
   COLOR=I;

   if (SecondFile)
      {
      if (strchr(IN2FILE,'*') || strchr(IN2FILE,'?'))
         {
         Zencode(10,"CADPLOT : Invalid Secondary File Name '%s'\n",IN2FILE);
         Zexit(1);
         }

      Zencode(2,"CADPLOT : Opening Secondary Input File '%s'\n",IN2FILE);
      if (((IN2STR = Zopen(IN2FILE,O_readb)) == NULL) ||
          (!Zgethead(IN2STR,&F2Header)))
         {
         ERRFLAG = 1;
         goto EXIT;
         }

      switch (F2Header.type)
         {
         case R_Data:
         case TR_Data:
         case X_Data:
         case TX_Data:
            T2FLAG=1;
            if (T0 >= T1) /* Find Scale */
               {
               Zencode(3,"CADPLOT : Determining Secondary File Scale\n");
               if (GETRNG(&YMAX,&YMIN,&TMAX,&TMIN,IN2STR,&F2Header,0))
                  {
                  ERRFLAG = 1;
                  goto EXIT;
                  }
               TRANGE[0] = YMIN;
               TRANGE[1] = YMAX;
               }
            break;
         default:
            Zencode(10,"CADPLOT : Invalid File Type.\n");
            ERRFLAG = 1;
            goto EXIT;
         }
      }

   if (TRANGE[0] == TRANGE[1])
      {
      ++TRANGE[1];
      --TRANGE[0];
      }

   if (YRANGE[0] == YRANGE[1])
      {
      --YRANGE[0];
      ++YRANGE[1];
      }

   Zencode(2,"CADPLOT : Building Vector Image\n");

   if (FRAME) FRAMEIT();

   W0 = WINDOW[0];
   W1 = WINDOW[1];
   W2 = WINDOW[2];
   W3 = WINDOW[3];

   I=COLOR;
   COLOR=0;
   PUTLAB();
   PUTTICS();

   SCLIPXL = WINDOW[0] = W0;
   SCLIPXH = WINDOW[2] = W2;
   SCLIPYL = WINDOW[1] = W1;
   SCLIPYH = WINDOW[3] = W3;

   if (BORDER) FRAMEIT();
   COLOR=I;

   if (PARMS[5])
      {
      TR1 = PLOG(TRANGE[0],5);
      TR2 = PLOG(TRANGE[1],5);
      }
   else
      {
      TR1 = TRANGE[0];
      TR2 = TRANGE[1];
      }  
   if (PARMS[6])
      {
      YR1 = PLOG(YRANGE[0],6);
      YR2 = PLOG(YRANGE[1],6);
      }
   else
      {
      YR1 = YRANGE[0];
      YR2 = YRANGE[1];
      }

   TSLOPE = ((double)(WINDOW[2] - WINDOW[0]))/(TR2 - TR1);
   TINTER = (double)WINDOW[0] - TSLOPE*TR1;
   YSLOPE = ((double)(WINDOW[3] - WINDOW[1]))/(YR2 - YR1);
   YINTER = (double)WINDOW[1] - YSLOPE*YR1;

   YPL1 = YRANGE[0];
   YPL2 = YRANGE[1];
   TPL1 = TRANGE[0];
   TPL2 = TRANGE[1];
   TCNT = 0.;

   for (I = 0, pChar = CatList->pList;
        (I < CatList->N) && !ERRFLAG;
        ++I, pChar = strchr(pChar,'\0') + 1)
      {
      FirstPointFlag = 0;
      TCNT = 0.;
      _splitpath(pChar,Drive,Dir,Fname,Ext);
      strcpy(INNAME,Fname);
      strcpy(INCLASS,Ext);
      ZBuildFileName(M_inname,INFILE);
      Zencode(2,"CADPLOT : Opening Input File '%s'\n",INFILE);
      if (((INSTR = Zopen(INFILE,O_readb)) == NULL) ||
           (!Zgethead(INSTR,&F1Header))) Zexit(1);
      switch (F1Header.type)
         {
         case R_Data:
         case TR_Data:
         case X_Data:
         case TX_Data:
            break;
         default:
            Zencode(10,"CADPLOT : Invalid File Type.\n");
            Zexit(1);
         }

      if (!T2FLAG)
         {
         while (Zread(INSTR,BUFFER1,F1Header.type)) PLOT1();
         if (ferror(INSTR)) ERRFLAG=1;
         }
      else /* Plot 2 Files Against One Another */
         {
         while (Zread(INSTR,BUFFER1,F1Header.type) &&
                Zread(IN2STR,BUFFER2,F2Header.type)) PLOT2();
         if (ferror(INSTR) || ferror(IN2STR)) ERRFLAG=1;
         }
      Zclose(INSTR);
/*
      (PARMS[3] < 0) ? --PARMS[3] : (PARMS[3] ? ++PARMS[3] : 0);
      if (PARMS[4]) ++PARMS[4];
*/
      }

/*
** ACAD DXF File Footer
*/
   if (!ERRFLAG)
      {
      fprintf(OUTSTR,SFORMAT,"ENDSEC");
      fprintf(OUTSTR,SFORMAT,"  0");
      fprintf(OUTSTR,SFORMAT,"EOF");
      Zencode(3,"CADPLOT : %G Data Points Processed\n",TOTAL);
      }

EXIT:
   if (IN2STR) Zclose(IN2STR);
   Zclose(OUTSTR);
   Zexit(Znameout(OUTFILE,TMPFILE,ERRFLAG));
   }

/************************************************************
*
* INITIALIZATION
*     This routine sets up the default values from
*     unspecified inputs.
*
*/
void MAININIT()
   {
   strcpy(OUTCLASS,"DXF");                            /* Always DXF */
   if ((PARMS[4] <0) || (PARMS[4] > 99)) PARMS[4] = 0;
   if (PARMS[5]) TMINOR = Max(TMINOR,2);
   if (PARMS[6]) YMINOR = Max(YMINOR,2);
   if ((PARMS[5] <=0) || (PARMS[5] == 1))
      PARMS[5] = 0;
   else
      PARMS[5] = log(PARMS[5]);

   if ((PARMS[6] <=0) || (PARMS[6] == 1))
      PARMS[6] = 0;
   else
      PARMS[6] = log(PARMS[6]);

   if (PARMS[7] <0) PARMS[7] = 0;
   if (PARMS[8] <0) PARMS[8] = 0;

   SCLIPXL=SCLIPYL=0;               /* Configure for 11 x 17 inches */
   SCLIPXH= 16999;
   SCLIPYH= 10999;

   WINDOW[0] = Max(WINDOW[0],0);
   WINDOW[2] = Max(WINDOW[2],0);
   WINDOW[1] = Min(WINDOW[1],SCLIPXH);
   WINDOW[3] = Min(WINDOW[3],SCLIPYH);

   if (WINDOW[0] >= WINDOW[2])
      {
      WINDOW[0] = 0;
      WINDOW[2] = SCLIPXH;
      }
   if (WINDOW[1] >= WINDOW[3])
      {
      WINDOW[1] = 0;
      WINDOW[3] = SCLIPYH;
      }

   if (!strlen(TFORMAT)) strcpy(TFORMAT,"%G");  /* Default output formats */
   if (!strlen(YFORMAT)) strcpy(YFORMAT,"%G");

   if (!COLOR) COLOR=7;                         /* Default color */

   RDataPntr1 =  (struct RData *)BUFFER1; /* Initialize pointers */
   RDataPntr2 =  (struct RData *)BUFFER2;
   TRDataPntr1 = (struct TRData *)BUFFER1;
   TRDataPntr2 = (struct TRData *)BUFFER2;
   XDataPntr1 =  (struct XData *)BUFFER1;
   XDataPntr2 =  (struct XData *)BUFFER2;
   TXDataPntr1 = (struct TXData *)BUFFER1;
   TXDataPntr2 = (struct TXData *)BUFFER2;
   return;
   }

/************************************************************
*
* PLOT1
*     Plot a single file.
*
*/
void PLOT1()
   {
   double XLOC, YLOC;

   ++TOTAL;
   switch (F1Header.type)
      {
      case R_Data:
         TIME = TCNT * F1Header.m + F1Header.b;
         DATA = RDataPntr1->y;
         FLAG = RDataPntr1->f;
         break;
      case TR_Data:
         TIME = TRDataPntr1->t;
         DATA = TRDataPntr1->y;
         break;
      case X_Data:
         TIME = TCNT * F1Header.m + F1Header.b;
         DATA = cabs(XDataPntr1->z);
         FLAG = XDataPntr1->f;
         break;
      case TX_Data:
         TIME = TXDataPntr1->t;
         DATA = cabs(TXDataPntr1->z);
         break;
      }
   ++TCNT;

   CHKBRK();            /* Test for ^C */
   if (!FLAG)           /* Only plot good data */
      {
      if (PARMS[5]) TIME = PLOG(TIME,5);
      if (PARMS[6]) DATA = PLOG(DATA,6);
      XLOC = Tpnt(TSLOPE*TIME + TINTER);
      YLOC = Ypnt(YSLOPE*DATA + YINTER);
      if (PARMS[3]>0)
         PLTSYM(XLOC,YLOC);
      else if (!FirstPointFlag)                     /* First point */
         {
         if (PARMS[3]) PLTSYM(XLOC,YLOC);
         VECTOR(XLOC,YLOC,XLOC,YLOC,0);
         FirstPointFlag = 1;
         }
      else                                /* Rest of points */
         {
         VECTOR(0.,0.,XLOC,YLOC,1);
         if (PARMS[3]) PLTSYM(XLOC,YLOC);
         }
      }
   return;
   }

/************************************************************
*
* PLOT2
*
*/
void PLOT2()
   {
   double XLOC, YLOC;

   ++TOTAL;
   switch (F1Header.type)    /* Data is Y Axis */
      {
      case R_Data:
         DATA = RDataPntr1->y;
         FLAG = RDataPntr1->f;
         break;
      case TR_Data:
         DATA = TRDataPntr1->y;
         break;
      case X_Data:
         DATA = cabs(XDataPntr1->z);
         FLAG = XDataPntr1->f;
         break;
      case TX_Data:
         DATA = cabs(TXDataPntr1->z);
         break;
      }

   switch (F2Header.type)    /* Data is TIME Axis */
      {
      case R_Data:
         TIME = RDataPntr2->y;
         FLAG += RDataPntr2->f;
         break;
      case TR_Data:
         TIME = TRDataPntr2->y;
         break;
      case X_Data:
         TIME = cabs(XDataPntr2->z);
         FLAG += XDataPntr2->f;
         break;
      case TX_Data:
         TIME = cabs(TXDataPntr2->z);
         break;
      }

   CHKBRK();
   if (!FLAG)
      {
      if (PARMS[5]) TIME = PLOG(TIME,5);
      if (PARMS[6]) DATA = PLOG(DATA,6);
      XLOC = Tpnt(TSLOPE*TIME + TINTER);
      YLOC = Ypnt(YSLOPE*DATA + YINTER);
      if (PARMS[3]>0)
         PLTSYM(XLOC,YLOC);
      else if (!FirstPointFlag)
         {
         if (PARMS[3]) PLTSYM(XLOC,YLOC);
         VECTOR(XLOC,YLOC,XLOC,YLOC,0);
         FirstPointFlag = 1;
         }
      else
         {
         VECTOR(0.,0.,XLOC,YLOC,1);
         if (PARMS[3]) PLTSYM(XLOC,YLOC);
         }
      }
     return;
     }

/************************************************************
*
* Subroutine to Frame the Current Window
*
*/
void FRAMEIT()
   {
   LINE(WINDOW[0],WINDOW[1],WINDOW[0],WINDOW[3]);
   LINE(WINDOW[0],WINDOW[3],WINDOW[2],WINDOW[3]);
   LINE(WINDOW[2],WINDOW[3],WINDOW[2],WINDOW[1]);
   LINE(WINDOW[2],WINDOW[1],WINDOW[0],WINDOW[1]);
   return;
   }

/************************************************************
*
* Subroutine to Title the Plot and update WINDOW
*
*/
void PUTLAB()
     {
   short XLOC, YLOC;
   short VAL, IPARM;
   char C;
/*
*
* Center the Title at the top or bottom and update WINDOW
*
*/
   if (PARMS[0] < 0) return;
   IPARM = PARMS[0];
   VAL = IPARM/100;
   IPARM %= 100;
   if (strlen(TITLE))
      {
      XLOC =  (W2 + W0 + 1 - strlen(TITLE)*CWIDTH)/2;
      if (VAL)
         {
         YLOC = W1; 
         W1 += (CHEIGHT + CHEIGHT/2);
         if (FRAME)
            {
            YLOC += CHEIGHT/2;
            W1 += CHEIGHT/2;
            }
         }
      else
         {
         YLOC = (W3 -= CHEIGHT);
         W3 -= CHEIGHT/2;
         if (FRAME)
            {
            YLOC -= CHEIGHT/2;
            W3 -= CHEIGHT/2;
            }
         }
      CHKBRK();
      PLTALPHA(TITLE,XLOC,YLOC,0);
      }

   VAL = IPARM/10;
   IPARM %= 10;
   if (strlen(TLABEL))
      {
      XLOC =  (W2 + W0 + 1 - strlen(TLABEL)*CWIDTH)/2;
      if (VAL)
         {
         YLOC = (W3 -= CHEIGHT);
         W3 -= CHEIGHT/2;
         if (FRAME)
            {
            YLOC -= CHEIGHT/2;
            W3 -= CHEIGHT/2;
            }
         }
      else
         {
         YLOC = W1; 
         W1 += (CHEIGHT + CHEIGHT/2);
         if (FRAME)
            {
            YLOC += CHEIGHT/2;
            W1 += CHEIGHT/2;
            }
         }
      CHKBRK();
      PLTALPHA(TLABEL,XLOC,YLOC,0);
      }

   if (strlen(YLABEL))
      {
      YLOC =  (W1 + W3 + 1 - strlen(YLABEL)*CWIDTH)/2;
      if (IPARM)
         {
         XLOC = W2; 
         W2 -= (CHEIGHT + CHEIGHT/2);
         if (FRAME)
            {
            XLOC -= CHEIGHT/2;
            W2 -= CHEIGHT/2;
            }
         }
      else
         {
         XLOC = (W0 += CHEIGHT);
         W0 += CHEIGHT/2;
         if (FRAME)
            {
            XLOC += CHEIGHT/2;
            W0 += CHEIGHT/2;
            }
         }
      CHKBRK();
      PLTALPHA(YLABEL,XLOC,YLOC,90);
      }
   return;
   }

/************************************************************
*
* Subroutine to Plot Tic Marks and Numeric Labels
*
*/
void PUTTICS()
   {
   short XLOC, YLOC;

   PTSETUP(&XLOC,&YLOC);
   PTXTICS(XLOC,YLOC);
   PTYTICS(XLOC,YLOC);
   return;
   }

/************************************************************
*
* Function for setting up values for tic marks
*
*/
void PTSETUP(X,Y)
short *X, *Y;
   {
   double N, XP, YP;
   short IPARM, ILFLG, DSFLG, TBFLGY, TBFLGT, IOFLG, IGRID;
   short XLOC, YLOC, I;
   double YY, DELTA, V1T, V2T, V1Y, V2Y, V, XX;
   short BLENY=0, BLENT=0;
   short IDAT;

   I = fabs(PARMS[9]);
   IITA = I/1000;
   I %= 1000;
   IIYA = I/100;
   I %= 100;
   ITV = I/10;
   IYV = I%10;

   if (TMAJOR[1] < 0)
      {
      N = floor(log10(TRANGE[1] - TRANGE[0]));
      N = pow(10.,N);
      I = ((TRANGE[1] - TRANGE[0])/N + .5);
      TMAJOR[1] = LUTABLE[I]*N/10.;
      TMAJOR[0] = TRANGE[1] - fabs(fmod(TRANGE[1],TMAJOR[1]));
      if (PARMS[5])
         {
         TMAJOR[1] = 1;
         TMAJOR[0] = pow(10.,floor(PLOG(TMAJOR[0],5)));
         }
      }

   if (YMAJOR[1] < 0)
      {
      N = floor(log10(YRANGE[1] - YRANGE[0]));
      N = pow(10.,N);
      I = ((YRANGE[1] - YRANGE[0])/N + .5);
      YMAJOR[1] = LUTABLE[I]*N/10.;
      YMAJOR[0] = YRANGE[1] - fabs(fmod(YRANGE[1],YMAJOR[1]));
      if (PARMS[6])
         {
         YMAJOR[1] = 1;
         YMAJOR[0] = pow(10.,floor(PLOG(YMAJOR[0],6)));
         }
      }

   if ((TMAJOR[0] < TRANGE[0]) || (TMAJOR[0] > TRANGE[1]))
      TMAJOR[1] = 0.;
   if ((YMAJOR[0] < YRANGE[0]) || (YMAJOR[0] > YRANGE[1]))
      YMAJOR[1] = 0.;

   XROT = 90;
   if (PARMS[1] >= 0)
      {
      IPARM = PARMS[1];
      IGRID = IPARM/1000;
      IPARM %= 1000;
      IOFLG = IPARM/100;
      IPARM %= 100;
      DSFLG = IPARM/10;
      IPARM %= 10;
      TBFLGT = IPARM;
      if (TMAJOR[1])
         {
         if (!TBFLGT) /* Set WINDOW According to the Side Chosen */
            {
            YLOC = W1; 
            if (!ITV) W1 += (CHEIGHT + CHEIGHT/2);
            if (IOFLG)
               {
               W1 += XTICBASE;
               if (!DSFLG) W3 -= XTICBASE;
               }
            }
         else
            {
            if (!ITV)
               {
               YLOC = (W3 -= CHEIGHT);
               W3 -= CHEIGHT/2;
               }
            if (IOFLG)
               {
               W3 -= XTICBASE;
               if (!DSFLG) W1 += XTICBASE;
               }
            }
         }

      if (PARMS[5])       /* Log T Axis */
         {
         V1T = PLOG(TRANGE[0],5);
         V2T = PLOG(TRANGE[1],5);
         if (TMAJOR[0] > 0) TVT = PLOG(TMAJOR[0],5);
/* 
** TMAJOR[1] now represents an exponent which is
** the seperation of the major tic marks in log space.
** NOTE: PARMS[5] is now log(P5)
*/
         TDELTA = exp(PARMS[5]*TMAJOR[1])/(double)(TMINOR);
         TMINOR -= 2;
         }
      else
         {
         V1T = TRANGE[0];
         V2T = TRANGE[1];
         TVT = TMAJOR[0];
         TDELTA = TMAJOR[1]/(double)(TMINOR+1);
         }

      if (TMAJOR[1] && ITV)
         {
         for (XX=TVT;XX >= V1T;XX-=TMAJOR[1])
            {
            CHKBRK();
            if (PARMS[5])
               XP = exp(XX*PARMS[5]);
            else
               XP = XX;
            sprintf(BUFFER,TFORMAT,XP);
            BLENT = Max(strlen(BUFFER)*CWIDTH,BLENT);
            }
         for (XX=TVT;XX <= V2T;XX+=TMAJOR[1])
            {
            CHKBRK();
            if (PARMS[5])
               XP = exp(XX*PARMS[5]);
            else
               XP = XX;
            sprintf(BUFFER,TFORMAT,XP);
            BLENT = Max(strlen(BUFFER)*CWIDTH,BLENT);
            }
         }
      else
         XROT = 0;
      }

   YROT = 0;
   if (PARMS[2] >= 0)
      {
      IPARM = PARMS[2];
      IGRID = IPARM/1000;
      IPARM %= 1000;
      IOFLG = IPARM/100;
      IPARM %= 100;
      DSFLG = IPARM/10;
      IPARM %= 10;
      TBFLGY = IPARM;
      if (YMAJOR[1])
         {
         if (!TBFLGY)
            {
            XLOC = W0;
            if (IYV)
               {
               XLOC = (W0 += CHEIGHT);
               W0 += CHEIGHT/2;
               }
            if (IOFLG)
               {
               W0 += YTICBASE;
               if (!DSFLG) W2 -= YTICBASE;
               }
            }
         else
            {
            XLOC = W2;
            if (IYV) W2 -= (CHEIGHT + CHEIGHT/2);
            if (IOFLG)
               {
               W2 -= YTICBASE;
               if (!DSFLG) W0 += YTICBASE;
               }
            }
         }
      if (PARMS[6])
         {
         V1Y = PLOG(YRANGE[0],6);
         V2Y = PLOG(YRANGE[1],6);
         if (YMAJOR[0] > 0) YVT = PLOG(YMAJOR[0],6);
         YDELTA = exp(PARMS[6]*YMAJOR[1])/(double)(YMINOR);
         YMINOR -= 2;
         }
      else
         {
         V1Y = YRANGE[0];
         V2Y = YRANGE[1];
         YVT = YMAJOR[0];
         YDELTA = YMAJOR[1]/(double)(YMINOR+1);
         }

      if (YMAJOR[1] && !IYV)
         {
         for (YY=YVT;YY >= V1Y;YY-=YMAJOR[1])
            {
            CHKBRK();
            if (PARMS[6]) YP = exp(YY*PARMS[6]); else YP = YY;
            sprintf(BUFFER,YFORMAT,YP);
            BLENY = Max(strlen(BUFFER)*CWIDTH,BLENY);
            }
         for (YY=YVT;YY <= V2Y;YY+=YMAJOR[1])
            {
            CHKBRK();
            if (PARMS[6]) YP = exp(YY*PARMS[6]); else YP = YY;
            sprintf(BUFFER,YFORMAT,YP);
            BLENY = Max(strlen(BUFFER)*CWIDTH,BLENY);
            }
         }
      else
         YROT = 90;
      }

   if (TBFLGT && ITV)
      {
      YLOC = (W3 -= BLENT);
      W3 -= CHEIGHT/2;
      }
   else
      W1 += BLENT;

   if (TBFLGY && !IYV)
      {
      XLOC = (W2 -= BLENY);
      W2 -= CHEIGHT/2;
      }
   else
      W0 += BLENY;

   TSLOPE = ((double)(W2 - W0))/(V2T - V1T);
   TINTER = (double)W0 - TSLOPE*V1T;

   YSLOPE = ((double)(W3 - W1))/(V2Y - V1Y);
   YINTER = (double)W1 - YSLOPE*V1Y;

   *X = XLOC;
   *Y = YLOC;

   return;
   }

/************************************************************
*
* X tic Marks
*
*/
void PTXTICS(XLOC,YLOC)
short XLOC,YLOC;
   {
   double X, V1, V2, XP, V;
   short XL, TBFLG, DSFLG, IOFLG, IPARM, I, BLEN;
   short IDAT, HILAB, LOLAB, IGRID;
   char C;

   if (PARMS[1] >= 0)
      {
      IPARM = PARMS[1];
      IGRID = IPARM/1000;
      IPARM %= 1000;
      IOFLG = IPARM/100;
      IPARM %= 100;
      DSFLG = IPARM/10;
      IPARM %= 10;
      TBFLG = IPARM;
      HILAB = (short)PARMS[7]/10;
      LOLAB = (short)PARMS[7]%10;
      if ((DSFLG) && (!TBFLG)) DSFLG = 1;
      else if ((DSFLG) && (TBFLG)) DSFLG = -1;
      if (!IOFLG) IOFLG = XTICBASE; else IOFLG = -XTICBASE;

      if (TMAJOR[1])
         {       
         for (X=TVT,XL=X*TSLOPE+TINTER;XL <= W2;
              X+=TMAJOR[1],XL=X*TSLOPE+TINTER)
            {
            CHKBRK();
            if (PARMS[5]) XP = exp(X*PARMS[5]); else XP = X;
            if (DSFLG >= 0)
               LINE(Tpnt(XL),W1,Tpnt(XL),W1+IOFLG);
            if (DSFLG <= 0)
               LINE(Tpnt(XL),W3,Tpnt(XL),W3-IOFLG);
            if (IGRID)
               LINE(Tpnt(XL),W1,Tpnt(XL),W3);
            sprintf(BUFFER,TFORMAT,XP);
            if (!ITV)
               BLEN = strlen(BUFFER)*CWIDTH/2;
            else
               BLEN = CHEIGHT/2;

            if ((((abs(XL-W2)<BLEN) && (HILAB)) ||
                  (abs(XL-W2)>BLEN))            &&
                (((abs(XL-W0)<BLEN) && (LOLAB)) ||
                  (abs(XL-W0)>BLEN)))
               PLTALPHA(BUFFER,
                        (ITV ? Tpnt(XL) + BLEN : Tpnt(XL) - BLEN),
                        YLOC,XROT);

            for (I=1;I<=TMINOR;++I)
               {
               if (PARMS[5])
                  XL = PLOG(XP*(1+I*TDELTA),5)*TSLOPE+TINTER;
               else
                  XL = (X+I*TDELTA)*TSLOPE+TINTER;
               if (XL > W2) break;
               if (DSFLG >= 0)
                  LINE(Tpnt(XL),W1,Tpnt(XL),W1+IOFLG/2);
               if (DSFLG <= 0)
                  LINE(Tpnt(XL),W3,Tpnt(XL),W3-IOFLG/2);
               if (IGRID)
                  LINE(Tpnt(XL),W1,Tpnt(XL),W3);
               }
            }

         for (X=TVT,XL=X*TSLOPE+TINTER;XL >= W0;
              X-=TMAJOR[1],XL=X*TSLOPE+TINTER)
            {
            CHKBRK();
            if (PARMS[5]) XP = exp(X*PARMS[5]); else XP = X;
            if (DSFLG >= 0)
               LINE(Tpnt(XL),W1,Tpnt(XL),W1+IOFLG);
            if (DSFLG <= 0)
               LINE(Tpnt(XL),W3,Tpnt(XL),W3-IOFLG);
            if (IGRID)
               LINE(Tpnt(XL),W1,Tpnt(XL),W3);
            sprintf(BUFFER,TFORMAT,XP);
            if (!ITV)
               BLEN = strlen(BUFFER)*CWIDTH/2;
            else
               BLEN = CHEIGHT/2;
            if ((((abs(XL-W2)<BLEN) && (HILAB)) ||
                  (abs(XL-W2)>BLEN))            &&
                (((abs(XL-W0)<BLEN) && (LOLAB)) ||
                  (abs(XL-W0)>BLEN)))
               PLTALPHA(BUFFER,
                        (ITV ? Tpnt(XL) + BLEN : Tpnt(XL) - BLEN),
                        YLOC,XROT);

            for (I=1;I<=TMINOR;++I)
               {
               if (PARMS[5])  /* Start at one down from X*/
                  {
                  V = (exp(PARMS[5]*(X-TMAJOR[1])))*(1+I*TDELTA);
                  XL = PLOG(V,5)*TSLOPE+TINTER;
                  }
               else
                  XL = (X-I*TDELTA)*TSLOPE+TINTER;
               if (XL > W0) /* Decades come in back door */
                  {
                  if (DSFLG >= 0)
                     LINE(Tpnt(XL),W1,Tpnt(XL),W1+IOFLG/2);
                  if (DSFLG <= 0)
                     LINE(Tpnt(XL),W3,Tpnt(XL),W3-IOFLG/2);
                  if (IGRID)
                     LINE(Tpnt(XL),W1,Tpnt(XL),W3);
                  }
               }
            }
         }
      }
   return;
   }

/************************************************************
*
* Y tic Marks
*
*/
void PTYTICS(XLOC,YLOC)
short XLOC,YLOC;
   {
   double Y, YP, V, ROTATION;
   short YL, TBFLG, DSFLG, IOFLG, IPARM, I, BLEN;
   short IDAT, HILAB, LOLAB, IGRID;
   char C;

   if (PARMS[2] >= 0)
      {
      IPARM = PARMS[2];
      IGRID = IPARM/1000;
      IPARM %= 1000;
      IOFLG = IPARM/100;
      IPARM %= 100;
      DSFLG = IPARM/10;
      IPARM %= 10;
      TBFLG = IPARM;
      HILAB = (short)PARMS[8]/10;
      LOLAB = (short)PARMS[8]%10;
      if ((DSFLG) && (!TBFLG))
         DSFLG = 1;
      else if ((DSFLG) && (TBFLG))
         DSFLG = -1;
      if (!IOFLG)
         IOFLG = YTICBASE;
      else
         IOFLG = -YTICBASE;

      if (YMAJOR[1])
         {
         for (Y=YVT,YL=Y*YSLOPE+YINTER;YL <= W3;
              Y+=YMAJOR[1],YL=Y*YSLOPE+YINTER)
            {
            CHKBRK();
            if (PARMS[6]) YP = exp(Y*PARMS[6]); else YP = Y;
            if (DSFLG >= 0)
               LINE(W0,Ypnt(YL),W0+IOFLG,Ypnt(YL));
            if (DSFLG <= 0)
               LINE(W2,Ypnt(YL),W2-IOFLG,Ypnt(YL));
            if (IGRID)
               LINE(W0,Ypnt(YL),W2,Ypnt(YL));
            sprintf(BUFFER,YFORMAT,YP);
            if (IYV)
               BLEN = strlen(BUFFER)*CWIDTH/2;
            else
               BLEN = CHEIGHT/2;
            if ((((abs(YL-W3)<BLEN) && (HILAB)) ||
                  (abs(YL-W3)>BLEN))            &&
                (((abs(YL-W1)<BLEN) && (LOLAB)) ||
                  (abs(YL-W1)>BLEN)))
               PLTALPHA(BUFFER,XLOC,Ypnt(YL) - BLEN,YROT);
            for (I=1;I<=YMINOR;++I)
               {
               if (PARMS[6])
                  YL = PLOG(YP*(1+I*YDELTA),6)*YSLOPE+YINTER;
               else
                  YL = (Y+I*YDELTA)*YSLOPE+YINTER;
               if (YL > W3) break;
               if (DSFLG >= 0)
                  LINE(W0,Ypnt(YL),W0+IOFLG/2,Ypnt(YL));
               if (DSFLG <= 0)
                  LINE(W2,Ypnt(YL),W2-IOFLG/2,Ypnt(YL));
               if (IGRID)
                  LINE(W0,Ypnt(YL),W2,Ypnt(YL));
               }
            }

         for (Y=YVT,YL=Y*YSLOPE+YINTER;YL >= W1;
              Y-=YMAJOR[1],YL=Y*YSLOPE+YINTER)
            {
            CHKBRK();
            if (PARMS[6]) YP = exp(Y*PARMS[6]); else YP = Y;
            if (DSFLG >= 0)
               LINE(W0,Ypnt(YL),W0+IOFLG,Ypnt(YL));
            if (DSFLG <= 0)
               LINE(W2,Ypnt(YL),W2-IOFLG,Ypnt(YL));
            if (IGRID)
               LINE(W0,Ypnt(YL),W2,Ypnt(YL));
            sprintf(BUFFER,YFORMAT,YP);

            if (IYV)
               BLEN = strlen(BUFFER)*CWIDTH/2;
            else
               BLEN = CHEIGHT/2;

            if ((((abs(YL-W3)<BLEN) && (HILAB)) ||
                  (abs(YL-W3)>BLEN))            &&
                (((abs(YL-W1)<BLEN) && (LOLAB)) ||
                  (abs(YL-W1)>BLEN)))
               PLTALPHA(BUFFER,XLOC,Ypnt(YL) - BLEN,YROT);

            for (I=1;I<=YMINOR;++I)
               {
               if (PARMS[6])
                  {
                  V = (exp(PARMS[6]*(Y-YMAJOR[1])))*(1+I*YDELTA);
                  YL = PLOG(V,6)*YSLOPE+YINTER;
                  }
               else
                  YL = (Y-I*YDELTA)*YSLOPE+YINTER;

               if (YL > W1) /* Decades come in back door */
                  {
                  if (DSFLG >= 0)
                     LINE(W0,Ypnt(YL),W0+IOFLG/2,Ypnt(YL));
                  if (DSFLG <= 0)
                     LINE(W2,Ypnt(YL),W2-IOFLG/2,Ypnt(YL));
                  if (IGRID)
                     LINE(W0,Ypnt(YL),W2,Ypnt(YL));
                  }
               }
            }
         }
      }
   return;
   }

/************************************************************
*
* Subroutine to Plot Alpha Numberics
*
*/
void PLTALPHA(LABEL,XLOC,YLOC,ANGLE)
char *LABEL;
short XLOC, YLOC, ANGLE;
   {
   double XFL, YFL, FANG;
   short LENGTH;

   if (!(LENGTH = strlen(LABEL)));

   FANG = (double)ANGLE;
   XFL = (double)XLOC/1000.;
   YFL = (double)YLOC/1000.;
   fprintf(OUTSTR,SFORMAT,"TEXT");
   fprintf(OUTSTR,SFORMAT,"8");
   fprintf(OUTSTR,DFORMAT,COLOR);       /* Layer Name */
   fprintf(OUTSTR,SFORMAT,"38");
   fprintf(OUTSTR,FFORMAT,POINT[0]);    /* Z1 */
   fprintf(OUTSTR,SFORMAT,"10");
   fprintf(OUTSTR,FFORMAT,XFL);    /* Insertion Point */
   fprintf(OUTSTR,SFORMAT,"20");
   fprintf(OUTSTR,FFORMAT,YFL);    /* Insertion Point */
   fprintf(OUTSTR,SFORMAT,"40");
   fprintf(OUTSTR,SFORMAT,"0.2");  /* Text Height */
   fprintf(OUTSTR,SFORMAT,"1");
   fprintf(OUTSTR,SFORMAT,LABEL);    /* Text */
   fprintf(OUTSTR,SFORMAT,"50");
   fprintf(OUTSTR,FFORMAT,FANG);    /* Rotation */
   fprintf(OUTSTR,SFORMAT,"7");
   fprintf(OUTSTR,SFORMAT,"SIMPLEX");
   fprintf(OUTSTR,SFORMAT,"0");
   return;
   }

/************************************************************
*
* Find the MAX, MIN of a File
*
*/
short GETRNG(YMAX,YMIN,TMAX,TMIN,INSTR,FHP,NotFirstCall)
double *YMAX, *YMIN, *TMIN, *TMAX;
FILE *INSTR;
struct FILEHDR *FHP;
int NotFirstCall;
   {
   short ERRFLAG=0;

   TCNT = 0.;
   while (Zread(INSTR,BUFFER1,FHP->type))
      {
      switch (FHP->type)
         {
         case R_Data:
            TIME = TCNT * FHP->m + FHP->b;
            ++TCNT;
            DATA = RDataPntr1->y;
            FLAG = RDataPntr1->f;
            break;
         case TR_Data:
            TIME = TRDataPntr1->t;
            DATA = TRDataPntr1->y;
            break;
         case X_Data:
            TIME = TCNT * FHP->m + FHP->b;
            ++TCNT;
            DATA = cabs(XDataPntr1->z);
            FLAG = XDataPntr1->f;
            break;
         case TX_Data:
            TIME = TXDataPntr1->t;
            DATA = cabs(TXDataPntr1->z);
            break;
         }

      if (((TIME >= TRANGE[0]) && (TIME <= TRANGE[1])) ||
           (TRANGE[0] >= TRANGE[1]))
         {
         if (!FLAG)
            {
            if (!NotFirstCall)
               {
               *YMIN = *YMAX = DATA;
               *TMAX = *TMIN = TIME;
               NotFirstCall = 1;
               }
            else
               {
               *YMAX = Max(DATA,*YMAX);
               *YMIN = Min(DATA,*YMIN);
               *TMAX = Max(TIME,*TMAX);
               *TMIN = Min(TIME,*TMIN);
               }
            }
         }
      }

   if (ferror(INSTR))
      {
      Zerror();
      ERRFLAG = 1;
      }

   return(ERRFLAG);
   }

/************************************************************
*
* Plot a Symbol
*
*/
void PLTSYM(FXLOC,FYLOC)
double FXLOC, FYLOC;
   {
   char C[2];
   short XLOC, YLOC;

   if ((FXLOC < (double)SCLIPXL) ||
       (FYLOC < (double)SCLIPYL) ||
       (FXLOC > (double)SCLIPXH) ||
       (FYLOC > (double)SCLIPYH)) return;

   XLOC = (short)(FXLOC);
   YLOC = (short)(FYLOC);
   LINE(XLOC,YLOC,XLOC,YLOC);    /* Place a node at the data point */
   XLOC = (short)(FXLOC-85.8);
   YLOC = (short)(FYLOC-86.0);
   C[0] = (char)fabs(PARMS[3]);
   C[1] = (char)0;
   if (C[0] != (char)255)
      PLTALPHA(C,XLOC,YLOC,0);
   return;
   }

/***************************************************************
**
** Take LOG base PRAMS[5] or PARMS[6]
*/
double PLOG(V,B)
double V;
short B;
   {
   V = log(V)/PARMS[B];
   return(V);
   }

/***************************************************************
**
** Vector Clipping Routine
*/
void VECTOR(X1,Y1,X2,Y2,F)
double X1, X2, Y1, Y2;
short F;
   {
   short VFLAG=0, HFLAG=0, FL=0;
   double M, B, ZXL, ZXH, ZYL, ZYH;
   static double LASTX, LASTY;

   if (F)
      {
      X1=LASTX;
      Y1=LASTY;
      }

   LASTX = X2;
   LASTY = Y2;

   if ((X2 != X1) && (Y2 != Y1))
      {
      M = (Y2-Y1)/(X2-X1);
      B = Y1 - M*X1;
      ZXL=M*(double)SCLIPXL+B;
      ZXH=M*(double)SCLIPXH+B;
      ZYL=((double)SCLIPYL-B)/M;
      ZYH=((double)SCLIPYH-B)/M;
      }

   if (X2 == X1) VFLAG = 1;

   if (Y2 == Y1) HFLAG = 1;

   if (X1 < (double)SCLIPXL)
      {
      if (VFLAG) return;
      X1 = (double)SCLIPXL;
      if (!HFLAG) Y1 = ZXL;
      FL=1;
      }
   else if (X1 > (double)SCLIPXH)
      {
      if (VFLAG) return;
      X1 = (double)SCLIPXH;
      if (!HFLAG) Y1 = ZXH;
      FL=1;
      }
   if (X2 < (double)SCLIPXL)
      {
      X2 = (double)SCLIPXL;
      if (!HFLAG) Y2 = ZXL;
      FL=1;
      }
   else if (X2 > (double)SCLIPXH)
      {
      X2 = (double)SCLIPXH;
      if (!HFLAG) Y2 = ZXH;
      FL=1;
      }

   if (Y1 < (double)SCLIPYL)
      {
      if (HFLAG) return;
      Y1 = (double)SCLIPYL;
      if (!VFLAG) X1 = ZYL;
      FL=1;
      }
   else if (Y1 > (double)SCLIPYH)
      {
      if (HFLAG) return;
      Y1 = (double)SCLIPYH;
      if (!VFLAG) X1 = ZYH;
      FL=1;
      }
   if (Y2 < (double)SCLIPYL)
      {
      Y2 = (double)SCLIPYL;
      if (!VFLAG) X2 = ZYL;
      FL=1;
      }
   else if (Y2 > (double)SCLIPYH)
      {
      Y2 = (double)SCLIPYH;
      if (!VFLAG) X2 = ZYH;
      FL=1;
      }

   if (((X1<(double)SCLIPXL) || (X1>(double)SCLIPXH)  ||
        (X2<(double)SCLIPXL) || (X2>(double)SCLIPXH)  ||
        (Y1<(double)SCLIPYL) || (Y1>(double)SCLIPYH)  ||
        (Y2<(double)SCLIPYL) || (Y2>(double)SCLIPYH)) ||
       ((X1 == X2) && (Y1 == Y2) && (FL == 1))) return;

   LINE((short)X1,(short)Y1,(short)X2,(short)Y2);

   return;
   }

/********************************************
*
* Line drawing Primitive
*
*/
void LINE(X1,Y1,X2,Y2)
short X1,Y1,X2,Y2;
   {
   double FX1, FX2, FY1, FY2;

   FX1 = (double)X1/1000.;
   FX2 = (double)X2/1000.;
   FY1 = (double)Y1/1000.;
   FY2 = (double)Y2/1000.;

   if ((X1==X2) && (Y1==Y2))
      {
      fprintf(OUTSTR,SFORMAT,"POINT");
      fprintf(OUTSTR,SFORMAT,"8");
      fprintf(OUTSTR,DFORMAT,COLOR);       /* Layer Name */
      if (CODE)   /* 3D Point */
         {
         fprintf(OUTSTR,SFORMAT,"38");
         fprintf(OUTSTR,FFORMAT,POINT[0]);    /* Z1 */
         }
      fprintf(OUTSTR,SFORMAT,"10");
      fprintf(OUTSTR,FFORMAT,FX1);      /* X1 */
      fprintf(OUTSTR,SFORMAT,"20");
      fprintf(OUTSTR,FFORMAT,FY1);      /* Y1 */
      fprintf(OUTSTR,SFORMAT,"0");
      }
   else
      {
      if (CODE)
         {
         fprintf(OUTSTR,SFORMAT,"3DLINE");
         fprintf(OUTSTR,SFORMAT,"30");
         fprintf(OUTSTR,FFORMAT,POINT[0]);    /* Z1 */
         fprintf(OUTSTR,SFORMAT,"31");
         fprintf(OUTSTR,FFORMAT,POINT[0]);    /* Z2 */
         }
      else
         fprintf(OUTSTR,SFORMAT,"LINE");

      fprintf(OUTSTR,SFORMAT,"8");
      fprintf(OUTSTR,DFORMAT,COLOR);       /* Layer Name */
      fprintf(OUTSTR,SFORMAT,"10");
      fprintf(OUTSTR,FFORMAT,FX1);      /* X1 */
      fprintf(OUTSTR,SFORMAT,"20");
      fprintf(OUTSTR,FFORMAT,FY1);      /* Y1 */
      fprintf(OUTSTR,SFORMAT,"11");
      fprintf(OUTSTR,FFORMAT,FX2);     /* X2 */
      fprintf(OUTSTR,SFORMAT,"21");
      fprintf(OUTSTR,FFORMAT,FY2);     /* Y2 */
      fprintf(OUTSTR,SFORMAT,"0");
      }
   return;
   }

/***************************************************************
**
** Check the ^C Interrupt Flag
*/
void CHKBRK()
   {
   if (kbhit()) getch();
   return;
   }

/***************************************************************
**
** Process ^C Interrupt
*/
short BREAKREQ()
   {
   fcloseall();
   unlink(TMPFILE);
   Zexit(3);
   }
/*
** Trap Floating Point Error
*/
short FPEERROR()
   {
   fcloseall();
   unlink(TMPFILE);
   Zexit(1);
   }