/*
     dograf.c : subroutine to draw graph

	 By Joel Swank September 3, 1988
	 Version 1.0

	 */

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h> 
#include <graphics/gfxbase.h> 
#include <graphics/gfx.h> 
#include <graphics/gfxmacros.h> 
#include <graphics/display.h> 
#include <graphics/text.h> 
#include <ctype.h> 

/*************

 *  Hooks to the rest of the program

 *************/

extern char nodatamsg[];
extern char tempbuf[];
extern char filename[];

#define MenuList1 Menu1
extern struct Menu Menu1;
extern struct Window	*Wind;
extern struct RastPort *rp;
extern struct IntuiText oktxt;
extern int numrecs;
extern int fileread;

/* save areas for graphing data */
int yrsave[1000];		/* save year of each entry */
float costsave[1000];	/* save averaged cost data of each entry */
float milesave[1000];	/* save averaged mile data of each entry */
float pricesave[1000];	/* save price data of each entry */
float odsave[1000];		/* save odometer data of each entry */
float rawcost[1000];	/* save cost data of each entry */

/* flags for which grafs to display */
extern int cpm;
extern int ppg;
extern int mpg;

extern int syr;		/* for requested start year */
extern int eyr;		/* for requested end year */

/* Local data */

/*
 *    Data describing the NEXT gadget
 *
 */

SHORT BorderVectorsM[] = {
	0,0,
	42,0,
	42,15,
	0,15,
	0,0
};
struct Border BorderM = {
	-2,-1,	/* XY origin relative to container TopLeft */
	1,2,JAM2,	/* front pen, back pen and drawmode */
	5,	/* number of XY vectors */
	BorderVectorsM,	/* pointer to XY vectors */
	NULL	/* next border in list */
};

