/*  25 Jan 12.  WJS							*/
/*	Rename some variables whose names conflict w/some "built-in"	*/
/*    functions' names.  Conflict existed w/o diagnostic on gb6, but	*/
/*    gb11 issues warnings.  Renaming done via capitalization; other	*/
/*    similar variable names capitalized to keep "equality" of names	*/
/*  28 Jul 05.  WJS							*/
/*	Type main to avoid diagnostic					*/
/* 	include stdlib for exit defn					*/
/*	Explicitly exit w/status 0 under normal conditions		*/
/*	Define putbitmap						*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/*................................................................*/

   FILE *tek_file;
   FILE *bm_file;

   int    X1, Y1, X0, Y0, bm_counter;
   int    xoff[4], yoff[4], inext=0;
   char   delimiter, reduce, nplotsfrm;
   char   first_instruction, frame_flag, c1;
   char   infile[80], outfile[80];
   char   ESC=27, FF=12, US=31, GS=29;
   unsigned char  bitmap[1024*780/8];
   int lineoffset;
/*

   Global Variables:

   tek_file          -  Tektronix input file
   bm_file           -  Post Script output file
   frame_flag        -  whether or not frame has anything in it
   bm_counter        -  holds counter of Post Script points plotted
   first_instruction -  whether or not first instruction of the frame.
   inext             -  controls position of plot on the frame

*/

/*...................................................................*/


int main ( argc, argv )

int argc;
char *argv[];

{
   void Setup(),Initialization(),Scan_Tektronix_File(),Close_Files();
   Setup ( argc, argv );

   Initialization();

   Scan_Tektronix_File();

   Close_Files();

   exit(0);
}


void Usage_Note()

{
  fprintf ( stderr, "Usage: tekxbm [-options]  [infile [outfile]\n");
  fprintf ( stderr, "Options:\n" );
  fprintf ( stderr, "       -h    displays this message\n" );
  fprintf ( stderr, "       -d n  specifies character n as delimiter");
  fprintf ( stderr," (default=%d)\n", delimiter );
  fprintf ( stderr, "       -f n  specifies n plots per frame; n can only\n");
  fprintf ( stderr, "            be 1, 2 or 4" );
  fprintf ( stderr," (default=%d)\n", nplotsfrm );
  fprintf ( stderr, "       -r n  specifies reduction 1,2,4");
  fprintf ( stderr," (default=%d)\n", reduce );
}


void Setup ( argc, argv )

int  argc;
char *argv[];

{

   int  i;
   char *fin=NULL;
    char *fout=NULL;

   /*---- defaults for internal parameters ---*/
   delimiter = '%';
   nplotsfrm = 1;
   reduce = 2;
   i=1;

   while (i<argc){
     if (argv[i][0]=='-'){
       switch (argv[i][1]){
       case 'h': Usage_Note();exit(1);
       case 'd': delimiter = atoi ( argv[++i] );break;
       case 'f': nplotsfrm = atoi ( argv[++i] );break;
       case 'r': reduce  = atoi ( argv[++i] );break;
       default: Usage_Note();exit(1);
       };
     }
     else 
       {
	 if (fin == NULL) fin=argv[i];
	 else fout=argv[i];
       };
i++;
};


   switch ( nplotsfrm )
   {
      case 1:  break;

      case 2:  xoff[0] = 480+0; yoff[0] = 160+2048;
               xoff[1] = 480+0; yoff[1] = 160+   0;
               break;

      case 4:  xoff[0] = 160+1599; yoff[0] = 160+2048;
               xoff[1] = 160+1599; yoff[1] =      160;
               xoff[2] =      160; yoff[2] = 160+2048;
               xoff[3] =      160; yoff[3] =      160;
               break;

      case 7:  xoff[0] = 160+1599; yoff[0] = 160+2048;
               xoff[1] = 160+1599; yoff[1] =      160;
               xoff[2] =      160; yoff[2] = 160+2048;
               xoff[3] =      160; yoff[3] =      160;
               break;

      case 8:  xoff[0] = 160+1599; yoff[0] = 160+2048;
               xoff[1] = 160+1599; yoff[1] =      160;
               xoff[2] =      160; yoff[2] = 160+2048;
               xoff[3] =      160; yoff[3] =      160;
               break;

      case 9:  xoff[0] = 160+1599; yoff[0] = 160+2048;
               xoff[1] = 160+1599; yoff[1] =      160;
               xoff[2] =      160; yoff[2] = 160+2048;
               xoff[3] =      160; yoff[3] =      160;
               break;

      default:
               fprintf ( stderr,
                         "\ntekxbm: invalid option -f %d \n", nplotsfrm );
               exit(1);
               break;
   }


/* Open files */

   /*-------------- Tektronix File ---------------*/

   if (fin==NULL)tek_file=stdin;
   else if((tek_file = fopen ( fin, "r" ))== NULL )
	 {
	   fprintf ( stderr,
		    "\ntekxbm: cannot open Tektronix file %s\n", fin);
	   exit(1);
	 };
   if (fout==NULL)bm_file=stdout;
   else if((bm_file = fopen ( fout, "wb" ))== NULL )
	 {
	   fprintf ( stderr,
		    "\ntekxbm: cannot open bitmap file %s\n", fout);
	   exit(1);
	 };
}

