/*--------------------------------------------------------------*/
/*	IBM PC Driver 1.0 (TURBO  C) , for GLE V3.0		*/
/*--------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
#include "all.h"
#include <graphics.h>
#include <math.h>
#include "core.h"
#include "mygraph.h"
#include "mydev.h"
int ingraphmode;
extern int gunit;
extern struct gmodel g;
/*---------------------------------------------------------------------------*/
#define pi 3.141592653
#define true (!false)
#define BLACKANDWHITE 1
#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);
int kbhit(void);
/*---------------------------------------------------------------------------*/
/* The global variables for the PC screen driver */
/*-----------------------------------------------*/

int i,l,j,ix,iy;
double f;


#define gerr() i = graphresult(); if (i!=0) printf("Graph error: %s \n",grapherrormsg(i));
#define xsizecm 21.0
#define ysizecm 18.0
#define sx(v) ( (int) ((v) * d_xscale)+1)
#define sy(v) ( d_maxy - ((int) ((v) * d_yscale)))
#define rx(v) ( (int) ((v) * d_xscale)+1)
#define ry(v) ( d_maxy - ((int) ((v) * d_yscale)))
#define textmode() {getch(); restorecrtmode();}
#define graphmode() {getch(); setgraphmode(d_graphmode);}
#define gon  if ((gle_debug & 256) > 0) graphmode()
#define goff if ((gle_debug & 256) > 0) textmode()

double d_scale, d_xscale, d_yscale;
int d_graphmode;
int d_fillstyle=1,d_fillcolor;
int d_lstyle,d_lwidth,d_pat;
int d_maxy;

int d_zzline(double cx,double cy,double zx,double zy);
int addline(char *s);

int getwhite();
int getwhite()
{
	int i;
	i = getmaxcolor();
	if (i>15) i = 15;
	return i;
}
d_devcmd(char *s)
{}

int undxy(int dx, int dy, double *x, double *y);
undxy(int dx, int dy, double *x, double *y)
{
	double ddx,ddy;
	char buff[80];
	ddx = (dx)/d_xscale;
	ddy = (dy - d_maxy) / -d_yscale;
	g_undev(ddx,ddy,x,y);
}
dxy(double x, double y, int *dx, int *dy)
{
	static double fx,fy;
	g_dev(x,y,&fx,&fy);
	*dx = sx(fx);
	*dy = sy(fy);
}
rxy(double x, double y, int *dx, int *dy)
{
	static double fx,fy,zx,zy;
	g_dev(x,y,&fx,&fy);
	g_dev(0.0,0.0,&zx,&zy);
	*dx = (int) ( (fx-zx) * d_xscale +1);
	*dy = (int) ( (fy-zy) * d_yscale);
}
/*---------------------------------------------------------------------------*/
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;
	if (ingraphmode) {
		oldx = getx(); oldy = gety();
		oldcolor = getcolor();
		setfillstyle(1,BLACK);
		setcolor(WHITE);
		bar(1,getmaxy()-19,getmaxx(),getmaxy());
		settextstyle(0,0,0);
		settextjustify(LEFT_TEXT,BOTTOM_TEXT);
		moveto(4,getmaxy()-10);
		if (strlen(lastline)>0) outtext(lastline);
		moveto(4,getmaxy()-2);
		outtext(s);
		ncpy(lastline,s,78);
		setcolor(oldcolor);
		setfillstyle(d_fillstyle,d_fillcolor);
		moveto(oldx,oldy);
		if (single_step) {
			if (getch()=='g') single_step = false;
		}
		if (kbhit()) {
			if ((bioskey(1) & 0xff) != 27) {
			 if (getch()=='s') single_step = true;
			 while (kbhit()) getch();
			 getch();
			}
		}
	} else {
		printf("%s\n",s);
	}
}
/*---------------------------------------------------------------------------*/
d_source(char *s)
{
	s=s;
}
/*---------------------------------------------------------------------------*/
d_get_type(char *t)
{
	strcpy(t,"INTERACTIVE, PC");
}
/*---------------------------------------------------------------------------*/
d_set_path(int onoff)
{}
/*---------------------------------------------------------------------------*/
d_newpath()
{
}
int svga_mode=grError;
int huge detect_svga()
{
  gprint("Loading USER BGI driver \n");
  return svga_mode;
}
add_svga()
{
	int g_error;
	char *s,buff[80],sname[40];
	s = getenv("GLE_ADDBGI");
	if (s==NULL) return;
	strcpy(buff,s);
	s = strtok(buff," .");
	if (s==NULL) {gprint("Expecting mode.name, e.g. 3.svga256,  found {%s} \n",buff); return;}
	svga_mode = atoi(s);
	s = strtok(NULL," .");
	if (s==NULL) {gprint("Expecting 'mode.name' , e.g. 3.svga256,  found {%s} \n",buff); return;}
	strcpy(sname,s);
	installuserdriver(sname,detect_svga);
	g_error = graphresult();
	if (g_error<0) {
		gprint("InstallUserDriver error %s\n",grapherrormsg(g_error));
		text_inkey();
	}
}