struct IntuiText ITextM = {
	1,2,JAM2,	/* front and back text pens, drawmode and fill byte */
	5,4,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	(UBYTE *)"NEXT",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct Gadget GadgetM = {
	NULL,	/* next gadget */
	5,142,	/* origin XY of hit box relative to window TopLeft */
	39,14,	/* hit box width and height */
	NULL,	/* gadget flags */
	RELVERIFY,	/* activation flags */
	BOOLGADGET,	/* gadget type flags */
	(APTR)&BorderM,	/* gadget border or image to be rendered */
	NULL,	/* alternate imagery for selection */
	&ITextM,	/* first IntuiText structure */
	0L,	/* gadget mutual-exclude long word */
	NULL,	/* SpecialInfo structure */
	NULL,	/* user-definable data */
	NULL	/* pointer to user-definable data */
};

/*
 *    Data describing the DONE gadget
 *
 */

SHORT BorderVectorsM1[] = {
	0,0,
	42,0,
	42,15,
	0,15,
	0,0
};
struct Border BorderM1 = {
	-2,-1,	/* XY origin relative to container TopLeft */
	1,2,JAM2,	/* front pen, back pen and drawmode */
	5,	/* number of XY vectors */
	BorderVectorsM1,	/* pointer to XY vectors */
	NULL	/* next border in list */
};

struct IntuiText ITextM1 = {
	1,2,JAM2,	/* front and back text pens, drawmode and fill byte */
	5,4,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	(UBYTE *)"DONE",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct Gadget GadgetM1 = {
	NULL,	/* next gadget */
	5,50,	/* origin XY of hit box relative to window TopLeft */
	39,14,	/* hit box width and height */
	NULL,	/* gadget flags */
	RELVERIFY,	/* activation flags */
	BOOLGADGET,	/* gadget type flags */
	(APTR)&BorderM1,	/* gadget border or image to be rendered */
	NULL,	/* alternate imagery for selection */
	&ITextM1,	/* first IntuiText structure */
	0L,	/* gadget mutual-exclude long word */
	NULL,	/* SpecialInfo structure */
	NULL,	/* user-definable data */
	NULL	/* pointer to user-definable data */
};

float vertscale, horizscale;
float max, min;		/* main max and min */
float vsize;		/* verticle range */
char textbuf[80];
char titlebuf[80];
int first = TRUE;
int prevyear = 0;	/* detecting year change */
long yval, xval;


/*
 *  draw_graph : draw requested graphs
 */
draw_graph()
{
long i;

	/* put up grafing gadgets */
	AddGadget(Wind,&GadgetM,(USHORT) ~0);
	AddGadget(Wind,&GadgetM1,(USHORT) ~0);

	/* disable all menu items except quit & print */
	for (i=0; i<6; i++)
		{
		if (i == 4) continue; /* skip print */
		OffMenu(Wind, (USHORT) SHIFTITEM(i));
		}

	/* add mouse reporting to window */
	ReportMouse(TRUE,Wind);

	/* do requested graphs */
	while (1)
	  	{
		if (ppg)
			{
			if (do_graph('p') == 0) break;
			}
		if (cpm)
			{
			if (do_graph('c') == 0) break;
			}
		if (mpg)
			{
			if (do_graph('m') == 0) break;
			}
		}

	/* delete mouse reporting from window */
	ReportMouse(FALSE,Wind);

	/* remove grafing gadgets */
	RemoveGadget(Wind,&GadgetM);
	RemoveGadget(Wind,&GadgetM1);

	/* enable all menu items */
	for (i=0; i<7; i++)
		{
		if (!fileread) 	/* if no file read . . . */
			{
			if (i=1) continue; /* skip draw and avgs */
			if (i=2) continue;
			}
		OnMenu(Wind, (USHORT) SHIFTITEM(i));
		}

	clr_grf();

}

/*
 *  do_graph : draw one graph from 'mode' and stored data 
 */

do_graph(mode)
char mode; /* what to graph, p=price/gal, m=mile/gal, c=cost/mile */
{

   struct IntuiMessage *msg;
   char *patptr;
   char *patpt2;
   int i, ystart = -1;
   int yend, year;
   int mousex, mx, my;
   register count;
 
	clr_grf();

/*************************************************
     Select data, and find max/min
*************************************************/

	max = 0;
	min = 1e10;

	for (count=0; count<numrecs; count++)
		{
		year = yrsave[count];

		/* eliminate undesired years */

		if (eyr != -1)	
	  		{
			if (year > eyr) break;
			}

		if (syr != -1)	
	  		{
			if (year < syr) continue;
			}

		if (ystart == -1) ystart = count; /* remenber first */


		/* find the max and min */
		switch (mode)
			{
			case 'c':
				if (costsave[count] > 0)
					{
					if (costsave[count] > max) max = costsave[count];
					if (costsave[count] < min) min = costsave[count];
					}
				break;
			case 'm':
				if(milesave[count] > 0)
					{
					if (milesave[count] > max) max = milesave[count];
					if (milesave[count] < min) min = milesave[count];
					}
				break;
			case 'p':
				if (pricesave[count] > max) max = pricesave[count];
				if (pricesave[count] < min) min = pricesave[count];
				break;
			}
		}
	yend = count;

	if (ystart == -1 || yend-ystart < 2)
	  	{
		AutoRequest(Wind,&nodatamsg,0L,&oktxt,0L,0L,300L,75L);
		return(0);
		}
 
/*************************************************
     Calculate scale factors
*************************************************/

		switch (mode)
			{
			case 'c':
			 strcpy(titlebuf,"Cents per Mile of Travel - File ");
			 break;
			case 'm':
			 strcpy(titlebuf,"Miles per Gallon of Gasoline - File ");
			 break;
			case 'p':
			 strcpy(titlebuf,"Dollars per Gallon of Gasoline - File ");
			 break;
			}
		vsize = (max - min) *1.1;
		vertscale = 180.0/vsize;
		horizscale = 570.0/ (float) (yend-ystart);

		strcat(titlebuf,filename);
		SetWindowTitles(Wind,(UBYTE *) titlebuf, -1L);

	/*	if (!wb) 
			{
			printf("Vert scale = %f\n",vertscale);
			printf("Horiz scale = %f\n",horizscale);
			printf("Max = %f\n",max);
			printf("Min = %f\n",min); 
			} */

	/*************************************************
	        draw axis and vertical labels 
	*************************************************/

		Move(rp,50L,15L);
		Draw(rp,50L,183L);
		Draw(rp,635,183L);
		Move(rp,50L,105L);
		Draw(rp,635,105L);
		switch (mode)
		{
		case 'c':
		 patptr = "%5.2f";
		 patpt2 = "%5.2f cents/mi";
		 break;
		case 'm':
		 patptr = "%5.2f";
		 patpt2 = "%5.2f mi/gal";
		 break;
		case 'p':
		 patptr = "%5.3f";
		 patpt2 = "$%5.3f $/gal";
		 break;
		}

	/* dray Y axis labels */
	Move(rp,5L,18L);
	sprintf(textbuf,patptr,min+vsize);
	Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));
	Move(rp,5L,107L);
	sprintf(textbuf,patptr,min+vsize/2);
	Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));
	Move(rp,5L,187L);
	sprintf(textbuf,patptr,min);
	Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));

	/* draw min and max values */
	Move(rp,65L,30L);
	sprintf(tempbuf,patpt2,max);
	strcpy(textbuf,"Maximum = ");
	strcat(textbuf,tempbuf);
	Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));
	Move(rp,400L,170L);
	sprintf(tempbuf,patpt2,min);
	strcpy(textbuf,"Minimum = ");
	strcat(textbuf,tempbuf);
	Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));

 
 
