/* *********************************************************************
  This programm reads and executes tektronix graphics
  from the named pipe tek.pipe
  the graphic cursor is send to /tmp/gcursor
 *********************************************************************** */

#include <sys/types.h>
#include <sys/stat.h>

#include <stdio.h>
#include <auxcfg.h>
#include <spec.h>


#define _TEKXMAX 4096
#define _TEKYMAX 3120
#define TMPGCURSOR   "/tmp/gcursor"


int   cx,cy,cb1,cb2,
      esc,fdstdin,fdstdout,
      ink=2,
       opt=1,
       prt_passes=2,
       prt_lsbmsb=1,
       x_prt_siz=1024,
       y_prt_siz=1024,
       aposx=0,
       aposy=0,
       fdprinter=0,
       pribufptr=0,
       pribufsiz=8190,
      paper=0,
      ptr=0,
      tekptr=0,
      bufsiz=200000,
      tekbufsiz=8192,     
      nohco=FALSE,
      msizex=3,
      msizey=3,
      sizex=3,
      sizey=3,
      sizex_1, sizey_1,
      sizex_2, sizey_2,
      thickx=1,
      thicky=1,
      txtangle=0,
      sinphi=0,
      cosphi=262144,
      gramode=0,
      flg_half=FALSE,
      hcothick=FALSE,
      bufferonfile=FALSE;

int            fdbuffer, fdptr;
unsigned char  lastchar;

unsigned char  *tekname,
                prt_init[80]="\x1B@",
                prt_gra[80]="\x1BZ",
                prt_halflf[80]="\x1B\x33\x02\n",
                prt_lf[80]="\x1B\x33\x14\n",
                prt_fin[80]="\x1B@\x0C",
                *primaryfont,
                *secondaryfont,
                *defaultprinter,
                *systemcommand,
                *bufferfile,
              *buf,
              *printerbuf,
              *tekbuf,
              *font_1,
              *fontdesc_1,
              *font_2,
              *fontdesc_2,
              *fontfile, *fontdesc;

int            *prop_1,
               fontwidth_1, fontheight_1,
               firstchar_1, offschar_1,
               *prop_2,
               fontwidth_2, fontheight_2,
               firstchar_2, offschar_2,
               *proptab,
               fontwidth, fontheight,
               firstchar, offschar;

int            prop_flag = 1;
int            baseline = 0;

help()
{
printf("This is the server, which reads the named pipe for tektronix\n");
printf("Vector grafic, and draws this grafic at the specified window\n");
printf("call it like:\n(xterm -t -e tekdaemon [-p n])&\n");
printf("optional parameters:\n");
printf("    -p n         specifies a number for the pipe.\n");
printf("    -buf n       change size of vector buffer(used for hardcopy)\n");
printf("            The Vectorbuffer may also be specified in Aux_Config\n");
printf("    -nohco       display only, no buffer for hardcopy\n");
}


teknewopen()
{
int   n,i,m,_tek4014;
char  c,s[80],z[80];


   strcpy(s,"gfx");
   c=_tekpipe+48;
   z[0]=c; z[1]=0;
   strcat(s,z);
   _tek4014=auxopen(s); /* _tekpipe is defined in spec.h */
   strcpy(tekname,auxparams[0]);
   if(_tek4014 > 0) { /* other programm active */
      fprintf(stderr,"tekdaemon: graphic pipe >%s< allready exists\n",tekname);
      fprintf(stderr,"you should delete it, before you try next time\n");
      sleep(2);
      if(!nohco) free(buf); free(tekbuf);
      exit(0);
   }
   strcpy(primaryfont,auxparams[1]);
   sizex_1 = atoi(auxparams[2]);
   sizey_1 = atoi(auxparams[3]);
   sizex = sizex_1; sizey = sizey_1;
   msizex = sizex; msizey = sizey;
   strcpy(secondaryfont,auxparams[4]);
   sizex_2 = atoi(auxparams[5]);
   sizey_2 = atoi(auxparams[6]);
   strcpy(bufferfile,auxparams[7]);
   if(bufferfile[0] > '9') {
      bufferonfile = TRUE;
   } else {
      bufferonfile = FALSE;
      bufsiz = atoi(bufferfile);
   }
   strcpy(defaultprinter,auxparams[8]);

   mknod(tekname,S_IFIFO | S_IROTH |S_IWOTH | S_IRUSR | S_IWUSR,0);
   sprintf(s,"chmod a+rw \"%s\"",tekname); system(s);
   _tek4014 = open(tekname,2);
   return(_tek4014);
}


