/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*
 * HEADER : pscrdrv.c      - Vers 3.6.010  - Jul 1994 -  L. Fini, OAA
 *
 * 
 * 090416	last modif
 *
 */


/*****************************************************************************/
/* AGL PostScript driver - L. Fini Jun 1987                                  */
/*                       - L. Fini Oct 1991 (Color support added)            */

/* This driver is based on a FORTRAN version provided by Alco Blom for       */
/* AGL V. 2.1                                                                */

/* This driver allows selection of landscape(default) and Portrait mode by   */
/* means of the USRAUX portion of the device definition string.              */

/* Output orientation and size default to landscape A4. Different selection  */
/* can be made when the first viewport is opened onto the device by means of */
/* format specifications characters with the following meanings:             */

/*       p    :  portrait                                                    */
/*       l    :  landscape                                                   */
/*       3    :  A3                                                          */
/*       4    :  A4                                                          */
/*       u    :  US-legal                                                    */


/* The selection characters are to be appendend to the device name, separa-  */
/* ted by a point as in the following examples:                              */

/*         iv=AG_VDEF("ps.p:",.......)      selects portrait A4              */
/*                     or                                                    */
/*         iv=AG_VDEF("ps.p4:",.......)     selects portrait A4              */

/*         iv=AG_VDEF("ps.pu:",.......)     selects portrait US-legal        */

/*         iv=AG_VDEF("ps.3:",.......)      selects portrait A3              */
/*                     or                                                    */
/*         iv=AG_VDEF("ps.l3:",.......)     selects landscape A3             */

/* (the characters: p,l,3,4,u can be put in any number and sequence. The     */
/*  last encountered only will take effect)                                  */

#include <aglsys.h>

#include <agl.h>
#include <aglerror.h>
#include <agldcom.h>
#include <agldcaps.h>


/*                                                                           */
/*  The following entry points have been defined:                            */
/*                                                                           */
/*  Function    Entry point                                                  */
/*                                                                           */
/*  Initialize  AGLINPS0                                                     */
/*  Cursor en.  AGLCUPS0                                                     */
/*  Erase       AGLERPS0                                                     */
/*  Escape      AGLESPS0                                                     */
/*  Polyline    AGLPLPS0                                                     */
/*  Finish      AGLTEPS0                                                     */
/*  Flush buff. AGLSEPS0                                                     */
/*                                                                           */


/*  device parameters definition                                             */

#define VERSCODE 36			/* Declare driver version            */

#define A4	1
#define A3	2
#define USLEGAL	3

#define PSFLAGS  SEPALPHA | EXECOMMND | SETBACKGR
#define PSMAXLWIDTH 4

#define PSBLACK		0	/* Bot index and grayscale value          */
#define PSWHITE		1	/* Bot index and grayscale value          */
#define PSRED		2
#define PSGREEN		3
#define PSBLUE		4
#define PSYELLOW	5
#define PSMAGENTA	6
#define PSCYAN		7

#define TRUE  1
#define FALSE 0

#define CVTX(x)  ((int)((x)*xfact))+1
#define CVTY(y)  ((int)((y)*yfact))+1


/* To allow for good resolution with small file length the driver uses      */
/*  an arbitrary set of coordinates so that numbers are never greater than  */
/* 10000 for A4 format. The PostScript scale factor is then used to adjust  */
/* for standard PostScript coordinates (1/72 of an inch). The following     */
/* values are the required conversion factors.                              */


/*      US Legal Landscape mode --------------------------+                 */
/*      US Legal Portrait mode ---------------------+     |                 */
/*      A3   Landscape mode -------------------+    |     |                 */
/*      A3   Portrait mode --------------+     |    |     |                 */
/*      A4   Landscape mode -------+     |     |    |     |                 */
/*      A4   Portrait mode --+     |     |     |    |     |                 */
/*                           |     |     |     |    |     |                 */
static float FACTC[6]  = { 6908, 9999, 9999, 14908,7453, 9817 };
static float PSCMAXL[6]= { 19.0, 27.5, 27.5, 41.0, 20.5, 27.0 }; 
static float PSCLENG[6]= { 19.0, 27.5, 27.5, 41.0, 21.0, 27.0 };
static float PIXCM[6]  = { 363.6364, 
                                 363.6364,
                                       363.6364, 
                                             363.6364, 
                                                   363.6364, 
                                                         363.6364 };