void Close_Files()

{
   fclose ( tek_file );
   fclose (  bm_file );

}


void Scan_Tektronix_File()

/*
       This procedure scans the Tektronix file and plots it on the screen.

    Notes:  Not a 100% Tek 4014.
    -----   CR is ignored.
            ESC 8, 9, :, and ; (font size) not handled.
            FS and ESC FS (point plot mode and special point plot mode)
             not handled.
            RS (incremental plot mode) not implemented.

            Alpha mode stuff ignored.


Local parameters:
----------------

   graph_mode        -  indicates whether graphic mode or not
   pen_down          -  indicates whether pen is down or not
   after_low_y       -  indicates if current byte is after a low y
   hx / lx           -  high/low x
   hy / ly           -  high/low y
   lxy               -  low x y
   OneByte           -  byte being processed

*/


{

   char   graph_mode=0, pen_down=0, after_low_y=0;
   char   hx=0, lx=0, hy=0, ly=0, lxy=0;

   register int OneByte;
   register int  frame;
   void Plot(),End_Page();

   /*------------- initialize control parameters --------------*/
   bm_counter        = 0;
   frame             = 1;
   first_instruction = 1;


   /*--------------------  m a i n    l o o p  -------------------------*/
   while (  ( OneByte = getc ( tek_file ) ) != EOF )
   {

      if ( OneByte == ESC )                   /* Handles escape sequence */
      {

         OneByte = getc ( tek_file );         /* get next byte */

         if ( OneByte == FF )                 /* Clear screen */
         {

            End_Page();


            frame++;
                                              /* reset control parameters */
            frame_flag      = 0;
            pen_down          = 0;
            after_low_y       = 0;
            lxy               = 0;
            first_instruction = 1;

         }

      }

      else if ( ! graph_mode )                  /* text mode */
      {
          if ( OneByte == GS )                  /* switch to graph mode */
          {
             graph_mode  = 1;
             pen_down    = 0;
             after_low_y = 0;
          }

          else;                                /* Ignore text.  To included it
                                                  recall that OneByte is the
                                                  character to be written.  */

      }


      else                                      /* graph mode */
      {

         if ( OneByte == GS )
         {
              after_low_y = 0;
              pen_down    = 0;
         }

         else if ( OneByte == US )
         {
              after_low_y = 0;
              graph_mode  = 0;
         }
                                                /* Set High x / High y */

         else if ( ( OneByte >= 32 ) && ( OneByte <= 63 ) )
         {
              if ( after_low_y )  hx = OneByte - 32;
              else                hy = OneByte - 32;
              after_low_y = 0;
         }

                                                 /* Set low x */

         else if ( ( OneByte >= 64 ) && ( OneByte <= 95 ) )
         {
              lx = OneByte - 64;
              X0 = hx * 128 + lx * 4 + ( lxy &  3 );
              Y0 = hy * 128 + ly * 4 + ( lxy >> 2 );

              if ( pen_down ) Plot ( X0, Y0, 'L' );
              else
              {
                  Plot ( X0, Y0, 'M' );
                  pen_down = 1;
              }

              after_low_y = 0;
         }

                                             /* Set low y / extra byte */

         else if ( ( OneByte >= 96 ) && ( OneByte <= 127 ) )
         {
              if ( after_low_y ) lxy = ( ly & 15 );
              ly          = OneByte - 96;
              after_low_y = 1;
         }

      }

   }

   if ( inext != 0 )
   {
      inext      = 999;        /* to force end of page */
      frame_flag = 1;
   }
   End_Page();


}