/*---------------------------------------------------------------------------*/
char *bgidir(void);
d_open(double width, double height)
{
	static int g_driver,g_error;
	double f;
	static int doneopen;

	if (!doneopen) {
		add_svga();

		doneopen = true;
		/* detectgraph(&g_driver, &d_graphmode);
		if (g_driver<0) {
			printf("No graphics hardware detected !!!!! \n");
			gle_abort("Could not load BGI graphics\n");
		}  */
		g_driver = DETECT;
		initgraph(&g_driver,&d_graphmode,bgidir());
	} else  {
		setgraphmode(d_graphmode);
	}
	g_error = graphresult();
	if (g_error<0) {
		printf("Init graph error %s\n",grapherrormsg(g_error));
		ingraphmode = false; text_inkey(); gle_abort("Init graph error\n");
	}
	if (g_driver==HERCMONO) pokeb(0x40,0x49,6); /* this makes mouse work on herc card */
	ingraphmode = true;
	/* Get largest rectangle we can fit on the screen */
	d_scale = xsizecm / width;
	f = ysizecm / height;
	if (f<d_scale) d_scale = f;

	d_xscale = d_scale * (getmaxx()-2) / xsizecm; /* Device Scale X, Device Scale y */
	d_yscale = d_scale * (getmaxy()-22) / ysizecm;
	d_maxy = getmaxy()-21;
	g.userwidth = width;
	g.userheight = height;
}
/*---------------------------------------------------------------------------*/
d_tidyup()
{
	if (ingraphmode) {
		gprint("AARRRrrrrgg,  Watch out I'm dying!!!\n");
		d_close();
	}
}
void mouseloc(int column,int  row);             /* set location of mouse cursor */
int draw_boxline(int d_imde,double x1,double y1,double x2,double y2);
int d_get_click(double *x, double *y, int *click);
int d_get_point(double *x, double *y, int *click);
void mousecursor( int toggle);
int cross_hair(double x, double y);
int mousecheck(void);
double mouse_x,mouse_y,gridstep;
int boxed_text,ismouse;
int d_imde;
double d_mousex,d_mousey;