static float CHARF[6]  = { 13.889,          		 /* Char. multip.   */
                                 13.889, 
                                       13.889, 
                                             13.889, 
                                                   13.889, 
                                                         13.889 };

static FILE *filpt;
static int id0, id1;
static int Size,Sptx,Spty;
static int rot;
static double xfact,yfact,xofst,yofst;
static double xdim,ydim;
static int page_touch;		/* TRUE when current page has something into */
static int file_touch;		/* TRUE when current file has something into */
static int cur_color;
static int cur_backg;
static int n_colors;

static struct {
		float red;
		float green;
		float blue;
} CTAB[8] =			{
		/* PSBLACK	*/	{ 0.0,	0.0,	0.0 },
		/* PSWHITE	*/	{ 1.0,	1.0,	1.0 },
		/* PSRED	*/	{ 1.0,	0.0,	0.0 },
		/* PSGREEN	*/	{ 0.0,	1.0,	0.0 },
		/* PSBLUE	*/	{ 0.0,	0.0,	1.0 },
		/* PSYELLOW	*/	{ 1.0,	1.0,	0.0 },
		/* PSMAGENTA	*/	{ 1.0,	0.0,	1.0 },
		/* PSCYAN	*/	{ 0.0,	1.0,	1.0 } };

static char *hd0 = "%% Page: 1 1\n";
static char *hd1 = "/cm { 28.34646 mul } def\n";
static char *hd2 = "1.0 cm 1.0 cm translate\n";
static char *hd3_us = "20.5 cm 0 cm translate\n90 rotate\n";
static char *hd3_a4 = "19.0 cm 0 cm translate\n90 rotate\n";
static char *hd3_a3 = "27.5 cm 0 cm translate\n90 rotate\n";
static char *hd4 = "0.077960552 0.077960552 scale\n";
static char *hd5 = "[] 0 setdash\n";
static char hd6[] = "1 6 mul setlinewidth\n";
static char *hd7 = "/m { moveto } def\n";
static char *hd8 = "/r { rlineto } def\n";
static char *hd9 = "/l { 8 { rlineto } repeat } def \n";
static char *hd10 = "/c { { rlineto } repeat } def\n";
static char *hd11  = "/s { stroke } def\n";
static char *hd12  = "/n { newpath } def\n";
static char *hd13  = "2 setlinejoin\n";
static char *hd14 = "% BEGINNING OF PLOT\n";



static void showpage(filpt)
FILE *filpt;
{
/*
static char *show = "showpage	% END OF PAGE\n";
*/
static char *trail1 = "showpage\n";
static char *trail2 = "% END OF PAGE\n";
static char *trail3 = "%% Trailer\n";
static char *trail4 = "%% EOF\n";

/*
fputs(show,filpt);
*/
fputs(trail1,filpt);
fputs(trail2,filpt);
fputs(trail3,filpt);
fputs(trail4,filpt);
}





void set_pscolor(color)		/* set up a given color                */
int color;
{
fprintf(filpt,"%f %f %f setrgbcolor\n",CTAB[color].red,
                                       CTAB[color].green,
                                       CTAB[color].blue );
}





static void fill_area(xmin,xmax,ymin,ymax,color)
int xmin,xmax;
int ymin,ymax;
int color;
{
set_pscolor(color);

fprintf(filpt,"n %d %d moveto\n",xmin,ymin);
fprintf(filpt,"%d %d lineto\n",xmax,ymin);
fprintf(filpt,"%d %d lineto\n",xmax,ymax);
fprintf(filpt,"%d %d lineto\n",xmin,ymax);

fprintf(filpt,"closepath fill\n");

set_pscolor(cur_color);
}


