/*--------------------------------------------------------------*/
/*	HPGL Driver 1.0 , for GLE V3.0		*/
/*---------------------------------------------------------------------------*/
#include "all.h"
#include <math.h>
#include "core.h"
#include "mygraph.h"
#include "mydev.h"
#define GS 29
#define FF 12
long hp_clipx, hp_clipy;
static long hpgl_addx, hpgl_addy;
extern int hpgl_size; /* a0, a1, a2, a3, a4 */
int ingraphmode;
extern struct gmodel g;
/*---------------------------------------------------------------------------*/
#define pi 3.141592653
#define true (!false)
#define BLACKANDWHITE 1
#define ESC 27
#define false 0
#define dbg if ((gle_debug & 64)>0)
#define stop if ((gle_debug & 128)>0) return
extern int gle_debug;
int incap=true;
int getch(void);
/*---------------------------------------------------------------------------*/
/* The global variables for the PC screen driver */
/*-----------------------------------------------*/

int i,l,j,ix,iy;
double f;
double devxcm,devycm;  /* settable via environment variables (or symbols*/
FILE *hpfile;

#define gerr() i = graphresult(); if (i!=0) printf("Graph error: %s \n",grapherrormsg(i));
#define sx(v) ( ((v) * d_xscale) + hpgl_addx)
#define sy(v) ( (((v) * d_yscale)) + hpgl_addy)
#define rx(v) ( ((v) * d_xscale))
#define ry(v) ( (((v) * d_yscale)))

double d_scale, d_xscale, d_yscale;
int d_graphmode;
int d_fillstyle=1,d_fillcolor;
int d_lstyle,d_lwidth;
char outstr[400];