main(argc,argv)
int argc;
char *argv[];
{
int  i,j,n,m,fd,fd2,nohco,ioctlarg;
char c,s[256],z[8192];
char *env;

  if(checkopt(argc,argv,"-dummy",z)) printf("(C) Rainer Kowallik\n");

  esc=FALSE;
  fdstdin=fileno(stdin); /* may cause trouble when porting ! then you will */
  fdstdout=fileno(stdout); /* have to find the filedescriptor by yourself */

  bufsiz=200000;
  env = (char *) getenv("TEKBUFSIZ");
  if(env != NULL) bufsiz = atoi(env);

  tekbufsiz=8192;
  nohco=FALSE;

   tekname = (unsigned char *) malloc(80);
   primaryfont = (unsigned char *) malloc(80);
   secondaryfont = (unsigned char *) malloc(80);
   defaultprinter = (unsigned char *) malloc(80);
   systemcommand = (unsigned char *) malloc(80);
   bufferfile = (unsigned char *) malloc(80);

  fd=teknewopen();
   if(checkopt(argc,argv,"-buf",z)) {
      strcpy(bufferfile,z);
      if(bufferfile[0] > '9') {
         bufferonfile = TRUE;
      } else {
         bufferonfile = FALSE;
         bufsiz = atoi(bufferfile);
      }
   }

   if(checkopt(argc,argv,"-nohco",z)) nohco=TRUE;

   if(bufferonfile) {
      fdbuffer = creat(bufferfile,0666);
      close(fdbuffer);
      fdbuffer = open(bufferfile,2,0666);
   } else {
      if(bufsiz < 1024) {
         nohco = TRUE;
      } else {
         if(!nohco) buf = (unsigned char *)malloc(bufsiz+10);
      }
   }


   font_1 = (unsigned char *) malloc(16384);
   font_2 = (unsigned char *) malloc(16384);
   prop_1 = (int *) calloc(256,sizeof(int));
   prop_2 = (int *) calloc(256,sizeof(int));

   fontfile = font_2; proptab = prop_2;
   readfont(secondaryfont);
   fontdesc_2 = fontdesc;
   fontheight_2 = fontheight;
   fontwidth_2 = fontwidth;
   firstchar_2 = firstchar;
   offschar_2 = offschar;

   fontfile = font_1; proptab = prop_1;
   readfont(primaryfont);
   fontdesc_1 = fontdesc;
   fontheight_1 = fontheight;
   fontwidth_1 = fontwidth;
   firstchar_1 = firstchar;
   offschar_1 = offschar;

  ptr=0; tekptr=0;

  tekbuf=(unsigned char *)calloc(tekbufsiz,sizeof(char));

  while(1==1) {
    n=read(fd,z,8191);
    if(n>0) {
       m=writebuf(z,n); /* writebuf returns some flags */
       if(m==-1) break;         /* quit flag */
    } else {
       close(fd);
       fd=open(tekname,2);
    }
  }
  close(fd);
  unlink(tekname);
  free(font_1); free(font_2); free(prop_1); free(prop_2);
  free(tekname); free(primaryfont); free(secondaryfont);
  free(defaultprinter); free(systemcommand); free(bufferfile);
  if(bufferonfile) {
      close(fdbuffer);
      unlink(bufferfile);
   } else {
     if (!nohco) free(buf);
  }
  exit(0);
}

/*
The routine writebuf writes all tektronix vectors to the specified buffer,
and searches for some specific actions. Every Clear Screen resets the buffer.
if the buffer is full, no additional vectors are accepted.
Values returned:
   0   normal return
   -1  program abort
*/