/*---------------------------------------------------------------------------*/
void AGLINPS0 (AGLDVCOM)
struct bufcom *AGLDVCOM;
{
  /* static char *in00 = "%!PS-Adobe-3.0 EPSF-3.0\n";
     static char *in01 = "%%BoundingBox: 28 28 ";
     static char *in01_a4 = "570 810\n";
     static char *in01_a3 = "810 1208\n";
     static char *in01_us = "604 795\n";  
     static char *in02 = "%! AGL PostScript driver file header - V 3.61\n";
     static char *in03 = "%%EndComments\n";
  */

static char *in00 = "%!PS-Adobe-3.0 EPSF-3.0\n";
static char *in01 = "%%BoundingBox: 28 28 ";
static char *in01_a4 = "570 810\n";
static char *in01_a3 = "810 1208\n";
static char *in01_us = "604 795\n";  
static char *in02 = "%% Creator: ESO-MIDAS/AGL AGL version 3.61\n";
static char *in03 = "%% DocumentNeededResources: font Helvetica\n";
static char *in04 = "%% LanguageLevel: 1\n";
static char *in05 = "%% Pages: 1\n";
static char *in06 = "%% EndComments\n";

extern void AG_DMSG();

char auxbuf[PHNAMLNG];
static char *filnam = "pscrplot";
char *pt;


ERRCODE=AGLNOERR;

switch((int)IBUFFR(0)) {		/* Select function           */
case 0:					/* Hardware initialization   */
	file_touch=FALSE;
	page_touch=FALSE;
  
	strcpy(auxbuf,filnam);
	AG_NEWN(auxbuf);

	if(*auxbuf == '\0') {
		ERRCODE=DEVOPNSEV;
		return;
	}

	filpt=fopen(auxbuf,"w");

	if (filpt==NULL) {
		AG_DMSG("Open error:",auxbuf);
		ERRCODE=DEVOPNSEV;
		return;
	}

	*hd6 = '1';

	CHANNEL=0;

	rot = TRUE;			/* Select default orientation */
	Size=A4; 			/* Select default size        */

	pt=CHARBUF;
	while(*pt++);			/* Skip device name          */
	while(*pt++);			/* Skip SYSAUX info          */
					/* to Get USRAUX string      */
	while(*pt) {			/* Scan selection string     */
		switch(TOUPPER(*pt)) {
		case 'P': 		/* select portrait mode      */
			rot = FALSE;
			break;
		case 'L': 		/* select landscape mode     */
			rot = TRUE;
			break;
		case '4':
			Size=A4;
			break;
		case 'U':
			Size=USLEGAL;
			break;
		case '3':
			Size=A3;
			break;
		}
		pt++;
	}
	if(rot) {				/* Select rotation    */
		AG_DMSG("Mode:","Landscape");
		id0 = 1;
		id1 = 0;
	} else {
		AG_DMSG("Mode:","Portrait");
		id0 = 0;
		id1 = 1;
	}

	strcpy(CHARBUF,auxbuf);		/* Copy filename to buffer   */
	AG_DMSG("Out to:",auxbuf);

	fputs(in00,filpt);
	fputs(in01,filpt);

	switch(Size) {				/* Select size         */
	case A4:
		Sptx = id0;
		Spty = id1;
		AG_DMSG("Size:","A4");
		fputs(in01_a4,filpt);
		break;
	case A3:
		Sptx = id0+2;
		Spty = id1+2;
		AG_DMSG("Size:","A3");
		fputs(in01_a3,filpt);
		break;
	case USLEGAL:
		Sptx = id0+4;
		Spty = id1+4;
		AG_DMSG("Size:","US-legal");
		fputs(in01_us,filpt);
		break;
	}
    
	/* 
        fputs(in02,filpt);
	fputs(in03,filpt);
	*/

	fputs(in02,filpt);
	fputs(in03,filpt);
	fputs(in04,filpt);
	fputs(in05,filpt);
	fputs(in06,filpt);
	

	fputs(hd0,filpt);
	fputs(hd1,filpt);
	fputs(hd2,filpt);
	if(rot) 
		switch(Size) {			/* Select size         */
		case A4:
			fputs(hd3_a4,filpt);
			break;
		case A3:
			fputs(hd3_a3,filpt);
			break;
		case USLEGAL:
			fputs(hd3_us,filpt);
			break;
		}

	fputs(hd14,filpt);
	fputs(hd4,filpt);
	fputs(hd5,filpt);
	fputs(hd6,filpt);
	fputs(hd7,filpt);
	fputs(hd8,filpt);
	fputs(hd9,filpt);
	fputs(hd10,filpt);
	fputs(hd11,filpt);
	fputs(hd12,filpt);
	fputs(hd13,filpt);
	fputs(hd14,filpt);
     
	xdim = (RBUFFR(id0)<PSCMAXL[Sptx]) ? RBUFFR(id0) : PSCMAXL[Sptx];
	xdim = (xdim<=0.0) ? PSCLENG[Sptx] : xdim;
	ydim = (RBUFFR(id1)<PSCMAXL[Spty]) ? RBUFFR(id1) : PSCMAXL[Spty];
	ydim = (ydim<=0.0) ? PSCLENG[Spty] : ydim;
	xofst = ((PSCMAXL[Sptx]-xdim)*0.5) * FACTC[Sptx];   
	yofst = ((PSCMAXL[Spty]-ydim)*0.5) * FACTC[Spty];
	xfact = (xdim/PSCMAXL[Sptx]) * FACTC[Sptx];
	yfact = (ydim/PSCMAXL[Spty]) * FACTC[Spty];
	xofst *= FACTC[Sptx];
	yofst *= FACTC[Spty];
	break;

case 1:					/* Pass back device characteristics  */
	*(CHARBUF) = '\0';
	RBUFFR(0) = xdim;
	RBUFFR(1) = ydim;

	IBUFFR(1) = PSFLAGS;

	n_colors = 7;

	IBUFFR(2) = n_colors;

	IBUFFR(3) = xdim*PIXCM[Sptx];
	IBUFFR(4) = ydim*PIXCM[Spty];
	IBUFFR(5) = VERSCODE;
	IBUFFR(6) = PSMAXLWIDTH;

	cur_color=PSBLACK;
	cur_backg=PSWHITE;

	IBUFFR(7) = cur_backg;	/* Default Background */
	IBUFFR(8) = cur_color;	/* Default foreground */
	IBUFFR(9) = PSBLACK;
	IBUFFR(10) = PSRED;
	IBUFFR(11) = PSGREEN;
	IBUFFR(12) = PSBLUE;
	IBUFFR(13) = PSYELLOW;
	IBUFFR(14) = PSMAGENTA;
	IBUFFR(15) = PSCYAN;
	IBUFFR(16) = PSWHITE;

	RBUFFR(2) = CHARF[Sptx];
	RBUFFR(3) = 0.0;
	RBUFFR(4) = 0.0;
	RBUFFR(5) = 0.0;
	RBUFFR(6) = PSCLENG[Sptx];
	RBUFFR(7) = PSCLENG[Spty];
	RBUFFR(8) = PSCMAXL[Sptx];
	RBUFFR(9) = PSCMAXL[Spty];
	break;

case 2:						/* set color                 */
	ERRCODE=AGLNOERR;
	cur_color=IBUFFR(1);
	if((cur_color<0)||(cur_color>n_colors))
		cur_color=PSBLACK;
	set_pscolor(cur_color);
	break;

case 3:						/* set line style            */
	ERRCODE=AGLNOERR;			/* Not used since vers. 3.3  */
	break;

case 4:						/* set line width            */
	ERRCODE=AGLNOERR;
	*auxbuf = *hd6;
	switch((int)IBUFFR(1)) {
	default:
	case 0:
		*hd6 = '1'; 
		break;
	case 1:
		*hd6 = '2'; 
		break;
	case 2:
		*hd6 = '3'; 
		break;
	case 3:
		*hd6 = '4'; 
		break;
	case 4:
		*hd6 = '5'; 
		break;
	}
	if(*auxbuf != *hd6) 
		fputs(hd6,filpt);
	break;

case 6:					/* Coordinate roundoff         */
	break;			/* Unnecessary for high resol. devices */
}
}

