/*
     autograf.c : Program to graph various data from the auto datafile

	 By Joel Swank September 3, 1988
	 Version 1.0

	 */
/*
   Reads a datafile of gasoline purchases of the following format:
   Individual fields separated by commas.
   * date - character format
   * odometer reading - 999999.9
   * price per gallon - $9.999
   * Total cost of purchase - $9999.99
   * gallons - 999.9
   * place and brand of gas - character

   Execute from CLI or WorkBench.

*/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h> 
#include <libraries/dosextens.h> 
#include <graphics/gfxbase.h> 
#include <graphics/gfx.h> 
#include <graphics/gfxmacros.h> 
#include <graphics/display.h> 
#include <graphics/text.h> 
#include <devices/printer.h> 
#include <stdio.h>

#include "fileio.h"
#include "wtext.h"
#include "menu.h"

#ifdef NULL
#undef NULL
#endif
#define NULL ((void *)0)

#define INTUITION_REV 1L
#define STDIN 0
#define MAXYR 99
#define MINYR 0

/* 
 *  Data describing the Window
 */

static struct NewWindow	New_Window = {
	0, 0,			/* Take all of the */
	640, 200,	/* standard screen       */
	-1, -1,			/* Default pens */
	MOUSEMOVE+MENUPICK+GADGETUP+CLOSEWINDOW,	/* Inputs acceppeted */
	WINDOWCLOSE		/* Fairly standard window */
	| WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH ,
	NULL,			/* gadgets */
	(struct Image *) NULL,
	(UBYTE *) NULL ,	/* title */
	(struct Screen *) NULL,		/* filled at startup */
	(struct BitMap *) NULL,
	0, 0, 0, 0,		/* no change sizes, doesn't matter */
	WBENCHSCREEN
	} ;



/*
 *    Data describing the requestor text
 *
 */

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

struct IntuiText nodatamsg = {
	0,1,JAM2,	/* front and back text pens, drawmode and fill byte */
	14,16,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	(UBYTE *)"No data selected - check options",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct IntuiText prfailtxt = {
	2,1,JAM2,	/* front and back text pens, drawmode and fill byte */
	14,16,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	(UBYTE *)"Printer failed to open",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

/*
 * Some things that need to be shared with done.
 */
extern struct IntuitionBase	*IntuitionBase ;
struct Window	*Wind = NULL ;
static struct MsgPort		*CreatePort() ;
extern struct DosLibrary *DosBase ;
extern struct GfxBase *GfxBase ;
struct RastPort *rp;
struct Library *DiskfontBase = NULL;
struct IntuiMessage	*msg;
struct FileIOSupport *FIOSupp = NULL;


/* data to be shared */

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

int syr = -1;		/* for requested start year */
int eyr = -1;		/* for requested end year */

char tempbuf[80];
extern float rawcost[1000];	/* save cost data of each entry */
extern float pricesave[1000];	/* save price data of each entry */
extern int yrsave[1000];		/* save year of each entry */
extern float odsave[1000];		/* save odometer data of each entry */

int numrecs;		/* number of records in data space */
double atof();
char *names[10];
char *malloc();
/* some window and screen titles */
char autotitle[] = "AutoGraf - Select from Menu";
char screentitle[] = "AutoGraf Version 1.0 080488";


main(argc,argv)
int argc;
char *argv[];
{

int cmd, i;
int cnt;
long menunum;
 


/*************************************************
     OPEN everything
*************************************************/

 
if ((IntuitionBase = (struct IntuitionBase *)
    OpenLibrary("intuition.library", INTUITION_REV)) == NULL)
	done(21);

GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", NULL);
if (GfxBase == NULL) done(22);
if ((DosBase = (struct DosLibrary *)OpenLibrary("dos.library", 0)) == NULL)
	done(27);

if ((Wind = (struct Window *) OpenWindow(&New_Window)) == NULL)
	done(25);
rp = Wind->RPort;
if (NULL == (FIOSupp = GetFileIOSupport()))
	done(26);


/*************************************************
     Main processing loop 
*************************************************/


	do_intro();
	SetWindowTitles(Wind,(UBYTE *) autotitle,
			(UBYTE *) screentitle);
	SetMenuStrip(Wind,&MenuList1);
	while (1)
		{
		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);
					continue;
				case MENUPICK:
					menunum = msg->Code;
					ReplyMsg(msg);
					if (menunum != MENUNULL) do_pick(menunum);
					SetWindowTitles(Wind,(UBYTE *)
						autotitle, -1L);
					continue;
				}
			ReplyMsg(msg);
			}
		}
	done(0);
}