writebuf(s,n)
char s[];
int n;
{
int i,j,p,erg,fd2;
char c,z[80],param[256];

   erg=0;                                /* assume normal return */

   for(i=0;i<n;i++) {
      c=s[i];
      if(esc) {                          /* trap escape sequences */
         switch(c) {
         case 0x1a :                     /* graphic cursor */
            gfxbufin(c); tekflush();
            z[0]=0; while(strlen(z)<5) fgets(z,80,stdin);
            j=strlen(z)-5;
            p=0; while(c!=0) {
               c = z[j++];
               z[p++] = c;
            }
            fd2=creat(TMPGCURSOR,0777);
            if(fd2<=0) {
               printf("\nfailed to open %s!\n",TMPGCURSOR);
               continue;
            }
            p=write(fd2,z,5);
            close(fd2);
            c=0;
            break;
         case 0x1c :                     /* request text length */
            p=0;
            c=1;
            i=i+1;
            while(c!=0) {
               c=s[i++];
               param[p++]=c;
            }
            i=i-1;
            p = textlen(param);
            sprintf(z,"%d\n",p);
            mknod(TMPGCURSOR,S_IFIFO | S_IROTH |S_IWOTH | S_IRUSR | S_IWUSR,0);
            fd2=open(TMPGCURSOR,1);
            if(fd2<=0) {
               printf("\nfailed to open %s !\n",TMPGCURSOR);
               continue;
            }
            p=write(fd2,z,strlen(z));
            close(fd2);
            c=0;
            break;
         case 0x1e :                     /* request text height */
            p = textheight();
            sprintf(z,"%d\n",p);
            mknod(TMPGCURSOR,S_IFIFO | S_IROTH |S_IWOTH | S_IRUSR | S_IWUSR,0);
            fd2=open(TMPGCURSOR,1);
            if(fd2<=0) {
               printf("\nfailed to open %s!\n",TMPGCURSOR);
               continue;
            }
            p=write(fd2,z,strlen(z));
            close(fd2);
            c=0;
            break;
         case 0x0c :                     /* clear screen => reset pointer */
            ptr=0;

            sizex = sizex_1;
            sizey = sizey_1;
            fontfile = font_1;
            proptab = prop_1;
            fontdesc = fontdesc_1;
            fontheight = fontheight_1;
            fontwidth = fontwidth_1;
            firstchar = firstchar_1;
            offschar = offschar_1;
            prop_flag = 1;

            if(bufferonfile) {
               close(fdbuffer);
               fdbuffer = creat(bufferfile,0666);
               close(fdbuffer);
               fdbuffer = open(bufferfile,2,0666);
            }

            break;
         case 0x40 :                     /* <esc>@ is now defined as quit */
            erg = -1;
            break;
         case 0x1b :                     /* <esc><esc>: special action */
            p=0;
            c=1;
            i=i+1;
            while(c!=0) {
               c=s[i++];
               param[p++]=c;
            }
            i=i-1;
            do_special(param); 
            esc = FALSE;
            break;
         }
         esc=FALSE;                      /* clear esc flag */
      } 
      esc=FALSE;
      if(c==0x1b)  esc=TRUE;             /* set escape flag */
      if(c==0x1f) {                      /* trap text sequence */
         c=32; p=0; 
         i=i+1;
         if(s[i]==0x1b) {                /* handle textsize changes */
            c=s[i+1];
            switch(c) {
            case ';':                    /* smallest text size */
               sizex = msizex / 2;
               sizey = msizey / 2;
               break;
            case ':':                    /* small text size */
               sizex = (msizex * 2) / 3;
               sizey = (msizey * 2) / 3;
               break;
            case '9':
               sizex = msizex;            /* normal text size */
               sizey = msizey;
               break;
            case '8':
               sizex = 2 * msizex;        /* big text size */
               sizey = 2 * msizey;
               break;
            }
            i=i+2;
         }
         while(c>31) {
            c=s[i++];
            param[p++]=c;
            if(i>n) break;
         }
         i=i-2;
         c=0;
         param[p-1]=0;                   /* set string end identifier */
         plotstr(param);
         continue;
      }
      if(c==0x1d) {               /* posita, store new position */
         p=i+1;
         gettekxy(s,&p,&cx,&cy);
      }
      gfxbufin(c); 
   }
   tekflush();
   return(erg);
}


/* ---------------------------------------------------------------
   Special actions: set text parameters and make hardcopy
   --------------------------------------------------------------- */
do_special(param)
char param[];
{
int i,n,m,sx,sy,tx,ty,w;
char c,s[80];

   sscanf(param,"%d",&n);

   hcothick = FALSE;
   if(n > 127) {
      hcothick = TRUE;
      n = n && 127;
   }

   strcpy(s,"");
   switch(n) {
   case 0 :                                     /* textparam */
      sscanf(param,"%d %d %d %d %d %d %s",&i,&sx,&sy,&tx,&ty,&w,s);
      if(sx>0) {sizex=sx; msizex=sx;}
      if(sy>0) {sizey=sy; msizey=sy;}
      if(tx>0) thickx=tx;
      if(ty>0) thicky=ty;
      if(s[0]!=0) readfont(s);
      txtangle=w;
      rotmat(w);
      break;
   case 1 :                                     /* hco */
      sscanf(param,"%d %s",&i,s); 
      hco(s);
      break;
   case 2 :
      sscanf(param,"%d %s",&i,s);               /* print HP-GL */
      save_hpgl(s);
      break;
   case 3 :
      sscanf(param,"%d %s",&i,s);               /* print PostScript */
      save_ps(s);
      break;
   }
}


cvtxy(xx,yy)
int xx,yy;
{
int i,xh,xl,yh,yl;
int x4, y4;
char ch,cl;

   x4 = xx >> 2; y4 = yy >> 2;
   yh = y4 >> 5; yl = y4 & 31;
   xh = x4 >> 5; xl = x4 & 31;
   i = (xx & 3) + 4 * (yy & 3); 
   gfxbufin(yh | 32);
   gfxbufin(i | 96);
   gfxbufin(yl | 96);
   gfxbufin(xh | 32);
   gfxbufin(xl | 64);
}