int gridit(double *x,double *y);
gridit(double *x,double *y)
{
	*x = floor(*x/gridstep + .5) * gridstep;
	*y = floor(*y/gridstep + .5) * gridstep;
}
d_prompts()
{
	 if (d_imde==1) d_message("Click on position for TEXT");
	 if (d_imde==2) d_message("Click on position for LINE");
	 if (d_imde==3) d_message("Click on position for BOX");
	 d_message("t=text l=line b=box o=bOxed_text c=Click u=penUp f=finer g=greater ESC=Exit");
}
d_cursor_toggle(void)
{
	static int onoff=0;
	onoff = !onoff;
	setcolor(getwhite());
	setwritemode(XOR_PUT);
	if (ismouse) mousecursor(onoff); else cross_hair(d_mousex,d_mousey);
	setcolor(0);
	setwritemode(COPY_PUT);
}
d_xor(void)
{
	setcolor(getwhite());
	setwritemode(XOR_PUT);
}
wait_for_return()
{
	int exitlp=false,click=0,clickex=0,oldmode;
	double x1,y1,x2,y2,nx,ny;
	char buff1[90],buff2[90];
/* valid commands are */
/* t = text, l = line, u=penup, b=box, o=bOxed text, f = finer, g = greater */
	d_imde = 2;
	if (d_mousex==0) {
		d_mousex = g.userwidth/2;
		d_mousey = g.userheight/2;
	}
	if (mousecheck()) ismouse = true;
	if (!ismouse) gridstep = 1;
	if (gridstep==0) gridstep = .1;
	d_cursor_toggle();
	for (;;) {
	 d_prompts();
	 oldmode = d_imde;
	 d_get_click(&x1,&y1,&click); if (click==3) goto aborting;
	 if (oldmode!=d_imde) goto next_one;
	 gridit(&x1,&y1);
	 if (d_imde==1) {
		d_message("Enter the text at the top of the screen");
		d_get_line(buff1,&click);
		if (click==3) goto next_one;
		sprintf(buff2,"amove %g %g ",x1,y1); addline(buff2);
		if (boxed_text) addline("begin box add .2");
		sprintf(buff2,"text %s",buff1);
		addline(buff2);
		if (boxed_text) addline("end box");
		g_move(x1,y1);
		g_text(buff1);
		if (d_imde==1) d_imde = 2;
		goto next_one;
	 }
	 sprintf(buff1,"amove %g %g",x1,y1); addline(buff1);
poly:	 d_xor();
	 draw_boxline(d_imde,x1,y1,x1,y1);
	 x2 = x1; y2 = y1;
	 if (d_imde==2 || d_imde==3) {
	  oldmode = d_imde;
	  for (click=0;click==0 && (d_imde==oldmode);) {
		d_get_point(&nx,&ny,&click);
		if (x2!=nx || y2!=ny) {
		  d_cursor_toggle();
		  d_xor();
		  draw_boxline(oldmode,x1,y1,x2,y2);
		  draw_boxline(oldmode,x1,y1,nx,ny);
		  d_cursor_toggle();
		}
		delay(10);
		x2 = nx; y2 = ny;
	  }
	  d_cursor_toggle();
	  d_xor();
	  draw_boxline(oldmode,x1,y1,nx,ny);
	  if (click==1 && d_imde==oldmode) {
		gridit(&x2,&y2);
		setcolor(0);
		setwritemode(COPY_PUT);
		draw_boxline(d_imde,x1,y1,x2,y2);
		if (d_imde==2) {
			sprintf(buff1,"rline %g %g",x2-x1,y2-y1); addline(buff1);
			x1 = x2; y1 = y2;
			d_cursor_toggle();
			if (click==1) goto poly;
		}
		if (d_imde==3) {
			sprintf(buff1,"box %g %g ",x2-x1,y2-y1); addline(buff1);
		}
	  }
	  d_cursor_toggle();
	 }
next_one:;
	setcolor(0);
	setwritemode(COPY_PUT);
	}
aborting:;
	d_cursor_toggle();
}
draw_boxline(int d_imde,double x1,double y1,double x2,double y2)
{
	if (d_imde==2) {
		g_move(x1,y1);
		g_line(x2,y2);
	} else {
		g_move(x1,y1);
		g_box_stroke(x1,y1,x2,y2);
	}
}
d_get_click(double *x, double *y, int *click)
{
	for (;;) {
	 d_get_point(x,y,click);
	 if (*click>0) return;
	 delay(10);
	}
}
#include "edt.h"
int ddgets(char *s);
d_get_line(char *s,int *click)
{
	if (ddgets(s)) *click = 3;
	else *click = 0;
}
ddgets(char *s)
{
	int c,cx=0;
	char mbuff[80];
	*s = 0;
	bottom_line(s);
	for (;;) {
	 c = text_inkey();
	 switch (c) {
	   case eescape: /* ESCAPE */
	   case equit: /* control c */
		return true;
	  case ereturn: /* carriage return */
		return false;
	  case edelete: /* delete */
		if (strlen(s)==0) break;
		if (cx<1) break;
		ncpy(mbuff,s,cx-1);
		strcat(mbuff,s + cx);
		strcpy(s,mbuff);
		cx--;
		bottom_line(s);
		break;
	  default: /* normal key */
		if (c<26  && c!=9) {fner("Key has no affect"); break;}
		if (c>200)  fner("Unimplemented command");
		else {
			ncpy(mbuff,s,cx);
			mbuff[cx] = c; mbuff[cx+1] = 0;
			strcat(mbuff,s + cx);
			strcpy(s,mbuff);
			bottom_line(s);
			cx++;
		}
		break;
	   }
	 }
}
bottom_line(char *s)
{
	setfillstyle(1,BLACK);
	setcolor(WHITE);
	bar(1,getmaxy()-9,getmaxx(),getmaxy());
	settextstyle(0,0,0);
	settextjustify(LEFT_TEXT,BOTTOM_TEXT);
	moveto(4,getmaxy()-2);
	outtext("Enter text? ");
	outtext(s);
	setcolor(0);
}