static int cnt=0;
static int xv[8], yv[8];

static void trace(filpt,xx,yy)
FILE *filpt;
int xx,yy;
{
xv[cnt]=xx;
yv[cnt]=yy;
cnt++;
if (cnt==8) {
	do {
		cnt--;
		fprintf(filpt,"%d %d ", xv[cnt], yv[cnt]);
	} while(cnt);
	fprintf(filpt,"l\n");
	cnt=0;
}
}
 
static void trace_flush(filpt)
FILE *filpt;
{
if (cnt>0) {
	if(cnt==1)
		fprintf(filpt,"%d %d r ",xv[0],yv[0]);
	else {
		int cnts=cnt;
		do {
			cnt--;
			fprintf(filpt,"%d %d ", xv[cnt], yv[cnt]);
		} while(cnt);
		fprintf(filpt,"%d c ",cnts);
	}
}
fprintf(filpt,"s\n");
cnt=0;
}

/*---------------------------------------------------------------------------*/
void AGLPLPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
int n;
float *vectx, *vecty;
int xx,yy;
int x0,y0;





ERRCODE=AGLNOERR;

n = NPOINTS;
vectx = VECTX;
vecty = VECTY;

if(cur_color != cur_backg)
	{
	page_touch=TRUE;
	file_touch=TRUE;


	fprintf(filpt,"n %d %d m\n",		/* Move to first point       */
	               (x0=CVTX(*vectx++)),
	               (y0=CVTY(*vecty++)));

        xx=CVTX(*vectx++)-x0;
        yy=CVTY(*vecty++)-y0;

	/* the usual trace_flush doesn't draw anything
	   => missing point on the `i' char. 
	   so we make a 1x1 `filled' square 		*/

	if ((n == 2) && (xx == 0) && (yy == 0))
   	   {
   	   yy = 1;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = 1; yy = 0;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = 0; yy = -1;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = -1; yy = 0;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = 1; yy = 1;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = -1; yy = 0;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   xx = 1; yy = -1;
   	   fprintf(filpt,"%d %d ", xx,yy);
   	   fprintf(filpt,"7 c ");		/* 7 line segments */
   	   fprintf(filpt,"s\n");
   	   }

	else
	   {
           trace(filpt,xx,yy); 			/* Trace to second point      */

           x0 += xx; y0 += yy; n--;

	   while(n-- > 1) 
              {
	      register int xn,yn;

	      xn=CVTX(*vectx++);
	      yn=CVTY(*vecty++);
	      xx= xn-x0;
	      yy= yn-y0;

	      if((0!=xx)||(0!=yy)) 
                 {
	         trace(filpt,xx,yy);
	         x0 = xn;
	         y0 = yn;
	         }
	      }
	   }

	trace_flush(filpt);
	} 
}