gettekxy(s,p,x,y)
char s[];
int *p,*x,*y;
{
int xx,yy,i,l,h,ptr,k,z1,z2;
char c;

   z1 = -1; z2 = -1;
   xx = -1 ; yy = -1;
   ptr = *p;
   for(k=1;k<10;k++) {
      c=s[ptr++];
      i=(c & 0xe0);
      switch(i) {
      case 32:
         h = (c & 31);
         break;
      case 64:
         l = (c & 31);
         xx = (h*32 + l) << 2;
         if(z2 != -1) xx = xx | z2;
         break;
      case 96:
         l = (c & 31);
         if(z1 != -1) {
            yy = h*32 + l;
            yy = (yy << 2) | (z1 >> 2);
            z2 = z1 & 3;
         } else {
            yy = (h*32 + l) << 2;
            z1 = l & 15;
         }
         break;
      }
      if((xx != -1) & (yy != -1)) break;
   }
   *x = xx; *y = yy; *p = ptr;
   return(0);
}

posita(x,y)
int x,y;
{
   int  n,m;

   gfxbufin(0x1d);
   cvtxy(x,y);
}

vectoa(x,y)
int x,y;
{
   int  n,m;

   cvtxy(x,y);
}



gfxbufin(c)
char c;
{
   if(bufferonfile) {
      write(fdbuffer,&c,1); 
      ptr++; fdptr++;
   } else {
      if((ptr<bufsiz) & (!nohco)) buf[ptr++]=c;
   }
 
   if(tekptr>=tekbufsiz) tekflush();
   tekbuf[tekptr++]=c;
}

tekflush()
{
write(fdstdout,tekbuf,tekptr);
tekptr=0;
}

getbuf(p)
int p;
{
   if(bufferonfile) {
      if(p == fdptr - 1) return(lastchar);
      if(p == fdptr) {
         read(fdbuffer,&lastchar,1);
         fdptr++;
         return(lastchar);
      }
      lseek(fdbuffer,p,0);
      read(fdbuffer,&lastchar,1);
      fdptr = p + 1;
      return(lastchar);
   } else {
      return(buf[p]);
   }
}


/* *********************************************************************

                  Vector font utilities

   ********************************************************************* */

/* ------------------------------------------------------------------
      Read Vector font from file (as defined in Aux_Config)
   ------------------------------------------------------------------ */
readfont(name)
char *name;
{
int n,i,m,xx,max;
int yy,base;
unsigned char *ptr;
int fd;

   fd = open(name,0);
   read(fd,fontfile,16384);
   close(fd);
   n = 0;
   while(fontfile[n] != 0x1a) if(n++ > 32767) break;
   i = fontfile[n+1] + 256 * fontfile[n + 2];
   ptr = &fontfile[i];
   if(ptr[0] != 0x2b) {
      printf("no font file\n");
      exit(0);
   }
   offschar = i + ptr[5] + 256 * ptr[6];
   firstchar = ptr[4];
   fontheight = ptr[8] + ptr[11];
   fontdesc = &ptr[18];
   base = 0;
   m = 128 - firstchar;
   for(n = 0; n < m; n++) {         /* check fontwidth, generate prop table */
      i = offschar + fontdesc[2 * n] + 256 * fontdesc[2 * n + 1];
      ptr = &fontfile[i];
      i = 0; max = 0;
      while((ptr[i] & 0x80) != 0) {
         xx = ptr[i++]; yy = ptr[i++];
         xx = xx & 0x7f; yy = yy & 0x7f;
         if(xx > max) max = xx;
         if((yy & 0x40) != 0) {
            yy = (yy & 0x3f) - 0x3f;
            if(yy < base) base = yy;
         }
      }
      max = max + 2;
      proptab[n + firstchar + 1] = max;
   }
   base = -1 * base; fontheight = 0;
   for(n = 0; n < m; n++) {         /* move baseline */
      i = offschar + fontdesc[2 * n] + 256 * fontdesc[2 * n + 1];
      ptr = &fontfile[i];
      i = 0; max = 0;
      while((ptr[i] & 0x80) != 0) {
         i++; yy = ptr[i];
         xx = yy; yy = yy & 0x7f;
         if((yy & 0x40) != 0) yy = (yy & 0x3f) - 0x3f;
         yy = yy + base;
         if(yy > fontheight) fontheight = yy;
         yy = yy | (xx & 0x80);
         ptr[i++] = yy;
      }
   }
   fontheight = fontheight / 2;
   proptab[' '] = proptab['i'];
   fontwidth = proptab['W'];
}

textlen(s)
char *s;
{
int c,i,n;

   i = 0; n = 0;
   while(s[i] != 0) {
      c = s[i++];
      if(c == 92) {     /* meta character BACKSLASH ! */
         i++;           /* ignore next character */
         continue;
      }
      if(prop_flag == 1) {
         n = n + sizex * proptab[c];
      } else {
         n = n + sizex * fontwidth;
      }
   }
   n = n >> 1; /* ????????????????????! */
   return(n);
}

textheight()
{
int h;

   h = sizey * fontheight;
   return(h);
}