d_get_point(double *x, double *y, int *click)
{
	int i,c,ix,iy,oldmode;

	if (ismouse) {
		undxy(mousecol(),mouserow(),x,y);
		d_mousex = *x; d_mousey = *y;
	} else {
		*x = d_mousex;
		*y = d_mousey;
	}
	*click = 0;
	if (kbhit()) {
		oldmode = d_imde;
		c = text_inkey();
		c = tolower(c);
		switch (c) {
		  case 'l': /* line */
			d_imde = 2;  break;
		  case 'b': /* box */
			d_imde = 3;  break;
		  case 't': /* text */
			d_imde = 1;  boxed_text = false; break;
		  case 'o': /* boxed text */
			d_imde = 1;
			boxed_text = true; break;
		  case 'f': /* finer grid */
			gridstep = gridstep / 10; break;
		  case 'g': /* greater grid */
			gridstep *= 10; break;
		  case ereturn: /* return, finished */
		  case eescape:
			*click = 3; break;
		  case 'u':  /* pen up */
			*click = 2; break;
		  case 'd': /* pen down */
		  case 'c': /* click */
			*click = 1; break;
		  case eup: /* Move cursor up 1 grid step */
			*y += gridstep; break;
		  case edown:
			*y -= gridstep; break;
		  case eright:
			*x += gridstep; break;
		  case eleft:
			*x -= gridstep; break;
		}
		if (oldmode!=d_imde) *click = 2;
	}
	if (ismouse) {
		i = mouseclick();
		if (i>0) *click = i;
		undxy(mousecol(),mouserow(),x,y);
	} else {
		gridit(x,y);
	}
	if (*x != d_mousex || *y != d_mousey) {
		if (ismouse) {
			dxy(d_mousex,d_mousey,&ix,&iy);
			mouseloc(ix,iy);
		} else {
			d_cursor_toggle();
			d_mousex = *x;
			d_mousey = *y;
			d_cursor_toggle();
		}
	}
}
cross_hair(double x,double y)
{
	int ix,iy;
	dxy(x,y,&ix,&iy);
	moveto(ix,iy-10);
	lineto(ix,iy+10);
	moveto(ix-10,iy);
	lineto(ix+10,iy);
}
d_close()
{
	stop;gon;
	if (ingraphmode == false) return;
	g_flush();
	d_message("Press <RETURN> to continue");
	lastline[0] = 0;
	if (kbhit()) getch();
	wait_for_return();
	ingraphmode = false;
	restorecrtmode();
}
/*---------------------------------------------------------------------------*/
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)
{
	stop;
	d_lwidth = 1;
	if (w>.099) d_lwidth = 3;
	setlinestyle(d_lstyle,d_pat,d_lwidth);
	gerr();goff;
}
/*---------------------------------------------------------------------------*/
d_set_line_styled(double dd)
{}
d_set_line_style(char *s)
{
	static char *defline[] = {"","","12","41","14","92",
	"1282","9229","4114","54"};
	int i, j, nblack, nwhite, pat;
	char *ss;
	stop;gon;

	if (strlen(s)==1)  s = defline[*s-'0'];
	if (strcmp(s,"")==0) {
	    d_lstyle = SOLID_LINE;
	    d_pat = 0;
	    setlinestyle(d_lstyle,0,d_lwidth);
	} else {
	    ss = s;
	    pat = 0;                 /* make a 16 bit pattern from digits */
	    for (i=15; i>=0;) {
		nblack = *s - '0';
		s++;
		for (j=0; j<nblack; j++) {
		    pat = pat | (1L << i);
		    i--;
		}
		if (*s == 0)  s = ss;   /* if odd number of digits, repeat */
		nwhite = *s - '0';
		s++;
		i = i - nwhite;
		if (*s == 0)  s = ss;
	    }
	    d_lstyle = USERBIT_LINE;
	    d_pat = pat;
	    setlinestyle(d_lstyle,pat,d_lwidth);
	}
	gerr();goff;
}
/*---------------------------------------------------------------------------*/
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;
	stop;gon;
	dxy( (*wkx)[0], (*wky)[0], &ix, &iy);
	moveto(ix,iy);
	for (i=1;i<nwk;i++) {
		dxy( (*wkx)[i], (*wky)[i], &ix, &iy);
		lineto(ix,iy);
	}
	gerr();goff;
}
/*---------------------------------------------------------------------------*/
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 dunx1,dunx2,duny1,duny2;
d_unline()
{
	 setcolor(getwhite());
	moveto(dunx1,duny1);
	lineto(dunx2,duny2);
}
d_zzline(double cx,double cy,double zx,double zy)
{
	static int ux,uy,ix,iy;
	dxy(cx,cy,&ux,&uy);
	dunx1 = ux; duny1 = uy;
	dxy(zx,zy,&ix,&iy);
	 setcolor(0);
	moveto(ux,uy);
	lineto(ix,iy);
	dunx2 = ix; duny2 = iy;
}