d_devcmd(char *s)
{}
/*---------------------------------------------------------------------------*/
d_dfont(char *c)
{
	/* only used for the DFONT driver which builds fonts */
}
/*---------------------------------------------------------------------------*/
static char lastline[80];
d_message(char *s)
{
	static int single_step;
	int oldcolor,oldx,oldy;
	printf("%s\n",s);
}
/*---------------------------------------------------------------------------*/
d_source(char *s)
{
	s=s;
}
/*---------------------------------------------------------------------------*/
d_get_type(char *t)
{
	strcpy(t,"HARDCOPY, HPGL, VAX, PC");
}
/*---------------------------------------------------------------------------*/
d_set_path(int onoff)
{}
/*---------------------------------------------------------------------------*/
d_newpath()
{
}
/*---------------------------------------------------------------------------*/
extern char output_file[];
extern char input_file[];
d_open(double width, double height)
{
	char *outfile;
	char *s;
	char outfileb[90] = "out.hp";

	outfile = &outfileb[0];
	s = strrchr(input_file,'.');
	if (s!=NULL) {
		strcpy(outfile,input_file);
		s = strrchr(outfile,'.');
		strcpy(s,".hp");
	}
	if (output_file[0]!=0) outfile = &output_file[0];
#ifdef __TURBOC__
	printf("\n Writing output to file (%s) \n",outfile);
#endif
	hpfile = fopen(outfile,"w");
	if (hpfile == NULL) {
		gprint("Unable to HP output file {%s} \n",outfile);
		gle_abort("Unable to open HP output file \n");
	}

	hpgl_initstr(); /* read environment variables for set sequences */
	graphmode();
	ingraphmode = true;

	/* Get largest rectangle we can fit on the screen */
	d_scale = devxcm / width;
	f = devycm / height;
	if (f<d_scale) d_scale = f;
	if (d_scale<1) gprint("Shrinking picture to fit by factor %g \n",d_scale);
	if (d_scale>1) d_scale = 1; /* scale down not up */

	d_xscale = d_scale * 400; /*  MAXX / devxcm;  Device Scale X, Device Scale y */
	d_yscale = d_scale * 400; /*  MAXY / devycm; */

	hp_clipx = 400L * (devxcm) + 1;
	hp_clipy = 400L * (devxcm) + 1;

	g.userwidth = width;
	g.userheight = height;
	plotter_fonts();
}
/*---------------------------------------------------------------------------*/
d_tidyup()
{
	textmode();
}
d_close()
{

	g_flush();
	textmode();
}
/*---------------------------------------------------------------------------*/
d_set_line_cap(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_join(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_miterlimit(double d)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_width(double w)
{
}
/*---------------------------------------------------------------------------*/
d_set_line_styled(double dd)
{}
double lstylewidths[10]; /* widths */
int nlstyle=0;	/* number in array, if zero then solid line */
int lstylei=0;  /* entry we are drawing */
double lstylex=0;	/* distance along current entry */
int lstyleblack=true;
d_line_dash(double zx, double zy)
{
	double ix,iy,ux,uy,dx,dy,d,dd,ddx,ddy,nx,ny,totald;
	int newblack;
	dx = zx - g.curx; dy = zy - g.cury;
	d = sqrt(dx*dx + dy*dy);
	totald = d;
	if (totald==0) return;
	for (;d>0;) {
		if (d>(lstylewidths[lstylei]-lstylex)) {
			dd = lstylewidths[lstylei++]-lstylex;
			newblack = !lstyleblack;
			lstylex = 0;
			if (lstylei>=nlstyle) { lstylei = 0; newblack =true;}
		} else {
			dd = d;
			newblack = lstyleblack;
			lstylex += dd;
		}
		d -= dd;
		ddx = dx *   dd/totald;  ddy = dy*dd/totald;
		nx = g.curx + ddx; ny = g.cury + ddy;
		if (lstyleblack) dd_line(nx,ny); else g.xinline = false;
		g.curx = nx; g.cury = ny;
		lstyleblack = newblack;
	}
}
d_set_line_style(char *s)
{
	/* should deal with [] for solid lines */
	static char *defline[] = {"","","12","42","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++)
		lstylewidths[i] = (*(s+i)-'0')*g.lstyled;
	nlstyle = l;
}
/*---------------------------------------------------------------------------*/
d_fill()
{
}
/*---------------------------------------------------------------------------*/
d_fill_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;
/*	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]);
*/
}
d_line_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;
/*
	g_dev( (*wkx)[0], (*wky)[0], &ix, &iy);
	moveto(ix,iy);
	for (i=1;i<nwk;i++) {
		g_dev( (*wkx)[i], (*wky)[i], &ix, &iy);
		lineto(ix,iy);
	}
*/
}
/*---------------------------------------------------------------------------*/
d_stroke()
{
}
/*---------------------------------------------------------------------------*/
d_clip()
{
}
/*---------------------------------------------------------------------------*/
d_set_matrix(double newmat[3][3])
{
}
/*---------------------------------------------------------------------------*/
d_move(double zx,double zy)
{
}
/*---------------------------------------------------------------------------*/
d_reverse() 	/* reverse the order of stuff in the current path */
{
}
/*---------------------------------------------------------------------------*/
d_closepath()
{
	g_line(g.closex,g.closey);
}
/*---------------------------------------------------------------------------*/
int hpglxy(double xx, double yy);
d_line(double zx,double zy)
{
	if (nlstyle==0) dd_line(zx,zy);
	else d_line_dash(zx,zy);
}
dd_line(double zx,double zy)
{
	static double ix,iy,ux,uy;
	static double oldx= -1000,oldy= -1000;
	char s1[40],s2[40];
	if (g.xinline==false) {
		g_dev(g.curx,g.cury,&ux,&uy);
		if (oldx!=ux || oldy!=uy) {
		 strcat(outstr,"; PU ; PA ");
		 hpglxy(ux,uy);
		}
		strcat(outstr,"; PD ; PA ");
		g.xinline = true;
	}
	g_dev(zx,zy,&ix,&iy);
	hpglxy(ix,iy);
	oldx = ix; oldy = iy;
	if (strlen(outstr)>70) d_flush();
}
/*---------------------------------------------------------------------------*/
hpglxy(double xx, double yy)
{
	long x,y;
	char ss[30];
	x = sx(xx); y = sy(yy);
/* 	if (x<0) x = 0;
	if (x>hp_clipx) x = hp_clipx;
	if (y<0) y = 0;
	if (y>hp_clipy) y = hp_clipy;
*/
	sprintf(ss,"%ld %ld ",x,y);
	strcat(outstr,ss);
}
/*---------------------------------------------------------------------------*/
d_clear()
{
 }
/*---------------------------------------------------------------------------*/
d_flush()
{
	fprintf(hpfile,"%s;\n PA ",outstr);
	outstr[0] = 0;
}
/*---------------------------------------------------------------------------*/
d_arcto(dbl x1,dbl y1,dbl x2,dbl y2,dbl rrr)
{
	df_arcto(x1,y1,x2,y2,rrr);
}
/*---------------------------------------------------------------------------*/
d_arc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	df_arc(r,t1,t2,cx,cy);
}
/*---------------------------------------------------------------------------*/
d_narc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	df_arc(r,t1,t2,cx,cy);
}
/*---------------------------------------------------------------------------*/
d_box_fill(dbl x1, dbl y1, dbl x2, dbl y2)
{
	df_box_fill(x1,y1,x2,y2);
}
d_box_stroke(dbl x1, dbl y1, dbl x2, dbl y2)
{
	df_box_stroke(x1,y1,x2,y2);
}
/*---------------------------------------------------------------------------*/
d_circle_stroke(double zr)
{
	df_circle_stroke(zr);
}
d_circle_fill(double zr)
{
	df_circle_fill(zr);
}
/*---------------------------------------------------------------------------*/
d_bezier(dbl x1,dbl y1,dbl x2,dbl y2,dbl x3,dbl y3)
{
	double ax,bx,cx,ay,by,cy,dist;
	double xxx,yyy,i,t,nstep,x0,y0;
	g_get_xy(&x0,&y0);
	dist = fabs(x3-x0) + fabs(y3-y0);
	nstep = 10;
	if (dist>3) nstep = 20;
	if (dist<.5) nstep = 5;
	if (dist<.3) nstep = 3;
 	if (dist<.1) {
		g_line(x3,y3);
		return;
	}
	cx = (x1-x0)*3;
	bx = (x2-x1)*3-cx;
	ax = x3-x0-cx-bx;
	cy = (y1-y0)*3;
	by = (y2-y1)*3-cy;
	ay = y3-y0-cy-by;
	for (i=0;i<=nstep;i++) {
		t = i/nstep;
		xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
		yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
		g_line(xxx,yyy);
	}
}
/*---------------------------------------------------------------------------*/
d_set_color(long f)
{
	int i;
	char ss[50];
	colortyp  cc;
	cc.l = f;
	i = 1;
	if (cc.b[B_R]>100) i = 2;
	if (cc.b[B_G]>100) i = 3;
	if (cc.b[B_B]>100) i = 4;
	if (cc.b[B_R]>100 && cc.b[B_G]>100) i = 5;
	if (cc.b[B_B]>100 && cc.b[B_G]>100) i = 5;
	if (cc.b[B_R]>250 && cc.b[B_G]>250 && cc.b[B_B]>250) i = 6;
	sprintf(ss,"; SP%d ; PA ",i);
	strcat(outstr,ss);
}
d_set_fill(long f)
{
}
/*---------------------------------------------------------------------------*/
d_beginclip()
{
}
d_endclip()
{
}
struct char_data {float wx,wy,x1,y1,x2,y2; };
int font_get_chardata(struct char_data **cd, int ff, int cc);
/*---------------------------------------------------------------------------*/
d_char(int font, int cc)
{
	static struct char_data cd;
	static int ix,iy,ix1,ix2,iy1,iy2,fz,fzx;
	static int ux,uy;
	static int safnt;
	char ss[2];

	ss[0] = cc;
	ss[1] = 0;
	if (safnt==0) safnt = pass_font("PLSR");
	if (font>=2) {
		my_char(font,cc);
		return;
	}
	my_char(safnt,cc);
}
char *hpglopenstr,*hpglclosestr;
int inithpgl;
graphmode()
{
	if (!inithpgl) hpgl_initstr();
	ingraphmode = true;
	fprintf(hpfile,"%s\n",hpglopenstr);
}
textmode()
{
	if (!inithpgl) hpgl_initstr();
	fprintf(hpfile,";\n %s \n",hpglclosestr);
	ingraphmode = false;
}
char *cvt_control(char *mystr);
char *cvt_control(char *xx)
{
	char *s;
	static char mystr[200];
	strcpy(mystr,xx);
loop1:	s = strchr(mystr,'^');
	if (s!=NULL) {
		*(s+1) = *(s+1) - 64;
		memmove(s,s+1,strlen(s+1)+1);
		goto loop1;
	}
	return mystr;
}
double getsymvalue(char *sym, double dflt);
char *getsymbol(char *sym);
double getsymvalue(char *sym, double dflt)
{
	char *s;
	s = getsymbol(sym);
	if (strlen(s)==0) return dflt;
	return atof(s);
}
hpgl_initstr()
{
	char  *s;
	double def_x,def_y;
	inithpgl = true;
	s = getsymbol("HPGL_OPEN");
	/* Init plotter and scale so that 400 units = 1cm */
	/* s = "^[.(^[.I;;17:^[.N;19:IN;IP 520,1140,15720,11140; sc 120,15320,540,10540;PU;VS10;SP1;PA;PU;"; */


	if (strlen(s)==0) s = "^[.(^[.I;;17:^[.N;19:IN;IP ;PU;VS10;SP1;PA;PU;";
	hpglopenstr = sdup(cvt_control(s));
	devxcm = getsymvalue("HPGL_WIDTH",200);
	devycm = getsymvalue("HPGL_HEIGHT",200);
	def_x = .9; def_y = 1.5;
	if (hpgl_size==0) { def_x = -22190.0/400; def_y = -15740.0/400; }
	if (hpgl_size==1) { def_x = -15120.0/400; def_y = -10760.0/400; }
	hpgl_addx = 400*getsymvalue("HPGL_ADDX",def_x);
	hpgl_addy = 400*getsymvalue("HPGL_ADDY",def_y);

	/* printf("width %g hei %g str {%s} \n",devxcm,devycm,s); */
	s = getsymbol("HPGL_CLOSE");
	/* Advance Full and cut page */
	if (strlen(s)==0) s = "SP0;IN;AF;^[.)";
/*	if (strlen(s)==0) s = "SP0;IN;AH;^[.)"; */
	hpglclosestr = sdup(cvt_control(s));
}