void Initialization()

{
int i;
for(i=0;i<1024*780/8;i++)bitmap[i]=0;
lineoffset=1024/reduce/8;
}


void New_Page()

{
int i;
for(i=0;i<1024*780/8;i++)bitmap[i]=0;
}



void Plot ( XA, YA, com )

int   XA, YA;
char  com;

/*
    This procedure plots or move the pen depending on
     the value of com:

    xa, ya  --  Tektronix coordinates - range: [0,4095]
    com     --  command:  "M" - move to position xa, xb
                          "L" - draw line from previous position
                                 to xa, ya

    NOTE:  The bm_counter is related to the size of the printer
           buffer.  The value used (500) is ok for many printers
           (like Apple, NEC, TI, etc...)

*/


{

   int xa, ya;
   void line();

   switch ( nplotsfrm )         /* transform coordinates according to the
                                   number of plots per frame */
   {

   case 2:    xa = xoff[inext] + 0.64 *  XA ;
              ya = yoff[inext] + 0.64 *  YA ;
              break;

   case 4:    xa = xoff[inext] + 0.5 * ( YA );
              ya = yoff[inext] + 0.5 * ( 4096 - XA );
              break;

   case 7:    xa = xoff[inext] + 1.024 * ( YA - 1600) + 800.;
              ya = yoff[inext] + 0.8 * ( 2048 - XA) + 1024.;
              break;

   case 8:    xa = xoff[inext] + 1.28 * ( YA - 1600) + 800.;
              ya = yoff[inext] + 1. * ( 2048 - XA) + 1024.;
              break;

   case 9:    xa = xoff[inext] + 1.6 * ( YA - 1600) + 800.;
              ya = yoff[inext] + 1.25 * ( 2048 - XA) + 1024.;
              break;

   default:
              xa = XA;             
              ya = 3120 - YA;
              break;
   }



   if ( ! frame_flag )
   {
       if ( first_instruction )     /* consider only frames with more
                                        than 1 instruction */
       {
          X1 = xa;
          Y1 = ya;
          c1 = com;
          first_instruction = 0;
       }
       else
       {
          New_Page();
          if ( com == 'L' ) line ( X1, Y1, xa, ya );
          X1 = xa;
          Y1 = ya;
          frame_flag = 1;
       }
   }

   else   /* third or later instruction */
   {
    if ( com == 'L' ) line ( X1, Y1, xa, ya );
    X1 = xa;
    Y1 = ya;
   }

}  /* end of Plot */



void End_Page()

{
int putbitmap();	/* in tekgif.c */
int i,j;
   if ( frame_flag )
   {
      inext++;
      if ( inext >= nplotsfrm )
	inext=putbitmap(bm_file,bitmap,1024/reduce,780/reduce);
   }
}

void line ( X1, Y1, X2, Y2 )
int    X1, Y1, X2, Y2;

/* Draw line using Bresenham's algorithm */

{
   register  int  t, dist;
             int  xerr=0, yerr=0, dx, dy;
             int  incx, incy;
   static int bits[]={128,64,32,16,8,4,2,1};

   /* compute distance in both directions */
   X1=X1/4/reduce;
   X2=X2/4/reduce;
   Y1=Y1/4/reduce;
   Y2=Y2/4/reduce;

   dx = X2 - X1;
   dy = Y2 - Y1;

   /* compute direction of the increment,
      an increment of 0 means either a vertical or
      horizontal line. */

   if       ( dx>0 ) incx =  1;
   else if ( dx==0 ) incx =  0;
   else              incx = -1;

   if      ( dy>0  ) incy =  1;
   else if ( dy==0 ) incy =  0;
   else              incy = -1;

   /* determine which distance is greater */
   dx = abs ( dx );
   dy = abs ( dy );
   if ( dx > dy ) dist = dx;
   else           dist = dy;

   /* draw the line */
   for ( t = 0; t<=dist+1; t++ )
   {
     bitmap[X1/8+lineoffset*(Y1)] = 
       bitmap[X1/8+lineoffset*(Y1)] | bits[X1%8];
      xerr += dx;
      yerr += dy;
      if ( xerr > dist )
      {
         xerr -= dist;
         X1   += incx;
      }
      if ( yerr > dist )
      {
         yerr -= dist;
         Y1   += incy;
      }
   }
}

/* ---------------------------------------------------------------------- */