/*---------------------------------------------------------------------------*/
void AGLCUPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
ERRCODE=UNSFEATINF;
}

/*---------------------------------------------------------------------------*/
void AGLERPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
int xmin,xmax,ymin,ymax;

ERRCODE=AGLNOERR;

xmin = CVTX(RBUFFR(0)); xmax = CVTX(RBUFFR(1));
ymin = CVTY(RBUFFR(2)); ymax = CVTY(RBUFFR(3));

if((xmin==CVTX(0.0))&&(xmax==CVTX(1.0))&&	/* Eject page, if the entire */
   (ymin==CVTY(0.0))&&(ymax==CVTY(1.0))  ){	/* page is erased            */
	if(page_touch) {
		showpage(filpt);
		page_touch=FALSE;
	}
}

cur_backg = IBUFFR(0);

if((cur_backg<0)||(cur_backg>n_colors))
	cur_backg=PSWHITE;

fill_area(xmin,xmax,ymin,ymax,cur_backg);
}

/*---------------------------------------------------------------------------*/
void AGLESPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
ERRCODE=UNSFEATINF;
}

/*---------------------------------------------------------------------------*/
void AGLSEPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
ERRCODE=AGLNOERR;
}

/*---------------------------------------------------------------------------*/
void AGLTEPS0(AGLDVCOM)
struct bufcom *AGLDVCOM;
{
extern void AG_DMSG();

showpage(filpt);
fclose(filpt); filpt=NULL; 

AG_DMSG("Out file","closed");
ERRCODE=AGLNOERR;
CHANNEL=(-1);
IBUFFR(0)= !file_touch;
}

