/***************** Display World Data Bank ********************/
#include	<clib/macros.h>
#include	<functions.h>
#include	<rjd/rjd.h>
#include	<intuition/intuition.h>
#include	<libraries/dosextens.h>
#include	<exec/memory.h>
#include	<wdb/req.h>

#define	QSPAN	90*6000
#define HSPAN	QSPAN*2
#define WSPAN	QSPAN*4
#define gg_ix   gg_addr->GadgetID
#define False 0

struct IntuitionBase *IntuitionBase;
struct GfxBase	*GfxBase;
struct Screen	*s;
struct Window	*w,*Contr,*win;
struct RastPort *rp;
struct Gadget	*gg_addr;

typedef struct { short Code, Lat, Lon; } PNT ;
#define PNTSiz	sizeof(PNT)
#define PCount	1024

PNT	*p;
long	Latitude, Longitude,
		X_Scale, Y_Scale,
		val,
		ymax,ymin,xmax,xmin,xspan,yspan;
double zoom,atof();
char	*infile;
short	dbug=1;
ULONG	class;

short CTable[] = {
	0x0000, 0x0ddd, 0x00a0, 0x0d00, 0x0ff0, 0x05f5, 0x0aaf, 0x033f
};

long colr[] = { 2, 2, 3, 0, 4, 5, 6, 7 };	/* pen = line type DIV 1000 */

struct TextAttr ta = {
	(STRPTR)"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT
};

struct NewScreen ns = {
	0,0,640,400,3,3,1,HIRES|LACE,CUSTOMSCREEN,&ta,
	(UBYTE *)"Micro WorldDataBank-II",NULL,NULL
};

struct NewWindow nw = {
	0,0,640,400,-1,-1,MENUPICK,NULL,
	NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN
};

struct IntuiText quitIT = { 3,2,JAM1,2,1,&ta,(UBYTE *)"Quit" ,NULL },
		 prntIT = { 3,2,JAM1,2,1,&ta,(UBYTE *)"Print",NULL },
		 loadIT = { 3,2,JAM1,2,1,&ta,(UBYTE *)"Load" ,NULL },
		 titlIT = { 3,2,JAM1,2,1,&ta,(UBYTE *)"Title",NULL },
		 specIT = { 3,2,JAM1,2,1,&ta,(UBYTE *)"Specs",NULL };

#define MenuFlags  ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP

struct MenuItem
		quitMI = {    NULL,0,40,99,11,MenuFlags,NULL,
					(APTR)&quitIT,NULL,(BYTE)'Q',NULL },
		prntMI = { &quitMI,0,30,99,11,MenuFlags,NULL,
					(APTR)&prntIT,NULL,(BYTE)'P',NULL },
		loadMI = { &prntMI,0,20,99,11,MenuFlags,NULL,
					(APTR)&loadIT,NULL,(BYTE)'L',NULL },
		titlMI = { &loadMI,0,10,99,11,MenuFlags,NULL,
					(APTR)&titlIT,NULL,(BYTE)'T',NULL },
		specMI = { &titlMI,0, 0,99,11,MenuFlags,NULL,
					(APTR)&specIT,NULL,(BYTE)'S',NULL };

struct Menu m = { NULL,0,0,64,11,MENUENABLED,(BYTE *)"Control",&specMI };

/************************** clean up **********************/
void quit()
{
	if (w) {
		ClearMenuStrip(w);
		CloseWindow(w);
	}
	if(Contr) CloseWindow(Contr);
	FreeMem(p,PCount*PNTSiz);
	if (s) CloseScreen(s);
	CloseLibrary(GfxBase);
	CloseLibrary(IntuitionBase);
	exit(0);
}

/************************* initialization ***********************/
void init_gfx()
{
	IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
	GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L);

	if (!(s = OpenScreen(&ns)))
		quit();
	LoadRGB4(&s->ViewPort, &CTable, 8L);
	nw.Screen = s;
	if (!(w = OpenWindow(&nw)))
		quit();
	SetMenuStrip(w,&m);
	rp = w->RPort;
}

/***********************************************************/
SetSpecs()
{

	Latitude  = -((((CrossGgtSInfo.VertPot  + 1) * 180) >> 16) - 90 ) * 6000;
	Longitude = ((((CrossGgtSInfo.HorizPot + 1) * 360) >> 16) - 180 ) * 6000;
	zoom      = atof(StrGgtSIBuff);
	val = zoom * 10.0;
	X_Scale   = zoom * 120.0 / 33.75;	/* 33.75 = 10800 / 320 */
	Y_Scale   = zoom * 100.0 / 26.00;	/* 27.00 =  5400 / 200 */
	ymax = QSPAN/zoom;
	ymin = -ymax;
	xmax = HSPAN / (zoom * 1.2);
	xmin = -xmax;
	xspan = xmax - xmin;
	yspan = ymax - ymin;
}


_wb_parse() {}

OpenContrWindow()
{
nw.Flags = SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH;
nw.IDCMPFlags = GADGETUP | VANILLAKEY;
nw.TopEdge = 200;
nw.LeftEdge = 10;
nw.Width = 250;
nw.Height = 120;
nw.FirstGadget = &CrossGgt;
Contr = (struct Window *)OpenWindow(&nw);
}


