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

    copypsfile - convert PostScript file to HP graphics  
                
                Peter A. Henning (P.Henning@gsi.de)
                February, 1995

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

#include "config.h" 
#include "commands.h"

#include <dos.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>

#ifdef vms
#include <file.h>
#else
#include <fcntl.h>
#endif

#ifdef MSDOS
#include <dos.h>     /* only for binaryopen on device  */
#endif

#ifdef  unix
#include <limits.h>
#endif

#ifdef _AMIGA
# include <exec/exec.h>
# include <exec/execbase.h>
# include <exec/tasks.h>
# include <proto/dos.h>
# include <proto/exec.h>
# include <fcntl.h>
# include <ios1.h>
# include "postlib.h"

/*-- Assembler routines */


extern void insertbreak(void);
extern void deletebreak(void);
extern void insertftrap(void);
extern void deleteftrap(void);

/*-- Routines defined and referenced only within this module */

extern void __saveds __asm copypage(register __d0 int num);

#endif

extern FILE    *outfp;

extern short   x_goffset;         /* global x-offset in dots             */
extern short   y_goffset;         /* global y-offset in dots             */
extern long    hconv, vconv;      /* converts DVI units to pixels        */
extern long    h;                 /* current horizontal position         */
extern long    v;                 /* current vertical position           */

#define PIXROUND(x,c) (((x)+c)/c)

/*-->CopyPSFile*/   /* interpret a Postscript file */
/*********************************************************************/
/***************************** CopyPSFile ****************************/
/*********************************************************************/

struct Library *PSbase;
struct PSparm parm;

int arec,hoff,voff,retcode;
int breakset, ftrapset;

