/*--------------------------------------------------------------*/
/*	Post Script Driver, for GLE V3.0 			*/
/*--------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
#include "all.h"

#include <math.h>
#include "core.h"
#include "mygraph.h"
#include "mydev.h"
char *fontdir(char *s);
extern int MAX_VECTOR; /* Cant send POSTSCRIPT too complex a path */
static int ps_nvec;

extern int control_d;
extern int dev_eps;
extern struct gmodel g;
/*---------------------------------------------------------------------------*/
#define pi 3.141592653
#define false 0
#define true (!false)
extern int BLACKANDWHITE;
#define dbg if ((gle_debug & 64)>0)
extern int gle_debug;
char *font_getname(int i);
/*---------------------------------------------------------------------------*/
/* The global variables that CORE keeps track of */
/*-----------------------------------------------*/

	FILE *psfile;
	int i,l,j;

colortyp g_cur_fill,g_cur_color;

/*---------------------------------------------------------------------------*/
d_dfont(char *c)
{
	/* only used for the DFONT driver which builds fonts */
}
/*---------------------------------------------------------------------------*/
d_tidyup()
{}
d_message(char *s)
{
#ifdef unix
	printw("%s\n",s);
#else
	printf("%s\n",s);
#endif
}
/*---------------------------------------------------------------------------*/
d_devcmd(char *s)
{
	fprintf(psfile,"%s",s);
}
d_source(char *s)
{
	dbg fprintf(psfile,"%% SOURCE, %s",s);
}
/*---------------------------------------------------------------------------*/
d_get_type(char *t)
{
	strcpy(t,"HARDCOPY, PS, FILLPATH");
	if (dev_eps) strcat(t,", EPS,");
}
/*---------------------------------------------------------------------------*/
d_set_path(int onoff)
{
}
/*---------------------------------------------------------------------------*/
d_newpath()
{
	fprintf(psfile," newpath ");
	ps_nvec = 0;
}
/*---------------------------------------------------------------------------*/
extern char output_file[];
extern char input_file[];
d_open(double width, double height)
{
	char *outfile;
	char *s;
	char outfileb[90] = "out.ps";

	outfile = &outfileb[0];
	s = strrchr(input_file,'.');
	if (s!=NULL) {
		strcpy(outfile,input_file);
		s = strrchr(outfile,'.');
		if (dev_eps) strcpy(s,".eps");
		else strcpy(s,".ps");
	}
	if (output_file[0]!=0) outfile = &output_file[0];
	psfile = fopen(outfile,"w");
	if (psfile == NULL) { perror("PS open file GLE_OUTPUT: ") ; exit(2); }

#ifdef __TURBOC__
	printf("\n Writing output to file (%s) \n",outfile);
#endif
	if (!dev_eps) {
		if (control_d) fprintf(psfile,"\x04 \n");
		fprintf(psfile,"%%!PS-Adobe-1.0 \n");
	} else {
		fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0 \n");
	}
	fprintf(psfile,"%%%%BoundingBox: -1 -1 %g %g \n",72*width/2.54+1,72*height/2.54+1);
	fprintf(psfile,"%%%%EndComments \n");
	fprintf(psfile,"%%%%EndProlog \n");
	fprintf(psfile,"gsave \n");
	fprintf(psfile," \n");
	fprintf(psfile,"/f {findfont exch scalefont setfont} bind def \n");
	fprintf(psfile,"/s {show} bind def \n");
	fprintf(psfile,"/ps {true charpath} bind def \n");
	fprintf(psfile,"/l {lineto} bind def \n");
	fprintf(psfile,"/m {newpath moveto} bind def \n");
	fprintf(psfile,"matrix currentmatrix /originmat exch def \n");
	fprintf(psfile,"/umatrix {originmat matrix concatmatrix setmatrix} def \n");
	fprintf(psfile," \n");
}
/*---------------------------------------------------------------------------*/
d_close()
{
	g_flush();
	fprintf(psfile,"showpage \n");
	fprintf(psfile,"grestore \n");
	fprintf(psfile,"%%%%Trailer \n");
	if (!dev_eps) if (control_d) fprintf(psfile,"\x04 \n");
	fclose(psfile);
}
/*---------------------------------------------------------------------------*/
d_set_line_cap(int i)
{
	/*  lcap, 0= butt, 1=round, 2=projecting square */
	if (!g.inpath) g_flush();
	fprintf(psfile,"%d setlinecap \n",i);
}
/*---------------------------------------------------------------------------*/
d_set_line_join(int i)
{
	if (!g.inpath) g_flush();
	fprintf(psfile,"%d setlinejoin \n",i);
}
/*---------------------------------------------------------------------------*/
d_set_line_miterlimit(double d)
{
	if (!g.inpath) g_flush();
	fprintf(psfile,"%g setmiterlimit \n",d);
}
/*---------------------------------------------------------------------------*/
d_set_line_width(double w)
{
	if (w==0) w = 0.02;
	if (w<.0002) w = 0;
	if (!g.inpath) g_flush();
	fprintf(psfile,"%g setlinewidth \n",w);
}
/*---------------------------------------------------------------------------*/
d_set_line_styled(double dd)
{}
d_set_line_style(char *s)
{
	/* should deal with [] for solid lines */
	static char *defline[] = {"","","12","41","14","92","1282"
	,"9229","4114","54","73","7337","6261","2514"};
	static char ob[200];
	int l;

	if (!g.inpath) g_flush();
	strcpy(ob,"[");
	if (strlen(s)==1) s = defline[*s-'0'];
	l = strlen(s);
	for (i=0;i<l;i++)
		sprintf(ob+strlen(ob),"%g ",(*(s+i)-'0')*g.lstyled);
	strcat(ob,"]");
	fprintf(psfile,"%s 0 setdash \n",ob);
}
/*---------------------------------------------------------------------------*/
d_fill()
{
	fprintf(psfile,"gsave \n");
	ddfill();
	fprintf(psfile,"grestore \n");
}
ddfill()
{
	if (g_cur_fill.b[B_F] == 255) return; /* clear fill, do nothing */
	if (g_cur_fill.b[B_F] == 2) {d_shade(); return;}
	set_fill();			/*because color and fill are the same*/
	fprintf(psfile,"fill \n");
	set_color();
}
d_shade()
{
	double x,y,step1,step2;
	fprintf(psfile,"gsave \n");
	fprintf(psfile,"clip \n");
	fprintf(psfile,"newpath  \n");
	fprintf(psfile,"0 setgray \n");
	step1 = g_cur_fill.b[B_B]/160.0;
	step2 = g_cur_fill.b[B_G]/160.0;

	fprintf(psfile,"%g setlinewidth\n",(double) g_cur_fill.b[B_R]/160.0);
	if (step1>0) {
	  fprintf(psfile,"%g %g %g { /x exch def \n",-40.0,step1,40.0);
	  fprintf(psfile,"x 0 moveto 40 x add 40 lineto stroke\n");
	  fprintf(psfile,"} for \n");
	}
	if (step2>0) {
	 fprintf(psfile,"%g %g %g { /x exch def \n",0.0,step2,80.0);
	 fprintf(psfile,"x 0 moveto -40 x add 40 lineto stroke\n");
	 fprintf(psfile,"} for \n");
	}
	fprintf(psfile,"grestore \n");
/*	d_set_line_width(g.lwidth); */
}
/*---------------------------------------------------------------------------*/
d_fill_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;
	fprintf(psfile,"gsave \n");
	fprintf(psfile,"newpath \n");
	fprintf(psfile,"%g %g moveto \n",(*wkx)[0],(*wky)[0]);
	for (i=1;i<nwk;i++)
		fprintf(psfile,"%g %g l \n",(*wkx)[i],(*wky)[i]);
	set_fill();
	fprintf(psfile,"fill \n");
	set_color();
	fprintf(psfile,"grestore \n");
}
d_line_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;
	fprintf(psfile,"gsave \n");
	fprintf(psfile,"newpath \n");
	fprintf(psfile,"%g %g moveto \n",(*wkx)[0],(*wky)[0]);
	for (i=1;i<nwk;i++)
		fprintf(psfile,"%g %g l \n",(*wkx)[i],(*wky)[i]);
	fprintf(psfile,"stroke \n");
	fprintf(psfile,"grestore \n");
}
/*---------------------------------------------------------------------------*/
d_stroke()
{
	fprintf(psfile,"gsave \n");
	fprintf(psfile,"stroke \n");
	fprintf(psfile,"grestore \n");
}
/*---------------------------------------------------------------------------*/
d_clip()
{
	fprintf(psfile,"clip \n");
}
/*---------------------------------------------------------------------------*/
d_set_matrix(double newmat[3][3])
{
	fprintf(psfile," [%g %g %g %g %g %g] umatrix \n ",
		newmat[0][0],newmat[1][0],newmat[0][1],
		newmat[1][1],newmat[0][2],newmat[1][2]);
}
/*---------------------------------------------------------------------------*/
d_move(double zx,double zy)
{
	if (g.inpath==true)
		fprintf(psfile,"%g %g moveto \n",zx,zy);
	else {
		ps_nvec++;
		fprintf(psfile,"%g %g m \n",zx,zy);
	}
}
/*---------------------------------------------------------------------------*/
d_reverse() 	/* reverse the order of stuff in the current path */
{
	fprintf(psfile,"reversepath \n");
}
/*---------------------------------------------------------------------------*/
d_closepath()
{
	fprintf(psfile,"closepath \n");
}
/*---------------------------------------------------------------------------*/
d_line(double zx,double zy)
{
	dbg gprint("in d_line  g.curx,y  %g %g ",g.curx,g.cury);
	if (g.xinline==false) {
		d_move(g.curx,g.cury);
	}
	ps_nvec++;
	if (ps_nvec>MAX_VECTOR) {
		gprint("Warning, complex path, if filling fails then try /nomaxpath \n");
		ps_nvec = 0; g_flush(); d_move(g.curx,g.cury);
	}
	if (fprintf(psfile,"%g %g l \n",zx,zy)==EOF) {
		perror("=========Unable to write to output file ");
	}
}
/*---------------------------------------------------------------------------*/
d_clear()
{
	int flipit;
	g_scale(72.0,72.0);
	g_scale(.393701,.393701);
	if (!dev_eps) g_translate(1.5,1.01);
	if ((!dev_eps) && (g.userwidth>g.userheight)) {
		fprintf(psfile,"%% Flipping coord system \n");
		g_move(0.0,0.0);
		g_rotate(90.0);
		g_translate(0.0,-g.userheight);
		g_move(0.0,0.0);
	}
}
/*---------------------------------------------------------------------------*/
d_flush()
{
	if (g.inpath) return;
	if (g.xinline) {
		fprintf(psfile,"stroke \n");
		ps_nvec = 0;
	}
}
/*---------------------------------------------------------------------------*/
d_arcto(dbl x1,dbl y1,dbl x2,dbl y2,dbl rrr)
{
	if (g.xinline==false)  d_move(g.curx,g.cury);
	fprintf(psfile,"%g %g %g %g %g arcto %g %g l \n",x1,y1,x2,y2,rrr,x2,y2);
	g.xinline = true;
}
/*---------------------------------------------------------------------------*/
d_arc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	double dx,dy;
	polar_xy(r,t1,&dx,&dy);
	if (!g.inpath) g_move(cx+dx,cy+dy);
	fprintf(psfile,"%g %g %g %g %g arc \n",cx,cy,r,t1,t2);
	g.xinline = true;
	if (!g.inpath) g_move(cx,cy);
}
/*---------------------------------------------------------------------------*/
d_narc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	double dx,dy;
	polar_xy(r,t1,&dx,&dy);
	if (!g.inpath) g_move(cx+dx,cy+dy);
	fprintf(psfile,"%g %g %g %g %g arcn \n",cx,cy,r,t1,t2);
	g.xinline = true;
	if (!g.inpath) g_move(cx,cy);
}
/*---------------------------------------------------------------------------*/
d_box_fill(dbl x1, dbl y1, dbl x2, dbl y2)
{
	if (g.inpath==true) xdbox(x1,y1,x2,y2);
	else {
		g_flush();
		fprintf(psfile," newpath ");
		xdbox(x1,y1,x2,y2);
		ddfill();
		fprintf(psfile,"newpath \n");
/*		set_fill();
		fprintf(psfile,"fill \n");
		set_color();
*/
	}
}
d_box_stroke(dbl x1, dbl y1, dbl x2, dbl y2)
{
	if (g.inpath==true) xdbox(x1,y1,x2,y2);
	else {
		g_flush();
		fprintf(psfile," newpath ");
		xdbox(x1,y1,x2,y2);
		fprintf(psfile,"stroke \n");
		ps_nvec = 0;
	}
}
/*---------------------------------------------------------------------------*/
xdbox(double x1, double y1, double x2, double y2)
{
   fprintf(psfile," %g %g moveto %g %g l %g %g l %g %g l closepath \n"
			,x1,y1,x2,y1,x2,y2,x1,y2);
}
/*---------------------------------------------------------------------------*/
d_circle_stroke(double zr)
{
	double x,y;
	g_get_xy(&x,&y);
	if (g.inpath==true)
		fprintf(psfile," %g %g %g 0 360 arc \n",x,y,zr);
	else {
		g_flush();
		fprintf(psfile," newpath ");
		fprintf(psfile," %g %g %g 0 360 arc \n",x,y,zr);
		fprintf(psfile,"stroke \n");
	}
}
d_circle_fill(double zr)
{
	double x=g.curx,y=g.cury;
	if (g.inpath==true)
		fprintf(psfile," %g %g %g 0 360 arc \n",x,y,zr);
	else {
		g_flush();
		fprintf(psfile,"newpath ");
		fprintf(psfile,"%g %g %g 0 360 arc \n",x,y,zr);
		ddfill();
		fprintf(psfile,"newpath \n");
/*

		set_fill();
		fprintf(psfile,"fill \n");
		set_color();
*/
	}
}
/*---------------------------------------------------------------------------*/
d_bezier(dbl x1,dbl y1,dbl x2,dbl y2,dbl x3,dbl y3)
{
	double x=g.curx,y=g.cury;
	if (g.inpath==true)
		fprintf(psfile,"%g %g %g %g %g %g curveto \n"
			,x1,y1,x2,y2,x3,y3);
	else {
		g_flush();
		if (!g.xinline) fprintf(psfile,"%g %g moveto ",x,y);
		fprintf(psfile,"%g %g %g %g %g %g curveto \n"
			,x1,y1,x2,y2,x3,y3);
		g.xinline = true;
	}
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
test_psfile()
{
	if (psfile==NULL) return;
	set_color();
}
set_color()
{
	if (BLACKANDWHITE) {
	 	fprintf(psfile,"%g setgray \n",((g_cur_color.b[B_R]*3.0/255.0
		+g_cur_color.b[B_G]*2.0/255.0+g_cur_color.b[B_B]/255.0) / 6));
	} else
	 	fprintf(psfile,"%g %g %g setrgbcolor \n",g_cur_color.b[B_R]/255.0
		,g_cur_color.b[B_G]/255.0,g_cur_color.b[B_B]/255.0);
}
set_fill()
{
	if (BLACKANDWHITE) {
	 	fprintf(psfile,"%g setgray \n",((g_cur_fill.b[B_R]*3.0/255.0
		+g_cur_fill.b[B_G]*2.0/255.0+g_cur_fill.b[B_B]/255.0) / 6));
	} else
	 	fprintf(psfile,"%g %g %g setrgbcolor \n",g_cur_fill.b[B_R]/255.0
		,g_cur_fill.b[B_G]/255.0,g_cur_fill.b[B_B]/255.0);
}
/*---------------------------------------------------------------------------*/
d_set_color(long f)
{
	g_flush();
	g_cur_color.l = f;
	set_color();
}
d_set_fill(long f)
{
	g_cur_fill.l = f;
}
/*---------------------------------------------------------------------------*/
d_beginclip()
{
	fprintf(psfile,"gsave \n");
}
d_endclip()
{
	char *state;
	g_flush();
	fprintf(psfile,"grestore \n");
	state = myallocz(300);
	g_get_state(state);
	g_set_state(state);
	myfree(state);
}
/*---------------------------------------------------------------------------*/
struct psfont_struct {char *sname; char *lname;} ;
struct psfont_struct psf[70] = { /* leaves room for twenty more from PSFONT.DAT*/
	"PSTR",		"Times-Roman",
	"PSTI",		"Times-Italic",
	"PSTB",		"Times-Bold",
	"PSTBI",	"Times-BoldItalic",
	"RM",		"Times-Roman",
	"RMI",		"Times-Italic",
	"RMB",		"Times-Bold",
	"RMBI",		"Times-BoldItalic",
	"SS",		"Helvetica",
	"SSB",		"Helvetica-Bold",
	"SSI",		"Helvetica-Oblique",
	"SSBI",		"Helvetica-BoldOblique",
	"PSH",		"Helvetica",
	"PSHB",		"Helvetica-Bold",
	"PSHBO",	"Helvetica-BoldOblique",
	"PSHO",		"Helvetica-Oblique",
	"PSAGB",	"AvantGarde-Book",
	"PSAGBO",	"AvantGarde-BookOblique",
	"PSAGD",	"AvantGarde-Demi",
	"PSAGDO",	"AvantGarde-DemiOblique",
	"PSBD",		"Bookman-Demi",
	"PSBDI",	"Bookman-DemiItalic",
	"PSBL",		"Bookman-Light",
	"PSBLI",	"Bookman-LightItalic",
	"PSC",		"Courier",
	"PSCB",		"Courier-Bold",
	"PSCBO",	"Courier-BoldOblique",
	"PSCO",		"Courier-Oblique",
	"TT",		"Courier",
	"TTB",		"Courier-Bold",
	"TTBI",		"Courier-BoldOblique",
	"TTI",		"Courier-Oblique",
	"PSNCSB",	"NewCenturySchlbk-Bold",
	"PSNCSBI",	"NewCenturySchlbk-BoldItalic",
	"PSNCSI",	"NewCenturySchlbk-Italic",
	"PSNCSR",	"NewCenturySchlbk-Roman",
	"PSPB",		"Palatino-Bold",
	"PSPBI",	"Palatino-BoldItalic",
	"PSPI",		"Palatino-Italic",
	"PSPR",		"Palatino-Roman",
	"PSZCMI",	"ZapfChancery-MediumItalic",
	"PSZD",		"ZapfDingbats",
	"PSSYM",	"Symbol",
	NULL,NULL
};
/*---------------------------------------------------------------------------*/
d_char(int font, int cc)
{
	double x,y;
	char *s;
	static int this_font;
	static double this_size;


	read_psfont();
	if (font_get_encoding(font)>2) {
		my_char(font,cc);
		return;
	}
	if (this_font!=font || this_size!=g.fontsz) {
		if (g.fontsz<0.00001) {
			gprint("Font size is zero, error ********* \n");
			return;
		}
		s = font_getname(font);
		for (i=0;;i++) {
			if (psf[i].sname==NULL) break;
			dbg printf("font match  {%s} {%s} \n",s,psf[i].sname);
			if (strcmp(psf[i].sname,s)==0) break;
		}
		if (psf[i].sname==NULL) {
			my_char(font,cc);
			return;
		}
		this_font = font;
		this_size = g.fontsz;
		fprintf(psfile," %f /%s f ",g.fontsz,psf[i].lname);
	}
	if (g.inpath==true) {
		if (isalnum(cc) && cc<127) fprintf(psfile,"(%c) ps ",cc);
		else  fprintf(psfile,"(\\%o) ps ",cc);
	} else {
		if (isalnum(cc) && cc<127) fprintf(psfile,"(%c) s ",cc);
		else  fprintf(psfile,"(\\%o) s ",cc);
	}
}
char *fontdir(char *s);
read_psfont()  /* add aditional ps fonts,  e.g.  pstr = TimesRoman */
{
	static init_done;
	FILE *fptr;
	char fname[80],*s;
	char inbuff[90];
	if (init_done) return;
	init_done = true;

	/* Find last used psf */
	for (i=0;;i++) if (psf[i].sname==NULL) break;

	strcpy(fname,fontdir("psfont.dat"));
	fptr = fopen(fname,"r");
	if (fptr==0) return; /* if not exists then don't bother */

	for (fgets(inbuff,200,fptr);!feof(fptr);fgets(inbuff,200,fptr)) {
		s = strchr(inbuff,'!');
		if (s!=NULL) *s=0;
		s = strtok(inbuff," \t,\n");
		if (s!=NULL) if (*s!='\n') {
			psf[i].sname = sdup(s);
			s = strtok(0," \t,\n");
			psf[i].lname = sdup(s);
			i++;
		}
	}
	psf[i].sname = NULL;
	psf[i].lname = NULL;
}