/***************************** main routine ********************************/
main(argc, argv)
int argc;
char *argv[];
{
	void load();
	struct IntuiMessage *im;
	long title = FALSE,
		MsgBits,MainMsgBit, ContrMsgBit;
	USHORT code;

	if (argv[1][1] == '?')
	  {
		Write(Output(), "Usage: WDB data_file\n", 14L);
		exit(0);
	  }
	if (argc == 2)
		infile = argv[1];
	else
		infile = "wdb.3.all";

	if ((p = (USHORT *)AllocMem(PCount*PNTSiz,MEMF_FAST)) == NULL)
	{
		Write(Output(), "Insufficient memory for buffer\n", 31L);
		exit(0);
	}
	init_gfx();
	OpenContrWindow();
	MainMsgBit = 1 << w->UserPort->mp_SigBit;
	ContrMsgBit = 1 << Contr->UserPort->mp_SigBit;
	FOREVER
	  { MsgBits = Wait(MainMsgBit | ContrMsgBit);
	  	if(MsgBits & MainMsgBit)
			win = w;
		else if (MsgBits & ContrMsgBit)
			win = Contr;
		while (im = (struct IntuiMessage *) GetMsg(win->UserPort))
		  { code = im->Code;
			class = im->Class;
			gg_addr = im->IAddress;
			ReplyMsg(im);
			switch(class)
			  {	case GADGETUP:
			  		switch(gg_ix)
					  {	case gidOK:
draw_map:					SetSpecs();				 /* redo parameters	*/
							WindowToBack(Contr);
							SetAPen(rp,0);	 /* clear screen	*/
							RectFill(rp,0,0,639,399);
							SetAPen(rp,1);
							load(infile);		 /* redisplay map	*/
							ActivateWindow(Contr);
							WindowToFront(Contr);
					  		break;
						case gidQUIT:
							goto exit;
						case gidCROSS:
							break;
					  	case gidMAG:
							zoom = ((MagGgtSInfo.HorizPot+1) * 30.0) / 0xffff;
							val = 10.0 * zoom;
							if(zoom < .5) 
								zoom = .833;
							sprintf(StrGgtSIBuff,"%5.2f",zoom);
							RefreshGadgets(&StrGgt,Contr,NULL,1);
					  		break;
						case gidSTR:
							zoom = atof(StrGgtSIBuff);
							val = 10.0 * zoom;
							ModifyProp(&MagGgt,Contr,NULL,MagGgtSInfo.Flags,
							 (short)((zoom * 0xffff)/30.0 - 1.0),
							 MagGgtSInfo.VertPot,
							 MagGgtSInfo.HorizBody,
							 MagGgtSInfo.VertBody);
							break;
					  }
					break;
				case VANILLAKEY:
					switch(code)
					  {
						case 'c':
							ActivateGadget(&StrGgt,Contr,NULL);
							break;
						case 'o':
							goto draw_map;
						case 'q':
							goto exit;
						default:
							break;
					  }
					break;
				case MENUPICK:
					switch (ITEMNUM(code))
					  {	case 0:					 /* new specs	*/
							WindowToFront(Contr);
							break;
						case 1:
							title ^= TRUE;
							ShowTitle(s, title);
							break;
						case 3:						/* print */
							break;
						case 4:
exit:						quit();
							break;
					  }
			  }
		  }
	  }
}

/***************************** nitty gritty **********************************/
void load(fn)
	char *fn;
{
	register long x, y;
	register PNT	*pp;
	PNT	*pend;
	struct FileHandle *in;
	long	z,LonPrv=0,LatPrv=0,xprv=0,yprv;
	short	newseg=0,n;

	if (in = Open(fn, MODE_OLDFILE)) {
		while (n = (short) Read(in, p, (long)PCount*PNTSiz))
		{
			for (pp = p,pend = p+n/6; pp < pend; pp++)
			{					/* do displacement	*/
				x = pp->Lon*100 - Longitude;
				y = pp->Lat*100 - Latitude;
								/* wrap around for East-West	*/
				if (x < -HSPAN)
					x += WSPAN;
				else if (x > HSPAN)
					x -= WSPAN;
								/* ignore pts outside magnified area	*/
				if((x < xmin || x > xmax || y < ymin || y > ymax))
				  {	newseg = 1;
					continue;
				  }
				if(ABS(x - LonPrv) >= xspan || ABS(y - LatPrv) >= yspan)
					newseg = 1;
				LonPrv = x;
				LatPrv = y;
								/* scale pts w/in area to interlace screen	*/
				x = 320 + (x * X_Scale)/10000;
				y = 200 - (y * Y_Scale)/10000;
								/* ignore duplicates	*/
				if (x == xprv && y == yprv)
					continue;
								/* if over edge, set for return	*/

				if (newseg || pp->Code > 5 || ABS(z - pp->Lon) > 10800)
				  {	SetAPen(rp, colr[pp->Code / 1000]);
					Move(rp, x, y);
					WritePixel(rp, x, y);
					newseg = 0;
				  }
				else
					Draw(rp, x, y);
				xprv = x;
				yprv = y;
				z = pp->Lon;
			}
		}
		Close(in);
	}
}