void
CopyPSFile( char *str, char *hscale,  char *vscale,
                       char *hoffset, char *voffset,
                       char *hsize,   char *vsize,
                       char *angle)
{   FILE *PStemp;
    char *files[]={"tex:ps/init.ps","tex:ps/specs.pro",
                   "T:post.tmp"," "};
    char *dum;

    char *pages[7]={"hscale","vscale","hoffset","voffset",
                  "hsize","vsize","angle"};
    int pagel[7][3]={{0,300,100},{0,300,100},
                   {-612,612,0},{-792,792,0},
                   {-612,612,0},{-792,792,0},{0,360,0}};
    int i,dx,rx,ry,pagep[7];

    files[3] = str;
    pagep[0] = (int)strtol(hscale,&dum,10);
    pagep[1] = (int)strtol(vscale,&dum,10);
    pagep[2] = (int)strtol(hoffset,&dum,10);
    pagep[3] = (int)strtol(voffset,&dum,10);
    pagep[4] = (int)strtol(hsize,&dum,10);
    pagep[5] = (int)strtol(vsize,&dum,10);
    pagep[6] = (int)strtol(angle,&dum,10);
    
    /*-- check the values for consistency */
    for(i=0;i<7;i++)
    {  if( (pagep[i] > pagel[i][1])||(pagep[i] < pagel[i][0]) )
       {  Warning("\\special parameter %s out of range, set to %d",
            pages[i],pagel[i][2]);
          pagep[i] = pagel[i][2];
       }
    };
    fprintf(stderr,
       " (%s %d %d %d %d %d %d %d",str,pagep[0],pagep[1],pagep[2],
       pagep[3],pagep[4],pagep[5],pagep[6]);

   /*-- Open the library */
    PSbase = OpenLibrary("post.library", POSTVERNO);
    if (PSbase == NULL)
    {   Warning("Unable to open post.library");
        goto errorexit;
    }

   /*-- Open the tempfile */
    PStemp = fopen(files[2], "w");
    if (PStemp == NULL)
    {   Warning("Unable to open %s",files[2]);
        goto errorexit;
    }

  /*-- Determine the page size and offsets 
       max. size 2480 (3507) dots, printer margin 50 dots,
       subtract current position, corrected for angle */
    rx = (int)PIXROUND(h, hconv) + x_goffset;
    ry = (int)PIXROUND(v, vconv) + y_goffset;
    dx = min( (int)(ry*sin(pagep[6]/180.0*PI)),(rx-50) );

    hoff = -dx;
    voff = -(ry-50);
    
    parm.page.depth   = 1;
    parm.page.xoff    = -dx;
    parm.page.yoff    = 0;
    parm.page.xsize   = 2480-50-rx+dx;
    parm.page.ysize   = ry-50;
    parm.page.xbytes  = (parm.page.xsize + 7) >> 3;
    parm.page.len     = parm.page.xbytes * parm.page.ysize;
    parm.page.ybase   = 0;                  /*-- only for bands */
    parm.page.yheight = parm.page.ysize;
    parm.page.xden    = 300;
    parm.page.yden    = 300;
    parm.page.ydir    = -1;

    /*-- Write the tempfile */
    fprintf(PStemp,"@beginspecial\n");
    fprintf(PStemp,"%d @hscale  %d @vscale\n",pagep[0],pagep[1]);
    fprintf(PStemp,"%d @hoffset %d @voffset\n",pagep[2],pagep[3]);
    if( pagep[4]!=pagel[4][2] )
       fprintf(PStemp,"%d @hsize ",pagep[4]);
    if( pagep[5]!=pagel[5][2] )
       fprintf(PStemp,"%d @vsize ",pagep[5]);
    if( pagep[6]!=0 ) 
       fprintf(PStemp,"%d @angle ",pagep[6]);
    fprintf(PStemp,"@setspecial\n");
    fclose(PStemp);

     
    /*-- Allocate the page buffer */
    if ((parm.page.buf[0] =
        AllocMem(parm.page.len, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
        {   Warning(
              "Can't get PostScript page buffer %d bytes",parm.page.len);
            goto errorexit;
        };
    fprintf(stderr,", buffer %d bytes",parm.page.len);
    

    /*-- Initialize for interpretation */
    insertbreak();
    SetExcept(~0, SIGBREAKF_CTRL_C);
    breakset = 1;
    insertftrap();
    ftrapset = 1;

    parm.copyfunc = (APTR) copypage;

    parm.infh  = Input();
    parm.outfh = Output();
    parm.errfh = (BPTR) Open("*", MODE_OLDFILE);
    if (parm.errfh == NULL)
    {   retcode = 20;
        goto tidyexit;
    }

    arec = PScreateact(&parm);
    if (arec == 0)
    {   Warning("Can't get memory for PostScript");
        goto errorexit;
    }

    if ((unsigned) arec <= errmax)
    {   arec = 0;
        retcode = 10;
        goto tidyexit;
    }

    /*-- interpret the argument files */
    for (i = 0; i < 4; i++)
    {   fprintf(stderr,"<%s>",files[i]);
        if (PSintstring(arec, files[i],
           -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE) != 0)
        {   retcode = 10;
            goto tidyexit;
        }
    } 

errorexit:
    retcode = 20;
   /*-- Tidy up and exit */
tidyexit:
    if (breakset)
    {   SetExcept(0, SIGBREAKF_CTRL_C);
        deletebreak();
        breakset = 0;
    }
    if (ftrapset)
    {   deleteftrap();
        ftrapset = 0;
    }

    if (arec) PSdeleteact(arec);

    if (parm.page.buf[0])
    {   FreeMem(parm.page.buf[0], parm.page.len);
        parm.page.buf[0] = NULL;
    };

    if (PSbase) CloseLibrary(PSbase);

    if (parm.errfh) Close(parm.errfh);

    fprintf(stderr,") ");
}

/*-- Signal an interrupt ----------------------------------------*/

void __saveds sigint()
{   PSsignalint(arec, 1);
}

/*-- Signal a floating point error ------------------------------*/

void __saveds sigfpe()
{   PSsignalfpe(arec);
}

/*-- Copy the page to the output --------------------------------*/

void __saveds __asm copypage(register __d0 int num)
{   char *buf;
    int ysize,len;

    fprintf(stderr,", copypage");

    /*-- move cursor with offsets, 
         resolution 300 dpi, start graphics  */
    fprintf(outfp, "\33*p%+dx%+dY\33*t300R\33*r1A",hoff,voff);

    /*-- loop for the rows */
    buf   = parm.page.buf[0];
    ysize = parm.page.ysize;

    while (ysize--)
    {   len = parm.page.xbytes;
        /*-- strip trailing zeros */         
        while (len && buf[len - 1] == 0) len--;
        /*-- dump line of pixels */
        fprintf(outfp, "\33*b%dW", len);
        fwrite(buf, 1, len, outfp);
        buf += parm.page.xbytes;
    }

    /*-- end graphics, form feed, reset number of copies */
    fprintf(outfp, "\33*rB");

    /*-- test for error */
    if (ferror(outfp)) PSerror(arec, errioerror);
}

/*-->CopyIFFFile*/   /* interpret an IFF file */
/*********************************************************************/
/***************************** CopyIFFFile ***************************/
/*********************************************************************/

void
CopyIFFFile( char *str,char *hoffset, char *voffset,
                       char *hsize,   char *vsize)
{  Warning("CopyIFFFile not yet implemented");
}
