#ifdef __TURBOC__
extern unsigned _stklen=20000;
#include <alloc.h>
#endif
#include "all.h"
#include <math.h>
#include "core.h"
#include "mygraph.h"
#include "mydev.h"
#ifndef __TURBOC__
#define huge
#endif
#define true (!false)
#define false 0
int d_open(double x, double y);
int dvitype(void);
int draw_file(void);
#define scx(v) ( ((v) * d_xscale))
#define scy(v) ( ((v) * d_yscale))
#define rx(v) ( ((v) * d_xscale))
#define ry(v) ( ((v) * d_yscale))
int gdebug=false;
int nxbits,nybits;
int flipit;
#define dbg if (gdebug==true)

double d_scale, d_xscale, d_yscale;

int set_grey(float cur_fill);
int setbitlwidth(float w);
int setbitlstyle(int n);
int path_bezier(float x1, float y1, float x2, float y2, float x3, float y3);
int path_row(float x1, float y1, float x2, float y2);
int path_box(float x1, float y1, float x2, float y2);
int path_alloc(void);
int path_move(float x1, float y1);
int path_line(float x1, float y1);
int flatten_bezier(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
int path_closepath(void);
int bitmap_print(void);
int bitmap_free(void);
int bitmap_alloc(void);
int bitmap_paint(int row, int x1, int x2);
int bitmap_pixel(int x, int y);
int intline(int  x1, int  y1, int  x2, int  y2);
int intbezier(float x0, float y0,float x1, float y1, float x2, float y2, float x3, float y3);
#include "pathtypes.h"
int hp_plus,dev_low;
char outfile[80];
FILE *inf,*outf;
int lj;
float uwidth,uheight;
/*---------------------------------------------------------------------------*/
char outbitname[120];
FILE *outbit;
main(int argc, char **argv)
{
	int i;
	inf = fopen("out.dvi","rb");
	if (inf==NULL) {
		printf("Unable to open OUT.DVI for input, run DVIGLE first\n");
		gle_abort("");
	}


	i = 1;
	hp_plus = true;
	for (i=1;i<argc; i++) {
		if (strncmp(argv[i],"-o",2)==0) hp_plus = false;
		else if (strncmp(argv[i],"/o",2)==0) hp_plus = false;
		else if (strncmp(argv[i],"/l",2)==0) dev_low = true;
		else if (strncmp(argv[i],"-l",2)==0) dev_low = true;
		else if (strncmp(argv[i],"-d",2)==0) gdebug = true;
		else strcpy(outbitname,argv[i]);
	}
	dvitype();  printf("\n");
#if __TURBOC__
	if (strlen(outbitname)!=0) {
	  printf("Writing output to file {%s} \n",outbitname);
	  outbit = fopen(outbitname,"wb");
	} else 	printf("Printing to LPT1 \n");
#else
            /* Special binary open for VMS */
	printf("Writing output to file {%s} \n",outbitname);
#ifdef unix
        if ((outbit = fopen(outbitname,"wb")) == NULL)
#else
        if ((outbit = fopen (outbitname,"wb","rfm=fix","bls=512","mrs=512")) == NULL)
#endif
        {   printf ("Can't open output bitmap file.\n");
            abort();
        }
#endif

	draw_file();
	close_output();
}
/*---------------------------------------------------------------------------*/
/*   Path variables for bitmap */
typedef union {int32 l; float f;} longfloat;
longfloat *path;
int npath;
int npath_alloc;
longfloat pth[100];
int npth;

int file_end = false;
float getf(void);
float getfx(void)
{
	static float x;
	fread(&x,sizeof(x),1,inf);
	if (feof(inf)) file_end = true;
	return scx(x);
}
int getfxy(float *x, float *y);
getfxy(float *x, float *y)
{
	float u,xx,yy;
	xx = getf();
	yy = getf();
	if (flipit) {
		u = yy;
		yy = uwidth - xx;
		xx = u;
	}
	*x = scx(xx);
	*y = scy(yy);
}
float getfy(void)
{
	static float x;
	fread(&x,sizeof(x),1,inf);
	if (feof(inf)) file_end = true;
	return scy(x);
}
float getf(void)
{
	static float x;
	fread(&x,sizeof(x),1,inf);
	if (feof(inf)) file_end = true;
	return x;
}
int32 getl(void)
{
	static int32 x;
	fread(&x,sizeof(x),1,inf);
	if (feof(inf)) file_end = true;
	return x;
}
float cur_lwidth,cur_color,cur_fill;
int coltab[]={7,6,5,3,4,1,2,0,6,3,5,4,2};
int cur_colori, cur_filli;
int32 cur_lstyle;
draw_file(void)
{
	float x,y,cx,cy,x2,y2,x3,y3,sx,sy;
	int32 i;
	set_grey(0.0);
	for (;!file_end;) {
	  i = getl();
	  if (file_end) break;
	  switch (i) {
		case p_size:
			dbg printf("size \n");
			x = getf(); y = getf();
			d_open(x,y);
		case p_newpath:
			dbg printf("newpath \n");
			npath = 0;
			break;
		case p_move:
			getfxy(&x,&y);
			cx = x; cy = y;
			dbg printf("move (%d) %g %g  \n",npath,x,y);
			path_move(x,y);
			sx = cx; sy = cy;
			break;
		case p_line:
			getfxy(&x,&y);
			cx = x; cy = y;
			dbg printf("line (%d) %g %g  \n",npath,x,y);
			path_line(x,y);
			break;
		case p_closepath:
			path_closepath();
			cx = sx; cy = sy;
			break;
		case p_dline:
			getfxy(&x,&y);
			intline(cx+.5,cy+.5,x+.5,y+.5);
			npath = 0;
			dbg printf("dline %g %g %g %g  \n",cx,cy,x,y);
			cx = x; cy = y;
			break;
		case p_bezier:
			getfxy(&x,&y);
			getfxy(&x2,&y2);
			getfxy(&x3,&y3);
			path_bezier(x,y,x2,y2,x3,y3);
			dbg printf("bezier (%d)\n",npath);
			cx = x3; cy = y3;
			break;
		case p_stroke:
			dbg printf("stroke \n");
			path_stroke();
			break;
		case p_fill:
			dbg printf("fill \n");
			path_fill();
			break;
		case p_lwidth:
			dbg printf("lwidth \n");
			cur_lwidth = getf();
			setbitlwidth(cur_lwidth);
			break;
		case p_lstyle:
			dbg printf("lstyle \n");
			cur_lstyle = getl();
			setbitlstyle(cur_lstyle);
			break;
		case p_setfilli:
			cur_filli = coltab[getl()];
			break;
		case p_setcolori:
			cur_colori = coltab[getl()];
			break;
		case p_setcolor:
			cur_color = getf();
			dbg printf("setcolor %f\n",cur_color);
			break;
		case p_setfill:
			cur_fill = getf();
			dbg printf("setfill %f\n",cur_fill);
			set_grey(cur_fill);
			break;
		case p_null:
			dbg printf("Null \n");
			break;
		default:
			printf("Error in PATH codes in .DVI file %ld %d\n",i,p_setcolori);
			break;
	  }
	}
	d_close();
}
gle_abort(char *s)
{
	exit(1);
}
/*--------------------------------------------------------------*/
/*	Bitmap output for EPSON printers 			*/
/*--------------------------------------------------------------*/
int bitmap_print(void);
char *bitmap_line(int y);
int bitmap_size(int *xbits, int *ybits, double *width, double *height);
/*--------------------------------------------------------------*/
/*	Genric Bitmap pathed Driver 1.0 (VAX C, TURBO  C) , for GLE V3.0 */
/*--------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int gunit;
struct gmodel g;
/*---------------------------------------------------------------------------*/
double xsizecm,ysizecm;
#define ROW_WIDTH 19
int (huge *rows)[ROW_WIDTH];
#define pi 3.141592653
#define true (!false)
#define SOLID_LINE 1
#define DASHED_LINE 2
#define BLACKANDWHITE 1
#define false 0
int gle_debug;
int getch(void);
int kbhit(void);
/*---------------------------------------------------------------------------*/
int d_graphmode;
int d_fillstyle=1,d_fillcolor;
int d_lstyle,d_lwidth,d_color;
int d_maxy;
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* -ve is used to indicate up or down */
int row_min,row_max;
unsigned int pcount;
static int lastany = true,ffup = 3,*ffp,*lastp,ffr,ffv;
static float ffx= -1,ffy= -1,lastx= -1,lasty= -1,cx= -1,cy= -1;
path_pcount()
{
	pcount = 1;
}
path_reset()
{
	ffx = -1; ffy = -1; ffup = 3;  ffp = 0;
	ffr = 0; ffv = 0;
	lastany = true;
	lastp = 0;
	lastx = -1; lasty = -1;
	cx = -1; cy = -1;
}
int setrowpnt(int x2, int y2,char *s);
path_row(float x1, float y1, float x2, float y2)
{
	float dx,dy,a,b,yfix,y2fix,oldx,oldy;
	int i,j,k,r,huge *m,isup=true,nofix=false,minmax=false;
	int start,end;
	unsigned int huge *p;
	static int lastup;
	float oy1,oy2,ox2,ox1;
	int ee;
	int enddot=false;

	dbg printf("path row %5.4g %5.4g -- %5.4g %5.4g   (%5.4g %5.4g)  (cy = %g) up=%d \n",x1,y1,x2,y2,x2-x1,y2-y1
			,cy,lastup);

	oy1 = y1; oy2 = y2; ox2 = x2; ox1 = x1;
	if (ffx != -1) {
		if (ffx == x2 && ffy == y2) {
			enddot = true;
		}
	}
	if (ffx == -1) { ffx = ox1; ffy = oy1; }

	if (y2==y1) goto exitrow;
	if (y1>y2) {     /* downward line swap around so line is upwards */
		isup = false;
		dx = x1; dy = y1; x1 = x2; y1 = y2; x2 = dx; y2 = dy;
	} else  {
	}
	dy = y2-y1; dx = x2-x1;
	a = dx/dy;
	b = x1 - a*y1;

	y2 = floor(y2) ;
	y1 = floor(y1+1) ;

	if (enddot) if (isup) {
		if (lastup) y2 = y2 - 1;
	} else {
		if (!lastup) y1 = y1 + 1;
	}

	if (isup) {
		if (lastup && cy==y1 && !lastany) y1 = y1 + 1;
		start = y1; end = y2;
	} else {
		if (!lastup && cy==y2 && !lastany) y2 = y2 - 1;
		start = y2; end = y1;
	}
	if (enddot && y1>y2) {
		if ((isup != lastup) && !lastany) {
			if (lastp!=NULL) *lastp = *lastp | (pcount << 12) ;
			lastp = 0;
			for (r=0;rows[ffr][r]!=0 && rows[ffr][r]!=ffv; r++) ;
			ffp = &rows[ffr][r];
			if (*ffp != 0) *ffp = *ffp | (pcount <<12);
			pcount++;
		}
	}
	if (y1>y2) return;
	if ((isup != lastup) && !lastany) minmax = true;
	if (isup) cy = y2; else cy=y1;
	if (pcount==15) {printf("pcount is too big \n"); pcount=1; }

	lastup = isup;
	if (ffup==3) ffup = lastup;

	  if (minmax) {
		if (lastp!=NULL) *lastp = *lastp |(pcount <<12);
		lastp = 0;
	  }


	lastany = false;
	if (y1<0) y1 = 0;
	if (y2>=nybits) y2 = nybits-1;
	for (i = y1; i<=y2 ; i++) {
	  if (i<row_min) row_min = i;
	  if (i>row_max) row_max = i;
	  k = a*(i)+b+1;
	  for (p = &rows[i][0]; k > (0x0fff & *p) && *p!=NULL; p++) ;
	  for (ee = 0; rows[i][ee] != 0  && ee<=17; ee++) ;
	  if (ee>=17) printf("Warning, path is too complex\n");
	  rows[i][ee+1] = 0;
	  for (m = &rows[i][ee]; m >= p; m--) {
		*m = *(m-1);
	  }
	  *p = k;
	  if (ffr == 0) if (i==start) { ffr = i; ffv=k; ffup = isup;}
	  if (minmax) if ((i==start)) {
		*p = *p | (pcount << 12);

		pcount++;
	  }
	  if (enddot && (ffup != isup)) if (i==end) {
		*p = *p | (pcount << 12);
			for (r=0;rows[ffr][r]!=0 && rows[ffr][r]!=ffv; r++) ;
			ffp = &rows[ffr][r];
			if (*ffp != 0) *ffp = *ffp | (pcount << 12);
		pcount++;
	  }
	  if (i==end) lastp = p;
   dbg printf("after %d, %x %x %x %x %x %x:(%d)  pc=%x \n",i,rows[i][0],rows[i][1]
		,rows[i][2],rows[i][3],rows[i][4],rows[i][5],k,pcount);
	}
	exitrow:;
}
check()
{
	int i=160;
	dbg printf("check %d, %d %d %d %d %d %d \n",i,rows[i][0],rows[i][1]
		,rows[i][2],rows[i][3],rows[i][4],rows[i][5]);
 }

setrowpnt(int k,int i,char *s)
{
	int ee,*p,*m;
       dbg	printf("pnt %s ",s);
	if (i>=nybits || i < 0 ) return;
	k+=1;
	for (p = &rows[i][0]; k > *p && *p!=NULL; p++) ;
	for (ee = 0; rows[i][ee] != 0  && ee<=10; ee++) ;
	  if (i<row_min) row_min = i;
	  if (i>row_max) row_max = i;
	rows[i][ee+1] = 0;
	for (m = &rows[i][ee]; m >= p; m--) {
		*m = *(m-1);
	}
	*p = k;
	 dbg printf("xxafter %d,  %x %x %x %x %x %x    (%d)  \n",i,rows[i][0],rows[i][1]
		,rows[i][2],rows[i][3],rows[i][4],rows[i][5],k);
}
path_fill(void)
{
	float sx=0,sy=0,cx=0,cy=0,x1,y1,x2,y2,x3,y3;
	int closed=true;
	int i,j,p1,p2;
	row_min = 20000; row_max = 0;
	path_pcount();
       dbg	printf("fill, npath %d \n",npath);
	for (i=0;i<npath;i++) {
	  switch(path[i].l) {
	    case p_move:
		if (!closed) if (cx!=sx || cy!=sy) path_row(cx,cy,sx,sy);
		path_reset();
		sx = path[++i].f;
		sy = path[++i].f;
		cx = sx; cy = sy;
		break;
	    case p_line:
		x1 = path[++i].f;
		y1 = path[++i].f;
		path_row(cx,cy,x1,y1);
		cx = x1; cy = y1;
		break;
	    case p_bezier:
		closed = false;
		x1 = path[++i].f;  y1 = path[++i].f;
		x2 = path[++i].f;  y2 = path[++i].f;
		x3 = path[++i].f;  y3 = path[++i].f;
		flatten_bezier(cx,cy,x1,y1,x2,y2,x3,y3);
		cx = x3; cy = y3;
		break;
	    case p_closepath:
		if (cx!=sx || cy!=sy) path_row(cx,cy,sx,sy);
		closed = true;
		cx = sx; cy = sy;
		break;
	    default:
		printf("Error in path_fill code path[%d] %ld \n",i,path[i].l);
	  }
	}

	if (row_max >= nybits) row_max = nybits-1;
	if (row_min < 0) row_min = 0;

	dbg printf("fill rows %d %d \n",row_min,row_max);
	for (i=row_min; i<=row_max; i++) {
	  for (j=0; rows[i][j] != 0; j+=2) {
		p1 = rows[i][j];
		p2 = rows[i][j+1];
		if ((p2 & 0xf000)!=0) if ((rows[i][j+2] & 0xf000)!=0) {
		  if ((p2 & 0xf000) == (rows[i][j+2] & 0xf000)) {
			p2=rows[i][j+3]; j+=2;
		  }
		}
		p1 = p1 & 0x0fff; p2 = p2 & 0x0fff;
		dbg printf("paint %d  (%d  %d)   %d %d\n",i,rows[i][j],rows[i][j+1],p1,p2);
		bitmap_paint(i,p1 & 0x0fff,p2 & 0x0fff);
		check();
	  }
	  rows[i][0] = 0; /* clear row for next fill */
	}


}
path_stroke(void)
{
	float sx=0,sy=0,cx=0,cy=0,x1,y1,x2,y2,x3,y3;
	int closed=true;
	int i,j,savepath;

	savepath = g.inpath;
	g.inpath = false;
	for (i=0;i<npath;i++) {
	  switch(path[i].l) {
	    case p_move:
		sx = path[++i].f;
		sy = path[++i].f;
		cx = sx; cy = sy;
		break;
	    case p_line:
		x1 = path[++i].f;
		y1 = path[++i].f;
		intline(cx+.5,cy+.5,x1+.5,y1+.5);
		cx = x1; cy = y1;
		break;
	    case p_bezier:
		closed = false;
		x1 = path[++i].f;  y1 = path[++i].f;
		x2 = path[++i].f;  y2 = path[++i].f;
		x3 = path[++i].f;  y3 = path[++i].f;
		intbezier(cx,cy,x1,y1,x2,y2,x3,y3);
		cx = x3; cy = y3;
		break;
	    case p_closepath:
		intline(cx+.5,cy+.5,sx+.5,sy+.5);
		break;
	    default:
		printf("Error in path_stroke code \n");
	  }
	}
}
path_move(float x,float y)
{
	path_alloc();
	path[npath++].l = p_move;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_line(float x,float y)
{
	path_alloc();
	path[npath++].l = p_line;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_bezier(float x1, float y1, float x2, float y2,float x3, float y3)
{
	path_alloc();
	path[npath++].l = p_bezier;
	path[npath++].f = x1;	path[npath++].f = y1;
	path[npath++].f = x2;	path[npath++].f = y2;
	path[npath++].f = x3;	path[npath++].f = y3;
}
path_closepath()
{
	path_alloc();
	path[npath++].l = p_closepath;
}
path_box(float x1, float y1, float x2, float y2)
{
	path_move(x1,y1);
	path_line(x2,y1);
	path_line(x2,y2);
	path_line(x1,y2);
	path_closepath();
}
path_alloc(void)
{
	static int npa;
	int32 *a;
	if (npath < (npath_alloc-20)) return;
	npath_alloc = 20 + 2 * npath;
	a = calloc(1,npath_alloc*sizeof(int32));
	if (a==NULL) {
		gle_abort("Unable to allocate memory for path \n");
	}
	dbg printf("path allocate %d \n",npa);
	if (path != NULL) {
		dbg printf("path reallocate, copy \n");
		memcpy(a,path,(npa)*sizeof(int32));
		free(path);
	}
	npa = npath_alloc;
	path = a;
}
path_free(void)
{
	if (path==NULL) return;
	free(path);
	path = NULL;
	npath = 0;
	npath_alloc = 0;
}
/*---------------------------------------------------------------------------*/

d_devcmd(char *s)
{}
/*---------------------------------------------------------------------------*/
d_dfont(char *c)
{
	/* only used for the DFONT driver which builds fonts (never used)*/
}
/*---------------------------------------------------------------------------*/
d_message(char *s)
{
	printf("%s\n",s);
}
/*---------------------------------------------------------------------------*/
d_source(char *s)
{
	s=s;
}
/*---------------------------------------------------------------------------*/
d_get_type(char *t)
{
	strcpy(t,"OUTPUT, BITMAP, BLACKANDWHITE, HARDCOPY");
}
/*---------------------------------------------------------------------------*/
d_set_path(int onoff)
{}
/*---------------------------------------------------------------------------*/
d_newpath()
{
	npath = 0;
}
/*---------------------------------------------------------------------------*/
int fittobit; /* modified in DVIWP */
int bitmap_size(int *xpix, int *ypix, double *width, double *height);
d_open(double width, double height)
{
	double f,f1,f2,fx,fy;
	/* nxbits, nybits, xsizecm, ysizecm */
	/* Get largest rectangle we can fit on the screen */

	bitmap_size(&nxbits, &nybits, &xsizecm, &ysizecm);
#if __TURBOC__
	rows = farcalloc(sizeof(int)*ROW_WIDTH,nybits+30);
#else
	rows = calloc(sizeof(int)*ROW_WIDTH,nybits+30);
#endif
	if (rows==0) printf("Unable to allocate rows %d %d\n",
		sizeof(int)*ROW_WIDTH,nybits+30);
	dbg printf("allocated rows %d %d\n",
		sizeof(int)*ROW_WIDTH,nybits+30);
	dbg printf("Allcate rows %ld\n",sizeof(int)*(int32) nybits*ROW_WIDTH+30);
	showfree();
	if (rows==NULL) gle_abort("Unable to allocate row array\n");
	uwidth = width; uheight = height;


	d_scale = xsizecm / width;
	f = ysizecm / height;
	if (f<d_scale) d_scale = f;

	if (fittobit) {
		fx = xsizecm / width;
		d_scale = 1;
		fy = ysizecm / height;
	}
	if (d_scale<.98) {
		if (width>height) {
			d_scale = ysizecm/width;
			f = xsizecm/height;
			if (f<d_scale) d_scale = f;
			flipit = true;
			printf("Flipping graph to fit on page better \n");
		}
	}

	bitmap_alloc();

	/* Get correct size of drawing */

	if (d_scale > 1.001) d_scale = 1;
	else {
		if (d_scale < .99) printf("Squashing onto page by factor %g \n",d_scale);
	}

	d_xscale = d_scale * (nxbits-2) / xsizecm; /* Device Scale X, Device Scale y */
	d_yscale = d_scale * (nybits-2) / ysizecm;
	if (fittobit) {
		d_xscale = fx * (nxbits-2) / xsizecm;
		d_yscale = fy * (nybits-2) / ysizecm;
	}
}
/*---------------------------------------------------------------------------*/
d_tidyup()
{
	printf("AARRRrrrrgg,  Dieing\n");
}
showfree()
{
#ifdef __TURBOC__
	struct heapinfo hi;
	hi.ptr = NULL;
	dbg printf("Heapcheck %d ",heapcheck());
/*	printf("Core memory left %ld \n",coreleft()); */
	dbg while (heapwalk(&hi)== _HEAPOK)
		printf("%ld   %s\n",hi.size,hi.in_use ? "used" : "free");
#endif
}
d_close()
{
	d_flush();
	showfree();
	if (rows!=NULL) free(rows);
	path_free();
	showfree();
	bitmap_print();
	bitmap_free();
}
/*---------------------------------------------------------------------------*/
d_set_line_cap(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_join(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_miterlimit(double d)
{
	int i=0;
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_width(double w)
{
	d_lwidth = 1;
	if (w>.099) d_lwidth = 3;
}
/*---------------------------------------------------------------------------*/
d_set_line_styled(double dd)
{}
d_set_line_style(char *s)
{
	d_lstyle = DASHED_LINE;
	if (strcmp(s,"")==0) d_lstyle = SOLID_LINE;
	if (strcmp(s,"1")==0) d_lstyle = SOLID_LINE;
}
/*---------------------------------------------------------------------------*/
d_fill()
{
	path_fill();
}
/*---------------------------------------------------------------------------*/
d_fill_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;

	path_move( (*wkx)[0], (*wky)[0]);
	for (i=1;i<nwk;i++) {
		path_line( (*wkx)[i], (*wky)[i]);
	}
	d_fill();
}
d_line_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;

	path_move( (*wkx)[0], (*wky)[0]);
	for (i=1;i<nwk;i++) {
		path_line( (*wkx)[i], (*wky)[i]);
	}
	d_stroke();
}
/*---------------------------------------------------------------------------*/
d_stroke()
{
	path_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()
{
	path_closepath();
}
int bit_line( double x, double y);
/*---------------------------------------------------------------------------*/
intbezier(float x0, float y0,float x1, float y1, float x2, float y2, float x3, float y3)
{
	float ax,bx,cx,ay,by,cy,dist,xx,yy;
	float xxx,yyy,i,t,nstep;
	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) {
		intline(x0+.5,y0+.5,x3+.5,y3+.5);
		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;
	xx = x0; yy = y0;
	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;
		intline(xx+.5,yy+.5,xxx+.5,yyy+.5);
		xx = xxx; yy = yyy;
	}
}

uint32 PATTERN = 0xFFFFFFFF;
int LINEWIDTH=1;
setbitlstyle(int n)
{
	uint32 style_type[9] = {0xffffffff,
		0xffffffff, 0xc0c0c0c0, 0xff00ff00, 0xfff0fff0
		,0xffff0000, 0xfffff0f0, 0xf00000f0, 0xf0f0f0f0};
	if (n>8) n = 8;
	PATTERN = style_type[n];
}
setbitlwidth(float w)
{
	if (w==0) LINEWIDTH=1;
	else {
		LINEWIDTH = scx(w);
	}
	if (LINEWIDTH<=1) LINEWIDTH=1;
}
intline(int  x1, int  y1, int  x2, int  y2)
{
#define sign(x) ((x) > 0 ? 1:  ((x) == 0 ? 0:  (-1)))
	int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy, x, y;
	static uint32 mask=0x80000000;

	if (x1<0) x1 = 0;
	if (x1>nxbits) x1 = nxbits-1;
	if (y1<0) y1 = 0;
	if (y1>nybits) y1 = nybits-1;
	if (x2<0) x2 = 0;
	if (x2>nxbits) x2 = nxbits-1;
	if (y2<0) y2 = 0;
	if (y2>nybits) y2 = nybits-1;

	/* line algorithym begins */


	dx = x2 - x1;
	dy = y2 - y1;
	sdx = sign(dx);
	sdy = sign(dy);
	dxabs = abs(dx);
	dyabs = abs(dy);
	x = 0;
	y = 0;
	px = x1;
	py = y1;



	if (dxabs >= dyabs)
	{

			mask = mask ? mask : 0x80000000;
			if (PATTERN & mask)
		        {
				for (j= -LINEWIDTH/2; j<=LINEWIDTH/2; j++)
					bitmap_pixel(px,py+j);
			}
			mask >>= 1;



		for (i=0; i<dxabs; i++)
		{
			mask = mask ? mask : 0x80000000;
			y += dyabs;
			if (y>=dxabs)
			{
				y -= dxabs;
				py += sdy;
			}
			px += sdx;
			if (PATTERN & mask)
		        {
				for (j= -LINEWIDTH/2; j<=LINEWIDTH/2; j++)
					bitmap_pixel(px,py+j);
			}
			mask >>= 1;
		}
	}
	else
	{
			mask = mask ? mask : 0x80000000;
			if (PATTERN & mask)
		        {
				for (j= -LINEWIDTH/2; j<=LINEWIDTH/2; j++)
					bitmap_pixel(px+j,py);
			}
			mask >>= 1;

		for (i=0; i<dyabs; i++)
		{
			mask = mask ? mask : 0x80000000;
			x += dxabs;
			if (x>=dyabs)
			{
				x -= dyabs;
				px += sdx;
        		}
			py += sdy;
			if (PATTERN & mask)
			{
				for (j= -LINEWIDTH/2; j<=LINEWIDTH/2; j++)
					bitmap_pixel(px+j,py);
			}
		        mask >>= 1;
		}
	}
}

/*---------------------------------------------------------------------------*/
d_clear()
{
	d_lstyle = SOLID_LINE;
	d_lwidth = 1;

}
/*---------------------------------------------------------------------------*/
d_flush()
{
}
flatten_bezier(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
	float  ax,bx,cx,ay,by,cy,dist;
	float xxx,yyy,i,t,nstep,xx,yy;
	dist = fabs(x3-x0) + fabs(y3-y0);
	nstep = 12;
	if (dist<1) nstep = 7;
	if (dist<.5) nstep = 3;
	if (dist<.1) {
		path_row(x0,y0,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;
	xx = x0;
	yy = y0;
	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;
		path_row(xx,yy,xxx,yyy);
		xx = xxx; yy = yyy;
	}
}
d_beginclip()
{
}
d_endclip()
{
}


#ifdef __TURBOC__
#include <dos.h>
char put_out(char c);
int status(void);
status(void)
{
	union REGS reg;

	reg.h.ah = 2;
	reg.x.dx = 0;
	int86(0x17, &reg, &reg);
	return (reg.h.ah & 0x80);
}
char put_out(char c)
{
	union REGS reg;
	int w=0;
	int ft=0;

	if (outbit!=NULL) {
		fputc(c,outbit);
		return;
	}
	while (!status()) {
		w++;
		if (w>10000) if (ft==0) {printf("Printer Busy "); w=0; ft=1;}
		if (w>10000) {printf(".");  w=0;}
	}
	if (ft==1) printf("\n");
	reg.h.ah = 0;
	reg.h.al = c;
	reg.x.dx = 0;
	int86(0x17,&reg,&reg);
	return (reg.h.ah);
}
close_output()
{
	if (outbit!=NULL) fclose(outbit);
}

#else

#include <stdio.h>
#ifdef VAXC
#include <file.h>
#endif
char zzbuff[512];
int nzz=0;
put_out(char c)
{
	zzbuff[nzz++] = c;
	if (nzz==512) {
	    fwrite(zzbuff,nzz,1,outbit);
	    nzz = 0;
	}
}
close_output()
{
	if (nzz > 0)  fwrite(zzbuff,nzz,1,outbit);
	fclose(outbit);
}

#endif

#ifndef unix
int printmem(char *s, int n);
void pprintf(va_list arg_list, ...)
{
 	va_list arg_ptr;
 	char *format;
	char output[200];

 	va_start(arg_ptr, arg_list);
 	format = arg_list;
 	vsprintf(output, format, arg_ptr);
	printmem(output,strlen(output));
}
#endif
printmem(char *s, int n)
{
	for (;n>0;n--) put_out(*s++);
}