d_line(double zx,double zy)
{
	static int ux,uy;
	if (g.xinline==false) {
		dxy(g.curx,g.cury,&ux,&uy);
		moveto(ux,uy);
		dunx1 = ux; duny1 = uy;
	}
	dxy(zx,zy,&ix,&iy);
	lineto(ix,iy);
	dunx2 = ix; duny2 = iy;
}
/*---------------------------------------------------------------------------*/
d_clear()
{
	double width,height;
	int x1,y1,x2,y2;
	width = g.userwidth;
	height = g.userheight;
	stop;
	d_lstyle = SOLID_LINE;
	d_pat = 0;
	d_lwidth = 1;
	setgraphmode(d_graphmode);

	/* now draw bounding box of screen */
	x1 = 0;
	y1 = d_maxy-height*d_yscale -1;
	x2 = width*d_xscale+2;
	y2 = d_maxy+1;
	setfillstyle(1,getwhite());
	bar(x1,y1,x2,y2);
	setcolor(BLACK);
	goff;
}
/*---------------------------------------------------------------------------*/
d_flush()
{
}
/*---------------------------------------------------------------------------*/
int polar_xy(double r, double angle, double *dx, double *dy);
int xy_polar(double dx,double dy,double *radius,double *angle);
d_arcto(dbl x1,dbl y1,dbl x2,dbl y2,dbl rrr)
{
	double x0,y0,r1,a1,r2,a2,r3,a3,a4,r5,sx,sy,ex,ey;
	double bx1,by1,bx2,by2,dist,neg;
	g_get_xy(&x0,&y0);
	xy_polar(x1-x0,y1-y0,&r1,&a1);
	xy_polar(x2-x1,y2-y1,&r2,&a2);
	neg = 1;
	a4 = (180-a2+a1);
	a3 = a2 + (a4/2);
	if ((a4/2)>90 && (a4/2)<180 ) neg = -1;
	if ((a4/2)<0 && (a4/2)>-90 ) neg = -1;
	r3 = neg*rrr/(tan((pi/180)*a4/2));
	dbg gprint("rrr %g a4/2 %g t=%g a2=%g a1=%g r1=%g r2=%g r3=%g \n",rrr,a4/2,tan(a4/2),a2,a1,r1,r2,r3);
	polar_xy(-r3,a1,&sx,&sy); sx += x1; sy += y1;
	polar_xy(r3,a2,&ex,&ey); ex += x1; ey += y1;
	g_line(sx,sy);
	dist = sqrt(pow(ex-sx,2) + pow(ey-sy,2));
	polar_xy(r1+ dist/2.5-r3,a1,&bx1,&by1); bx1 += x0; by1 += y0;
	polar_xy(-r2+ -dist/2.5+r3,a2,&bx2,&by2); bx2 += x2; by2 += y2;
	g_bezier(bx1,by1,bx2,by2,ex,ey);
	g_line(x2,y2);
}
/*---------------------------------------------------------------------------*/
d_arc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	static int ixr,iyr,icx,icy;
	double ux,uy,z;
	dxy(cx,cy,&icx,&icy);
	rxy(r,r,&ixr,&iyr);
	if (t1>t2) {z = t1; t1 = t2; t2 = z;}
	/* arc(icx,icy,(int) t1, (int) t2, ixr); */
	ellipse(icx,icy,(int) t1, (int) t2, ixr, iyr);
}
/*---------------------------------------------------------------------------*/
d_narc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	static int ixr,iyr,icx,icy;
	double ux,uy,z;
	dxy(cx,cy,&icx,&icy);
	rxy(r,r,&ixr,&iyr);
	if (t1>t2) {z = t1; t1 = t2; t2 = z;}
	/* arc(icx,icy,(int) t1, (int) t2, ixr);*/
	ellipse(icx,icy,(int) t1, (int) t2, ixr, iyr);
}
/*---------------------------------------------------------------------------*/
d_box_fill(dbl x1, dbl y1, dbl x2, dbl y2)
{
	static int ix1,iy1,ix2,iy2;
	static int ii;
	stop;gon;
	dxy(x1,y1,&ix1,&iy1);
	dxy(x2,y2,&ix2,&iy2);
	if (ix1>ix2) { ii = ix1; ix1 = ix2; ix2 = ii; }
	if (iy1>iy2) { ii = iy1; iy1 = iy2; iy2 = ii; }
	bar(ix1,iy1,ix2,iy2);
	goff;
}
d_box_stroke(dbl x1, dbl y1, dbl x2, dbl y2)
{
	static int ix1,iy1,ix2,iy2;
	static int ii;
	stop;gon;
	dxy(x1,y1,&ix1,&iy1);
	dxy(x2,y2,&ix2,&iy2);
	if (ix1>ix2) { ii = ix1; ix1 = ix2; ix2 = ii; }
	if (iy1>iy2) { ii = iy1; iy1 = iy2; iy2 = ii; }
/* 	rectangle(ix1,iy1,ix2,iy2); */
	moveto(ix1,iy1);
	lineto(ix2,iy1);
	lineto(ix2,iy2);
	lineto(ix1,iy2);
	lineto(ix1,iy1);
	goff;
}
/*---------------------------------------------------------------------------*/
d_circle_stroke(double zr)
{
	static int ixr,iyr;
	int ux,uy;
	rxy(zr,zr,&ixr,&iyr);
	dxy(g.curx,g.cury,&ux,&uy);
	ellipse(ux,uy,0,360,ixr,iyr);
}
d_circle_fill(double zr)
{
	static int ixr,iyr;
	int ux,uy;
	dxy(g.curx,g.cury,&ux,&uy);
	rxy(zr,zr,&ixr,&iyr);
	fillellipse(ux,uy,ixr,iyr);
}
/*---------------------------------------------------------------------------*/
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 = 12;
	if (dist<1) nstep = 7;
	if (dist<.5) 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_bezier(dbl zx1,dbl zy1,dbl zx2,dbl zy2,dbl zx3,dbl zy3)