/*
 * do_pick : handle chain of menu selections
 */

do_pick(menunum)
long menunum;
{
struct MenuItem *item, *ItemAddress();
	while (menunum != MENUNULL)
		{
		switch(ITEMNUM(menunum))
			{
			case 0:
				read_file();
	  			clr_grf();
				break;
			case 1:
				draw_graph();
				break;
			case 2:
				do_avgs();
				break;
			case 3:
				get_opt();
				break;
			case 4:
				do_print();
				break;
			case 5:
				do_help();
				break;
			case 6:
				done(0);
				break;
			}
		item = ItemAddress(&MenuList1,menunum);
		menunum = item->NextSelect;
		}
}


/*
 * do_print : dump the window to the printer
 */

union printerIO {
	struct IOStdReq ios;
	struct IODRPReq iodrp;
	struct IOPrtCmdReq iopc;
	};

extern union printerIO *CreateExtIO();
extern struct MsgPort *CreatePort();

do_print()
{
union printerIO *request;
struct MsgPort *printerPort;
struct ViewPort *vp;
struct Screen *sc;

	ClearMenuStrip(Wind);
	SetWaitPointer(Wind);

	/* set up for dump rastport request */
	printerPort = CreatePort("myprport",0L);
	request = CreateExtIO(printerPort, sizeof(union printerIO));
	if (OpenDevice("printer.device",0L,request,0L) !=0)
		{
		AutoRequest(Wind,&prfailtxt,0L,&oktxt,0L,0L,300L,75L);
		goto cleanup;
		}

	request->iodrp.io_Command = PRD_DUMPRPORT;
	request->iodrp.io_RastPort = rp;
	sc = Wind->WScreen;
	vp = &sc->ViewPort;
	request->iodrp.io_ColorMap = vp->ColorMap;
	request->iodrp.io_Modes = vp->Modes;
	request->iodrp.io_RastPort = rp;
	request->iodrp.io_SrcX=2L;
	request->iodrp.io_SrcY=11L;
	request->iodrp.io_SrcWidth=635L;
	request->iodrp.io_SrcHeight=187L;
	request->iodrp.io_DestCols=0L;
	request->iodrp.io_DestRows=0L;
	request->iodrp.io_Special=SPECIAL_ASPECT | SPECIAL_FULLCOLS;
	DoIO(request);
	CloseDevice(request);
  cleanup:
	DeleteExtIO(request, sizeof(union printerIO));
	DeletePort(printerPort);
	SetMenuStrip(Wind,&MenuList1);
	ClearPointer(Wind);
}

/*
 * do_intro : display sign on text
 */

do_intro()
{
	WindowToFront(Wind);
	clr_grf();
	PrintIText(rp,&IntroText1,0L,0L);	/* Print the text */
}

/*
 * do_avgs : display averages and min/max readings foe current data
 */


