/* draw.c	draws holigraphically on crt
	dr_iRastWindow()  initializes raster coords of window
	dr_iProgCoords()  initializes user floating point coords of screen

	dr_zoom()	zoom in to subsection of screen
	dr_Vreset()	resets V stack
	dr_Vpush()	push V onto stack
	dr_Vpop()	pop V from stack

	dr_sBox()	starts the filling in of the above box
	dr_compute()	divides sub box into required rectangles
	dr_area	generate a box of points around the current one

	dr_xy()	computes a mandelbrot value and puts in buffer
	dr_putBuf()	puts buffer on crt
	dr_clip		sets clip rectangle for dr_putBuf

	load_clut()
 */

#include <obdefs.h>
#include <define.h>
#include <gemdefs.h>
#include <osbind.h>
#include <stdio.h>
#include <debug.h>

#define L (long)
#define LOG_CELLS 9
				/* was 9 */
#define ASPECT_F (16.0/19.0)	/* X dimension of pixel / Y~ */
int vs_handle;			/* virtual workstation handle */
int wi_handle;			/* window handle */

/**** shared with window.c: */
double Vx0, Vy0, Vxw, Vyw;	/* Size of viewed area, in real numbers */
int Niter = 256;		/* max number of iterations */
int box_invisible;		/* if 0, boxes get outlined in black */

#define Nunzoom 50		/* stack of zoom-ins, to allow unzoom */
int Iunzoom;
struct unzoom
{	double x0, y0,  xw, yw;
} unzoom[Nunzoom];

long Tx0, Ty0;			/* Transform from Raster Coords to Prog Coords*/
double Txx, Tyy;
/* was pc X Y min gain */

int Wx0, Wy0;		/* Display Window Position, in Raster Coords */ 
int Wxw, Wyw;
int Wx1, Wy1;

int Cx0, Cx1, Cy0, Cy1; /* clip window */

int len;			/* side in pixels of boxes being generated */
long count;
int count_slider, slider;	/* of bar graph */

#define SIZEOF_BUF 160
int bufI, *bufP;
int buf[SIZEOF_BUF+1][5];

char str[128];
int v_pr_ct = 3;
#define v_printf(a,b,c) sprintf(str,a,b,c);v_gtext(handl,30,10*v_pr_ct++,str);


dr_iRastWindow(X0,Y0, Xw,Yw)
int X0, Y0, Xw, Yw;				/* of window, in rc's */
{	Wx0 = X0;	Wy0 = Y0;
	Wxw = Xw;	Wyw = Yw;
	Wx1 = Wx0 + Wxw -1;
	Wy1 = Wy0 + Wyw -1;
}
long debug1;

dr_iProgCoords(x0,y0, xw,yw)
double x0, y0, xw, yw;
{	double ratio, dif;
	long magnification;

	ratio = (double)Wxw * ASPECT_F/(double)Wyw;
	if (xw < (dif= ratio * yw))
	{	x0 -= (dif - xw)/2;		/* expand pcX */
		xw = dif;
	}else
	{	dif = xw / ratio;			/* expand pcY */
		y0 -= (dif - yw)/2;
		yw = dif;
	}
	Vx0 = x0;
	Vy0 = y0;
	Vxw = xw;
	Vyw = yw;

	Tx0 = x0 * (double)0x4000000; Ty0 = y0 * (double)0x4000000;
	Tyy = yw/(double)Wyw * (double)0x4000000; /*2^26*/;
	Txx = Tyy * ASPECT_F;

	magnification = 1.0/xw + 1.0;
	clip_full();
	sprintf(str, "%ldx  ", magnification);
	v_gtext(vs_handle, Wx0+20, Wy0-3, str);
	clip_current();
	
}

dr_zoom(x0,y0, x1,y1)
int x0,y0, x1,y1;
{	double Rx, Ry;
	int dx, dy, i;
	if (x0 > x1)
	{	i=x0; x0=x1; x1=i;
	}
	if (y0 > y1)
	{	i=y0; y0=y1; y1=i;
	}
	dr_Vpush();
	Vx0 += (double)(x0-Wx0) / (double)Wxw * Vxw;
	Vy0 += (double)(y0-Wy0) / (double)Wyw * Vyw;
	Vxw *= Rx = (double)(x1-x0+1) / (double)Wxw;
	Vyw *= Ry = (double)(y1-y0+1) / (double)Wyw;

	dr_iProgCoords(Vx0, Vy0,  Vxw, Vyw);
}

dr_Vpush()
{	if (Iunzoom == Nunzoom) 
	{	form_alert(0,"[1][Unzoom stack overflow,|UNZOOM is now broken.]\
			[I understand]");
		Iunzoom++;
	}
	else if (Iunzoom < Nunzoom)
	{	unzoom[Iunzoom].x0 = Vx0;
		unzoom[Iunzoom].y0 = Vy0;
		unzoom[Iunzoom].xw = Vxw;
		unzoom[Iunzoom++].yw = Vyw;
}	}

dr_Vpop()
{	if (Iunzoom<Nunzoom && Iunzoom-- >0 )
	{	Vx0 = unzoom[Iunzoom].x0;
		Vy0 = unzoom[Iunzoom].y0;
		Vxw = unzoom[Iunzoom].xw;
		Vyw = unzoom[Iunzoom].yw;
		dr_iProgCoords(Vx0, Vy0,  Vxw, Vyw);
		return(1);
	}	
	else
	{	form_alert(0,"[1][No previous place to|zoom back to.|\
Command ignored.][acknowlege]");
		Iunzoom = 0;
		return(0);
}	}