/* {
/* 	long  ax,bx,cx,ay,by,cy,dist;
/* 	long xxx,yyy,i,t,nstep;
/* 	long t2,t3;
/* 	int x0,y0,x1,y1,x2,y2,x3,y3;
/* 	double zx0,zy0;
/* 	g_get_xy(&zx0,&zy0);
/*
/* 	dxy(zx1,zy1,&x1,&y1);
/* 	dxy(zx2,zy2,&x2,&y2);
/* 	dxy(zx3,zy3,&x3,&y3);
/* 	dxy(zx0,zy0,&x0,&y0);
/*
/* 	x0 *= 1; y0 *= 1;
/* 	x1 *= 1; y1 *= 1;
/* 	x2 *= 1; y2 *= 1;
/* 	x3 *= 1; y3 *= 1;
/* 	nstep = 20;
/* 	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;
/* 	t3 = 0;
/* 	for (i=0; i<=100; i += 10) {
/* 		t = i ;
/* 		t2 = (i*i)/100l;
/* 		t3 = (t2*i)/100l;
/* 		xxx = (ax*t3) + (bx*t2) + (cx*t) + ((long ) x0)*100l;
/* 		yyy = (ay*t3) + (by*t2) + (cy*t) + ((long ) y0)*100l;
/* 		lineto((int) (xxx/100l),(int) (yyy/100l));
/* 	}
/* }
*/
/*---------------------------------------------------------------------------*/
d_set_color(long f)
{
	int i;
	colortyp  cc;
	stop;gon;
	cc.l = f;
	i = 0;
	if (cc.b[B_R]>1 && cc.b[B_G]>1 && cc.b[B_B]>1) i = 8;
	if (cc.b[B_R]>60 && cc.b[B_G]>60 && cc.b[B_B]>60) i = 7;
	if (cc.b[B_R]>100) i = 12;
	if (cc.b[B_B]>100) i = 9;
	if (cc.b[B_G]>100) i = 10;
	if (cc.b[B_R]>100 && cc.b[B_G]>100) i = 14;
	if (cc.b[B_G]>100 && cc.b[B_B]>100) i = 5;
	if (cc.b[B_R]>100 && cc.b[B_G]>100 && cc.b[B_B]>100) i = 7;
	if (i>=getwhite()) i = 0;
	if (cc.b[B_R]>250 && cc.b[B_G]>250 && cc.b[B_B]>250) i = getwhite();
	setcolor(i); goff;
}
d_set_fill(long f)
{
	int i;
	colortyp  cc;
	stop;gon;
	cc.l = f;
	i = 0;
	if (cc.b[B_R]>1 && cc.b[B_G]>1 && cc.b[B_B]>1) i = 8;
	if (cc.b[B_R]>60 && cc.b[B_G]>60 && cc.b[B_B]>60) i = 7;
	if (cc.b[B_R]>100) i = 12;
	if (cc.b[B_B]>100) i = 9;
	if (cc.b[B_G]>100) i = 10;
	if (cc.b[B_R]>100 && cc.b[B_G]>100) i = 14;
	if (cc.b[B_G]>100 && cc.b[B_B]>100) i = 5;
	if (cc.b[B_R]>100 && cc.b[B_G]>100 && cc.b[B_B]>100) i = 7;
	if (i>=getwhite()) i = 0;
	if (cc.b[B_R]>250 && cc.b[B_G]>250 && cc.b[B_B]>250) i = getwhite();
	d_fillcolor = i;
	setfillstyle(d_fillstyle,d_fillcolor);
	goff;
}
/*---------------------------------------------------------------------------*/
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);
/*---------------------------------------------------------------------------*/
int safnt;
int simple_char(int cc);
d_char(int font, int cc)
{
	static struct char_data cd;
	static int ix1,ix2,iy1,iy2;
	static int ux,uy;
	char ss[2];

	ss[0] = cc;
	ss[1] = 0;
	if (safnt==0) safnt = pass_font("PLSR");
	if (font!=82 && font>7) {
		my_char(font,cc);
		return;
	}
	if (gunit) simple_char(cc);
	else  my_char(safnt,cc);
}