/*************************************************
     MAIN Drawing Routine
*************************************************/

	first = TRUE;
	prevyear = 0;

	for (count=ystart ; count< yend; count++)
      {

	  year = yrsave[count];

	  switch (mode)
		{
		case 'c':
		 if (costsave[count] == 0) yval = 0;
		 else yval = 180L - (long) ((costsave[count] - min) * vertscale);
		 break;

		case 'm':
		 if (milesave[count] == 0) yval = 0;
		 else yval = 180L - (long) ((milesave[count] - min) * vertscale);
		 break;

	    case 'p':
		 yval = 180L - (long) ((pricesave[count] - min) * vertscale);
		 break;
		}

	  xval = (long) ( ((float) (count-ystart)) * horizscale)+50;

	  if (yval != 0) /* don't draw zero entrys */
	  	{
	  	if (first)
			{
			Move(rp,xval, yval);
			first = FALSE;
			}
	  	else Draw(rp,xval, yval);
		}
	  	/* printf("X=%ld, y=%ld\n",xval,yval);  */
  	  if (year != prevyear) /* draw horiz label */
		{
		sprintf(textbuf,"%2d",year%100);
		Move(rp,xval-TextLength(rp,textbuf, (long) strlen(textbuf))/2, 196L);
		Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));
		Move(rp,xval,180L);	/* tick marks */
		Draw(rp,xval,186L);
		Move(rp,xval, yval);
		}
	  prevyear = year;

	  }

	/* redraw Gadgets */
	RefreshGadgets(&GadgetM,Wind,0L);
	RefreshGadgets(&GadgetM1,Wind,0L);
 
/*************************************************
     WAIT for Close, NEXT or DONE Gadget and manage
	      the mouse reporting
*************************************************/

while (1)
	{
	int menunum;
	struct MenuItem *item, *ItemAddress();
	Wait( 1L << Wind->UserPort->mp_SigBit);	/* wait on mesg */
	while(msg = (struct IntuiMessage *) GetMsg(Wind->UserPort)) {
		switch(msg->Class) {
			case CLOSEWINDOW:
				ReplyMsg(msg);
				done(0);
			case GADGETUP:
				ReplyMsg(msg);
				if (msg->IAddress == &GadgetM) return(1);  /* next graf */
				if (msg->IAddress == &GadgetM1) return(0); /* next file */
				continue;
			case MENUPICK:	/* only print and quit are allowed */
				menunum = msg->Code;
				ReplyMsg(msg);
				while (menunum != MENUNULL)
					{
					switch(ITEMNUM(menunum))
						{
						case 4:
						  do_print();
						  break;
						case 6:
						  done(0);
						}
					item = ItemAddress(&MenuList1,menunum);
					menunum = item->NextSelect;
					}
				continue;
			case MOUSEMOVE:
				mx = msg->MouseX;
				my = msg->MouseY;
				ReplyMsg(msg);
				if (mx<50 || my>180) continue; /* off grafics area */
				if (mx != mousex)     /* if x has changed */
					{
					int index;
					float val;
					mousex =mx;
					/* get data value for current mouse X */
					index = (int) ( ((float) mx - 50) / horizscale) - ystart;
					if (index < ystart || index >= yend) continue;
					switch (mode)
						{
						case 'c':
						  val = costsave[index];
		 				  break;
						case 'm':
						  val = milesave[index];
		 				  break;
						case 'p':
						  val = pricesave[index];
		 				  break;
						}
					/* Draw the value */
					Move(rp,65L,20L);
					sprintf(tempbuf,patpt2,val);
					strcpy(textbuf,"Mouse @ ");
					strcat(textbuf,tempbuf);
					Text(rp,(UBYTE *)  textbuf, (long) strlen(textbuf));
					}
				continue;
			}
			ReplyMsg(msg);
		}
	}
}