/* ------------------------------------------------------------------
      Rotation
   ------------------------------------------------------------------ */
rotate(xx,yy)
int *xx,*yy;
{
int rx,ry,x,y;

   x = *xx ; y = *yy;
   rx = ((x * cosphi) >> 19) - (( y * sinphi) >> 19);
   ry = (( y * cosphi) >> 19) + ((x * sinphi) >> 19);
   *xx = rx ; *yy = ry;
}

/* ------------------------------------------------------------------
      plot one single character
   ------------------------------------------------------------------ */

plotchar(c)
int c;
{
int xx,yy;
int ix,iy;
int i,n;
unsigned char *ptr;

   ix = cx; iy = cy;

   posita(ix,iy);

   n = c - firstchar - 1;
   i = offschar + fontdesc[2 * n] + 256 * fontdesc[2 * n + 1];
   ptr = &fontfile[i];
   i = 0;
   while((ptr[i] & 0x80) != 0) {
      xx = ptr[i++]; yy = ptr[i++];
      n = 0;
      if((yy & 0x80) != 0) n = 1;
      xx = xx & 0x7f; yy = yy & 0x7f;
      xx = xx * sizex;
      yy = yy * sizey;
      rotate(&xx,&yy);
      if(n == 1) {
         vectoa(ix + xx, iy + yy);
      } else {
         posita(ix + xx, iy + yy);
      }
   }
   xx = sizex * fontwidth; yy = 0;
   if(prop_flag == 1) xx = sizex * proptab[c];
   rotate(&xx ,&yy);
   cx = ix + xx;
   cy = iy + yy;
   return(0);
}

/* ------------------------------------------------------------------
      plot string
   ------------------------------------------------------------------ */
plotstr(s)
char s[];
{
int i,mx,my,tx,ty;
int msizex, msizey, mprop;
unsigned char c;

   cy = cy - 4;
   msizex = sizex;
   msizey = sizey;
   mprop = prop_flag;
   mx = cx ; my = cy;
   for(tx=0;tx<thickx;tx++) {
      for(ty=0;ty<thicky;ty++) {
         cx = mx + tx;
         cy = my + ty;
         i=0;
         baseline = 0;
         sizex = msizex;
         sizey = msizey;
         fontfile = font_1;
         proptab = prop_1;
         fontdesc = fontdesc_1;
         fontheight = fontheight_1;
         fontwidth = fontwidth_1;
         firstchar = firstchar_1;
         offschar = offschar_1;
         prop_flag = mprop;

         while(1==1) {
            c = s[i++];
            if(c==0) break;
            if(c==92) {   /* meta character BACKSLASH ! */
               c = s[i++];
               switch(c) {
                  case 'u':   /* superscript */
                     baseline = baseline +1;
                     if(baseline > 0) {
                        cy = cy + ((sizey * fontheight) >> 1);
                        sizex = (sizex << 2) / 5;
                        sizey = (sizey << 2) / 5;
                        continue;
                     }
                     if(baseline == 0) {
                        cy = my + ty;
                        sizex = msizex;
                        sizey = msizey;
                        continue;
                     }
                     if(baseline < 0) {
                        cy = cy + ((sizey * fontheight) >> 1);
                        sizex = (5 * sizex) >> 2;
                        sizey = (5 * sizey) >> 2;
                        continue;
                     }
                  case 'd':   /* subscript */
                     baseline = baseline -1;
                     if(baseline < 0) {
                        cy = cy - ((sizey * fontheight) >> 1);
                        sizex = (sizex << 2) / 5;
                        sizey = (sizey << 2) / 5;
                        continue;
                     }
                     if(baseline == 0) {
                        cy = my + ty;
                        sizex = msizex;
                        sizey = msizey;
                        continue;
                     }
                     if(baseline > 0) {
                        cy = cy - ((sizey * fontheight) >> 1);
                        sizex = (5 * sizex) >> 2;
                        sizey = (5 * sizey) >> 2;
                        continue;
                     }
                  case '1':   /* primary font */
                        fontfile = font_1;
                        proptab = prop_1;
                        fontdesc = fontdesc_1;
                        fontheight = fontheight_1;
                        fontwidth = fontwidth_1;
                        firstchar = firstchar_1;
                        offschar = offschar_1;
                        continue;
                  case '2':   /* secondary font */
                        fontfile = font_2;
                        proptab = prop_2;
                        fontdesc = fontdesc_2;
                        fontheight = fontheight_2;
                        fontwidth = fontwidth_2;
                        firstchar = firstchar_2;
                        offschar = offschar_2;
                        continue;
                  case '0':   /* proportional off */
                        prop_flag = 0;
                        continue;
                  case 'b':   /* backspace */
                        cx = (cx - (sizex * fontwidth) >> 1);
                        continue;
               }
            }
            plotchar(c);
         }
      }
   }
   baseline = 0;
   sizex = msizex;
   sizey = msizey;
   fontfile = font_1;
   proptab = prop_1;
   fontdesc = fontdesc_1;
   fontheight = fontheight_1;
   fontwidth = fontwidth_1;
   firstchar = firstchar_1;
   offschar = offschar_1;
   prop_flag = mprop;
   return(0);
}