dr_Vreset()
{	Iunzoom = 0;
}

dr_Vprint()
{	int i;
	printf("V = (%f,%f) + (%f,%f)\n",Vx0,Vy0,Vxw,Vyw);
	for (i = Iunzoom; --i>=0;)
		printf("%d = (%f,%f) + (%f,%f)\n",i, unzoom[i].x0,unzoom[i].y0,
			unzoom[i].xw,unzoom[i].yw);
	wait();
}

wait()
{	long i;
	for (i=0; i<2000000; i++);
}

dr_sBox()	/* called when finally going to restart */
{	int pxyarray[4];

	st_inz(LOG_CELLS, Wxw, Wyw);
	count_slider = 0; slider = 0;		/* of bar graph */
	wind_set(wi_handle, WF_VSLIDE, 0, 0, 0, 0);

	vsf_interior(vs_handle,2);	vsf_style(vs_handle,8);	
}

dr_clip(x0,y0, xw,yw)
int x0,y0, xw,yw;
{	Cx0 = x0;
	Cy0 = y0;
	Cx1 = x0 + xw - 1;
	Cy1 = y0 + yw - 1;
}

dr_compute()
{	dprintf(stderr, "dr_compute()\n");/**/
	bufP = buf;
	bufI = 0;		/* (64 --- space for recursive splits) */
	while (bufI < SIZEOF_BUFF - 64) /* or LOG_CELLS*3 -5 */
	{	dprintf(stderr, "dr_compute: bufI=%d\n",bufI);/**/
		if (st_do_next() == 0) 
		{	dprintf(stderr, "st_do_next returned 0\n");/**/
			break;
	}	}
	dprintf(stderr, "dr_compute returning %d\n", bufI);/**/
	return (bufI);
}

dr_area(x0, y0, len)
int x0, y0, len;
{	int i, j;
	bufP = buf;
	bufI = 0;
	for (i = -len; i<=len; i++)
		for (j = -len; j<=len; i++)
			dr_xy(x0+i, y0+j, 1);
}

dr_xy(x0, y0, len)
int x0, y0, len;
{	long Zx, Zy;
	long pcX, pcY;
	int x,y;
	int count, count_max, color;
	char str[128];
	
	dprintf(stderr, "dr_xy: X=%x, Y=%x, l=%x, ", x0, y0, len);/**/
	if (x0<Wxw && y0<Wyw)
	{	pcX = (long)((double)x0 * Txx) + Tx0;
		pcY = (long)((double)y0 * Tyy) + Ty0;
		Zx=0; Zy=0;
		count = Niter - mandels(L Niter, pcY, pcX, &Zy,&Zx);
/*		count = (3*x0 + 2*y0)/57;/**/
		if (count==Niter)
		{	color = 1;
			count = 32757;
		}
		else
			color = ((count & 0x7fff)>>2)  %14 +2;
		if (bufI > SIZEOF_BUF)
			panic("write bufI overflow\n", 0L, 0L);
		*bufP++ = color;
		*bufP++ = ((x = Wx0 + x0) < Cx0)? Cx0: x;
		*bufP++ = ((y = Wy0 + y0) < Cy0)? Cy0: y;
		*bufP++ = ((x += len-1) > Cx1)? Cx1: x;
		*bufP++ = ((y += len-1) > Cy1)? Cy1: y;
		bufI++;
		dprintf(stderr, "c=%d, bI=%d\n", count, bufI);/**/
	}
	else	
	{	dprintf(stderr, "off-screen\n");/**/
		count = -1;
	}
	return (count);
}

dr_putBuf(box_count)
int box_count;
{	int i;
	int *p;

	draw_on_screen();
	st_check("dr_putBuf: \b\b\b\b\b\b\b\b\b\b\b");
	for (i=0; i<box_count; i++)
	{	p = buf[i];		
		if (p[1]==p[3] || box_invisible)
		{	vsf_color(vs_handle, *p);	/*draw colored box*/
			v_bar(vs_handle, p+1);
		}else
		{	vsf_color(vs_handle, 0);	/*draw white box*/
			v_bar(vs_handle, p+1);
			vsf_color(vs_handle, *p);	/*draw colored box*/
			p[1]++; p[2]++;			/*(smaller)*/
			v_bar(vs_handle, p+1);
		}
		if (--count_slider <= 0)
		{	wind_set(wi_handle, WF_VSLSIZE, 1000-slider, 0, 0, 0);
			clip_full();
			sprintf(str,"%d%% ", slider/10); 
			v_gtext(vs_handle, Wx1-39, Wy0-3, str);
			clip_current();
			count_slider = (L Wxw*Wyw)/100;
			slider += 10;
	}	}
	st_check("painted\b\b\b\b\b\b\b");
	view_screen();
}

rotate_clut(handle,clut)
int handle, clut[16][3];
{	int i, r,g,b;
	r = clut[15][0];
	g = clut[15][1];
	b = clut[15][2];
	for (i=15; i>2; i--)
	{	clut[i][0] = clut[i-1][0];
		clut[i][1] = clut[i-1][1];
		clut[i][2] = clut[i-1][2];
	}
	clut[2][0] = r;
	clut[2][1] = g;
	clut[2][2] = b;
	load_clut(handle,clut,(int *)0);
}
load_clut(handle, new, old)
int handle, new[16][3], old[16][3];
{	int i;
	for (i=0; i<16; i++)
	{	if (old) vq_color(handle, i, 0, old[i]);
		vs_color(handle, i, new[i]);
}	}