do_avgs()
{
   float firstod = 0, miles, od;
   float lastod, prevod;
   float gallons, cost, price;
   float totgal = 0, totcost = 0;
   int count = 0;
   int year, i;

   float maxtank = 0;
   float maxcost = 0;
   float maxpr = 0;
   float maxgal = 0;
   float minpr =1e10;
   int maxtyr;
   int maxcostyr;
   int maxpryr;
   int maxgalyr;
   int minpryr;

   SetWaitPointer(Wind);

   for (i=0; i<numrecs; i++)
      {

	  year = yrsave[i];

	  /* eliminate undesired years */

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

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


	  od = odsave[i];	/* get odometer reading */

	  if (!firstod) firstod = od;
	  else {
	  	float t = od-prevod;
		if (t > maxtank) 
			{
			maxtank = t;
			maxtyr = year;
			}
		}

	  lastod = od;


	  price = pricesave[i];		/* get price */

	  cost = rawcost[i];		/* get cost */

	  gallons = cost/price;
	  /* accumulate data */
	  if (count != 0)
	  	{
	 	totgal += gallons;
	 	totcost += cost;
		}

	  if (price > maxpr) { maxpr = price; maxpryr = year; }
	  if (price < minpr) { minpr = price; minpryr = year; }
	  if (gallons > maxgal) { maxgal = gallons; maxgalyr = year; }
	  if (cost > maxcost) { maxcost = cost; maxcostyr = year; }

	  count++;
	  prevod = od;
	  }

	  if (count < 2)
	  	{
		AutoRequest(Wind,&nodatamsg,0L,&oktxt,0L,0L,300L,75L);
		return;
		}

	  /* print results */
	  miles = lastod-firstod;

	  clr_grf();
	  sprintf(tempbuf,"%d transactions processed", count);
	  Move(rp,50L,50L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Maximum distance between transactions= %-5.1f miles in %d",
	        maxtank, maxtyr);
	  Move(rp,50L,60L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Maximum gallons = %-5.1f in %d", maxgal, maxgalyr);
	  Move(rp,50L,70L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Maximum cost = $%-6.2f in %d", maxcost, maxcostyr);
	  Move(rp,50L,80L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Maximum gasoline price = $%-6.3f in %d", maxpr, maxpryr);
	  Move(rp,50L,90L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Minimum gasoline price = $%-6.3f in %d", minpr, minpryr);
	  Move(rp,50L,100L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Total Miles = %-8.1f", miles);
	  Move(rp,50L,110L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Total Gallons = %-7.1f", totgal);
	  Move(rp,50L,120L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Total Cost = $%-8.2f", totcost);
	  Move(rp,50L,130L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Average Cost per Gallon = $%-6.4f", totcost/totgal);
	  Move(rp,50L,140L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Average Miles per Gallon = %-5.2f", miles/totgal);
	  Move(rp,50L,150L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  sprintf(tempbuf,"Average Cost per Mile = %-5.2f cents", totcost/miles*100);
	  Move(rp,50L,160L);
	  Text(rp,tempbuf,strlen(tempbuf));
	  ClearPointer(Wind);
}

/*
 * done - just clean up that which is open, and then leave.
 */
done(how)
int how;
    {
    if (Wind) 
		{
		ClearMenuStrip(Wind);
		CloseWindow(Wind) ;
		}
    if (IntuitionBase) CloseLibrary(IntuitionBase) ;
    if (GfxBase) CloseLibrary(GfxBase) ;
	if (DosBase) CloseLibrary(DosBase);
	if (FIOSupp) ReleaseFileIO(FIOSupp);
 
    /* OpenWorkBench() ;		/* As requested */
    exit(how) ;
    }




/*
 * clr_grf : clear the graphics area of the screen
 *
 */
clr_grf()
{
	SetAPen(rp,0L);
	RectFill(rp,2L,11L,637L,198L);
	SetAPen(rp,3L);
}

/*
 * do_help : display help text in main window
 *
 */

do_help()
{
	WindowToFront(Wind);
	clr_grf();
	PrintIText(rp,&HelpText2,0L,0L);	/* Print help text */

}
/*
 * abort handler : call by manx Chk_Abort() routine
 */

_abort()
{
	printf("^C\n");
	done(20);
}