/* ----------------------------------------------------
       Calculate rotation matrix
   ---------------------------------------------------- */

rotmat(n)
int n;      /* Angle in degree */
{
int i,m;
float phi,cphi,sphi;

   phi = ((float) n) * 3.1415926 / 180.0;
   cphi = 262144 * cos( phi );
   sphi = 262144 * sin( phi );
   sinphi = (int) sphi;
   cosphi = (int) cphi;
}

xtoi(s)
char  s[];
{  int i,m,l,e;
   char c;

   l=strlen(s); e=0;
   for( i = 0 ; i < l ; i++ ) {
      c = s[i] ; c = toupper(c) ;
      m = c - '0' ;
      if( m > 9 ) m = m - 7 ;
      e = 16 * e + m ;
   } ;
   return(e) ;
}

/* ****************************************************************

                  HARDCOPY and related functions

   **************************************************************** */

hco(str)
char str[];
{
unsigned char *bitplane;
char z[80];
int n;

   pribufsiz=8190;
   pribufptr=0;
   printerbuf=(unsigned char *)calloc(pribufsiz+2,sizeof(char));
   if(buf==NULL) {
      fprintf(stderr,"could not allocate printer buffer %d bytes\n",pribufsiz);
      return(0);
   }


   strcpy(z,defaultprinter);
   if(str[0]!=0) strcpy(z,str);
   fdprinter=auxopen(z);
   strcpy(systemcommand,auxparams[4]);

   n=5;
   prt_passes=atoi(auxparams[n]); n=n+1;
   prt_lsbmsb=atoi(auxparams[n]); n=n+1;
   x_prt_siz=atoi(auxparams[n]); n=n+1;
   y_prt_siz=atoi(auxparams[n]); n=n+1;

   if(prt_lsbmsb == 10) {
      save_ps(auxparams[0],x_prt_siz,y_prt_siz);
      system(systemcommand);
      return(0);
   }
   if(prt_lsbmsb == 11) {
      save_hpgl(auxparams[0],x_prt_siz,y_prt_siz);
      system(systemcommand);
      return(0);
   }

   cvtbs(prt_init,auxparams[n]); n=n+1;
   cvtbs(prt_gra,auxparams[n]); n=n+1;
   cvtbs(prt_halflf,auxparams[n]); n=n+1;
   cvtbs(prt_lf,auxparams[n]); n=n+1;
   cvtbs(prt_fin,auxparams[n]);

   if(fdprinter <= 0) {
      fdprinter = creat(auxparams[0],0666);
      if(fdprinter <= 0) return(0);
   }

   n = (x_prt_siz * y_prt_siz) / 8;     /* length of buffer needed */
   n = n + 1024;                        /* to go shure */
   bitplane=(unsigned char *)calloc(n,sizeof(char));
   if(buf==NULL) {
      fprintf(stderr,"could not allocate shadow memory %d bytes\n",n);
      free(printerbuf);
      close(fdprinter);
      return(0);
   }
   redrawhco(bitplane);
   printout(bitplane);
   close(fdprinter);
   free(bitplane); free(printerbuf); 
   system(systemcommand);
   return(0);
}

strtoprt(s)
unsigned char s[];
{
int n;
unsigned char c;

   n=0;
   while(1==1) {
      c=s[n++];
      if(c==0) break;
      pribufin(c);
   }
}

pribufin(c)
unsigned char c;
{
if(pribufptr>=pribufsiz) pribufflush();
printerbuf[pribufptr++]=c;
}

pribufflush()
{
write(fdprinter,printerbuf,pribufptr); 
pribufptr=0;
}

redrawhco(bitplane)
unsigned char *bitplane;
{
int x,y,i,n,m,p;
char c,s[80];

   p=0;
   while(getbuf(p)!=0x1d) p=p+1;          /* find posita first */

   while(p<ptr) {                      /* scan vector buffer */

      c=getbuf(p);
      if(c==0x1d) {
         p=p+1;
         gettekxy(buf,&p,&x,&y);
         if((x>_TEKXMAX) | (y>_TEKYMAX)) {
            while(getbuf(p)!=0x1d) p=p+1;
            continue;
         }
         draw_to(bitplane,FALSE,x,y);
         continue;
      }
      if(c>31) {
         gettekxy(buf,&p,&x,&y);
         if((x>_TEKXMAX) | (y>_TEKYMAX)) {
            while(getbuf(p)!=0x1d) p=p+1;
            continue;
         }
         draw_to(bitplane,TRUE,x,y);
         continue;
      }
      while(getbuf(p)!=0x1d) p=p+1;          /* find next posita */
   }
}
      