int pass_font(char *s);
int draw_char_fixed(char *s);
int get_char_pcode(int ff, int cc, char **pp);
simple_char(int cc)
{
	char *pp;
	get_char_pcode(safnt,cc,&pp);
	draw_char_fixed(pp);
}
int frxi(char **s);
draw_char_fixed(char *s)
{
	int ux,uy,cx,cy,x1,y1,x2,y2,lx,ly;
	long xsclm,ysclm,xscld,yscld;
	double ox,oy;
	dxy(g.curx,g.cury,&ux,&uy);
	xsclm = g.fontsz*d_xscale; xscld = 1000;
	ysclm = g.fontsz*d_yscale; yscld = 1000;
	while (*s!=15) {
	  switch (*s++) {
	    case 1:
		cx = frxi(&s); cy = frxi(&s);
		moveto(ux + (cx*xsclm)/xscld, uy - (cy*ysclm)/yscld );
		lx = cx; ly = cy;
		break;
	    case 2:
		cx = cx + frxi(&s); cy = cy + frxi(&s);
		lineto(ux + (cx*xsclm)/xscld, uy - (cy*ysclm)/yscld );
		break;
	    case 3:
		cx = cx + frxi(&s); cy = cy + frxi(&s);
		x1 = cx; y1 = cy;
		cx = cx + frxi(&s); cy = cy + frxi(&s);
		x2 = cx; y2 = cy;
		cx = cx + frxi(&s); cy = cy + frxi(&s);
		g_bezier(x1,y1,x2,y2,cx,cy);
		break;
	    case 4:
		lineto(ux + (lx*xsclm)/xscld, uy - (ly*ysclm)/yscld );
		break;
	    case 5:
	    case 6:
	    case 7:
	    case 8:
		break;
	    case 0: /* no char in this font */
		goto abort;
	    default:
		gprint("Error in mychar pcode %d \n",*s++);
		goto abort;
	  }

	}
abort:;
}