/* --------------------------------------------------------------- */
/*       Draw a line                                               */
/* --------------------------------------------------------------- */
draw_to(bitplane,pen_down,x,y)
unsigned char *bitplane;
int pen_down,x,y;
{
   int   xinc,yinc,
         xcount,ycount,
         fx,fy;


   x = (x_prt_siz * x) / _TEKXMAX ;
   y = (y_prt_siz * y) / _TEKYMAX ; y=y_prt_siz-y;

   if(pen_down == TRUE) {
      xinc=liabs(x-aposx);
      yinc=liabs(y-aposy);
      fx=lisgn(x-aposx);
      fy=lisgn(y-aposy);
      xcount=xinc;
      ycount=yinc;
      do {
         set_pixel(bitplane,aposx,aposy);
         if(hcothick) {
            set_pixel(bitplane,aposx+1,aposy);
            set_pixel(bitplane,aposx,aposy+1);
            set_pixel(bitplane,aposx+1,aposy+1);
         }
         if(xcount>ycount) {
            ycount=ycount+yinc ; aposx=aposx+fx;
         } else {
            xcount=xcount+xinc ; aposy=aposy+fy;
         }
      } while((liabs(x-aposx)>=1) || (liabs(y-aposy)>=1));
   }
   aposx=x; aposy=y;
}

liabs(x)
int x;
{
   if(x>=0) return(x);
   return(-x);
}

lisgn(x)
int  x;
{
   if(x>0) return(1L);
   if(x<0) return(-1L);
   return(0L);
}

/* --------------------------------------------------------------- */
/*       plot one pixel                                            */
/* --------------------------------------------------------------- */
set_pixel(bitplane,x,y)
unsigned char *bitplane;
int x,y;
{
   register int  byte,bit,n;



   byte=y*(x_prt_siz>>3)+(x>>3);
   bit= x & 7; n=128>>bit;
   bitplane[byte] |= n;
}

/* --------------------------------------------------------------- */
/*       get one pixel from shadow memory                          */
/* --------------------------------------------------------------- */
get_pixel(bitplane,x,y)
unsigned char *bitplane;
int x,y;
{
   register int   byte,bit;
   register unsigned char c;

   byte=y*(x_prt_siz>>3)+(x>>3);
   bit=7-(x & 7);
   c=((bitplane[byte])>>bit) & 1;
   return((int)c);
}

/* ----------------------------------------------------------- */
/*       get one byte ready to print from shadow memory        */
/* ----------------------------------------------------------- */
get_prtbyte(bitplane,x,y)
unsigned char *bitplane;
int x,y;
{
   int    i,m;
   long   n;

   m=0; n=0; x=x_prt_siz-x;
   for(i=1; i<=8; ++i) {
      n=n+prt_passes;
      m=2*m+get_pixel(bitplane,x-n,y);
   }
   return(m);
}

/* ----------------------------------------------------------- */
/*       make hardcopy of shadow memory                        */
/* ----------------------------------------------------------- */
printout(bitplane)
unsigned char *bitplane;
{
   long  x,y,i;
   unsigned char c;


   strtoprt(prt_init); pribufflush();

   if(prt_lsbmsb == 2) {              /* trap HP raster row graphics */
      hp_rasterrow(bitplane);
      return(0);
   }

   if(prt_lsbmsb == 3) {              /* trap HP DeskJet 500 */
      hp_deskjet(bitplane);
      return(0);
   }

   /* it follows the epson style printout routine */

   x=0;
   while(x<x_prt_siz) {
      y=0;
      for(i=1; i<=prt_passes; ++i) {
         prt_gra_out(y_prt_siz);
         while(y<y_prt_siz) {
            c=get_prtbyte(bitplane,x,y++);
            pribufin(c);
         }
         strtoprt(prt_halflf); 
         y=0; ++x;
      }
      strtoprt(prt_lf); pribufflush();
      x=x+7*prt_passes;
   }

   strtoprt(prt_fin); pribufflush();
   return(0);
}

/* -----------------------------
   HP mode raster row graphics 
   ----------------------------- */

hp_rasterrow(bitplane)
unsigned char *bitplane;
{
   int  n,x,m,i;
   unsigned char c;


   m = x_prt_siz / 8;
   n = (y_prt_siz -1) * m;
   x=0;
   while(x<n) {
      strtoprt(prt_gra);
      for(i=0; i<m; i++) {
         c=bitplane[x++];
         pribufin(c);
      }
      pribufflush();
   }
   strtoprt(prt_fin); pribufflush();
   return(0);
}

/* -----------------------------
      HP DeskJet mode  
   ----------------------------- */

hp_deskjet(bitplane)
unsigned char *bitplane;
{
int  x,y,i;
unsigned char c;

   x=0;
   while(x<x_prt_siz) {
      y = y_prt_siz - 1;
      strtoprt(prt_gra);
      while(y >= 0) {
         c = 0;
         for(i = 0; i < 8; i++) {
            c = (2 * c) + get_pixel(bitplane,x,y--);
         }
         pribufin(c);
      }
      pribufflush();
      x = x + 1;
   }
   strtoprt(prt_fin); pribufflush();
   return(0);
}

/* ------------------------------------------------------------ */
/* some printer dependend routines:                             */
/* ------------------------------------------------------------ */

prt_gra_out(x)
int  x;
{
unsigned char c1,c2;

   c1=x/256; c2=x-256*c1;
   strtoprt(prt_gra);
   if(prt_lsbmsb==1) {
      pribufin(c2);
      pribufin(c1);
   } else {
      pribufin(c1);
      pribufin(c2);
   }
   return(0);
}


/* convert string which includes the backslash */

cvtbs(s2,s1)
char s2[] , s1[];
{  int   l , i2 , i1 ;
   char  c , cc , s[8];

   l=strlen(s1); i2=0 ;
   for (i1 = 0; i1 <= l; i1++) {
      c=s1[i1];
      if(c == ' ') continue;
      if(c == '\\') {
         cc=s1[++i1];
         switch(cc) {
         case 'n':
            c='\n' ;  break ;
         case 'f':
            c='\f' ;  break ;
         case 't':
            c='\t' ;  break ;
         case 'b':
            c='\b' ;  break ;
         case 'x': /* hexadecimal conversion */
            s[0]=s1[++i1] ; s[1]=s1[++i1] ; s[2]=0 ;
            c=xtoi(s) ; break ;
         default:
            ; } ;
         } ;
      s2[i2++]=c ; }
   s2[i2]=0 ;
   return(i2-1);
}


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

      Diverse Vektororientierte Ausgabe formate:

      HP-GL , DXF, PostScript

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

vector_out(output,x_faktor,y_faktor,x_ofs,y_ofs,move_to,draw_to)
 FILE *output;
 char move_to[], draw_to[];
 float x_faktor, y_faktor;
 float x_ofs, y_ofs;
{
int x,y,p;
float fx,fy;
char c;
int linecount;          /* This variable is introduced to work around a "bug" in most
                           PostScript interpreters, which have only restricted memory
                           capacities                                                 */

   p=0; linecount = 0;
   while(getbuf(p)!=0x1d) p=p+1;          /* find posita first */

   while(p<ptr) {                      /* scan vector buffer */

      c=getbuf(p);
      if(c==0x1d) {
         p=p+1;
         gettekxy(buf,&p,&x,&y);
         if((x>_TEKXMAX) | (y>_TEKYMAX)) {
            while(getbuf(p)!=0x1d) p=p+1;
            continue;
         }
         fx = (x_faktor * x) + x_ofs;
         fy = (y_faktor * y) + y_ofs;
         fprintf(output,move_to,fx,fy);
         linecount = 0;
         continue;
      }
      if(c>31) {
         gettekxy(buf,&p,&x,&y);
         if((x>_TEKXMAX) | (y>_TEKYMAX)) {
            while(getbuf(p)!=0x1d) p=p+1;
            continue;
         }
         fx = (x_faktor * x) + x_ofs;
         fy = (y_faktor * y) + y_ofs;
         fprintf(output,draw_to,fx,fy);
         if(linecount++ > 20) {           /* work around PostScript "bug" */
            linecount = 0;
            fprintf(output,move_to,fx,fy);
         }
         continue;
      }
      while(getbuf(p)!=0x1d) p=p+1;          /* find next posita */
   }
   return(0);
}

save_hpgl(s)
char *s;
{
FILE *output;

   output = fopen(s,"w");
   fprintf(output,"IN;\nLT;\n1;\n");
   vector_out(output,(float)15,(float)15,(float)0,(float)0,
      "PU;PA %5.0f,%5.0f;\n",
      "PD;PA %5.0f,%5.0f;\n");
   fprintf(output,"PU;SP;IP;SC;PA 0,7650\n");
   fclose(output);
   return(0);
}

save_dxf(s)
char *s;
{
FILE *output;

   output = fopen(s,"w");
   vector_out(output,(float)15,(float)15,(float)0,(float)0,
      "PU;\nPA %5.0f %5.0f;\n",
      "PD;\nPA %5.0f %5.0f;\n");
   fclose(output);
   return(0);
}

save_ps(s)
char *s;
{
FILE *output;

   output = fopen(s,"w");
   vector_out(output, 0.5, 0.5, 10.0, 30.0,
      "0.2 setlinewidth\nstroke\n%4.2f %4.2f moveto\n",
      "%4.2f %4.2f lineto\n");
   fprintf(output,"0.2 setlinewidth\nstroke\nshowpage\n");
   fclose(output);
   return(0);
}
