/***************** Display WorldData Base ********************/

#include	<clib/macros.h>
#include	<functions.h>
#include	<intuition/intuition.h>
#include	<libraries/dosextens.h>
#include	<exec/memory.h>

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

#define	gidMAGS 1
#define gidLATS	2
#define gidLONS	3
#define gidMAG	4
#define gidLAT	5
#define gidLON	6
#define gidPLOT	7
#define gidQUIT 8
#define gidSTRCH 9
#define PCount	1024

	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)

	PNT	*p;
	double	zoom,atof(),stretch = 1.2;
	long	Latitude, Longitude,
			Lat,Lon,X_Scale, Y_Scale,
			ymax,ymin,xmax,xmin,xspan,yspan;
	ULONG	class;
	short	xx,yy;
	char	*infile;
	UBYTE	title[50],UndoBuf[10];

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

	UBYTE 
		LonSGgtSIBuff[10] = "   0'0",
		LatSGgtSIBuff[10] = "   0'0",
		MagSGgtSIBuff[10] =  " 1.00",
		StrchGgtSIBuff[10] = " 1.20";

	SHORT 
		CTable[] = { 0x0000,0x0ddd,0x0d00,0x00a0,0x0ff0,0x05f5,0x0aaf,0x033f },
		BoolVectors[] = { 0,0, 35,0, 35,10, 0,10, 0,0 },
		BorderVectors3[] = { 0,0, 45,0, 45,9, 0,9, 0,0 },
		BorderVectors4[] = { 0,0, 58,0, 58,9, 0,9, 0,0 },
		BorderVectors5[] = { 0,0, 66,0, 66,9, 0,9, 0,0 };

	struct Border 
		BoolBorder = { -2,-1, 1,0,JAM1, 5, BoolVectors, NULL },
		Border3 = { -2,-1, 3,0,JAM1, 5, BorderVectors3, NULL },
		Border4 = { -2,-1, 3,0,JAM1, 5, BorderVectors4, NULL },
		Border5 = { -2,-1, 3,0,JAM1, 5, BorderVectors5, NULL };

	struct IntuiText 
		quitIT = { 3,2,JAM1,  2,1,&ta,(UBYTE *)"Quit" ,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 },
		IText1 = { 2,0,JAM2, -120,1, NULL,
			(UBYTE *)"Horiz Stretch:", NULL },
		IText2 = { 1,2,JAM2, 0,1, NULL, (UBYTE *)"Quit", NULL },
		IText3 = { 1,2,JAM2, 0,1, NULL, (UBYTE *)"Plot", NULL },
		IText4 = { 2,0,JAM2, -80,0, NULL, (UBYTE *)"Longitude", NULL },
		IText5 = { 2,0,JAM2, 64,0, NULL, (UBYTE *)"Latitude", NULL },
		IText6 = { 2,0,JAM2, -120,1, NULL,
			(UBYTE *)"Magnification:", NULL },
		IText7 = { 2,0,JAM2, -9,-9, NULL, 
			(UBYTE *)"x0       x40      x80     x120", NULL };

	struct StringInfo 
		StrchGgtSInfo = { StrchGgtSIBuff, UndoBuf, 0, 8, 0,
			0,0,0,0,0, 0, 0, NULL },
		LonSGgtSInfo = { LonSGgtSIBuff, UndoBuf, 0, 8, 0,
			0,0,0,0,0, 0, 0, NULL },
		LatSGgtSInfo = { LatSGgtSIBuff, UndoBuf, 0, 7, 0,
			0,0,0,0,0, 0, 0, NULL },
		MagSGgtSInfo = { MagSGgtSIBuff, UndoBuf, 0, 6, 0,
			0,0,0,0,0, 0, 0, NULL };

	struct PropInfo 
		LonGgtSInfo = { AUTOKNOB+FREEHORIZ, 32767,-1, 1820,1456, },
		MagGgtSInfo = { FREEHORIZ, 4400,0, 545,-1, },
		LatGgtSInfo = { AUTOKNOB+FREEVERT, -1,32767, 1456,3640, };

	USHORT ImageData2[] = { 0x0800,0x1C00,0x3E00,0x7F00,0xFF80 };

	struct Image 
		Image1 = { 155,0, 6,8, 1,       NULL, 0x0000,0x0000, NULL },
		Image2 = {  13,1, 9,5, 1, ImageData2, 0x0002,0x0000, NULL },
		Image3 = {   0,33,6,8, 1,       NULL, 0x0000,0x0000, NULL };

	struct Gadget 
		StrchGgt = { NULL, 176,65, 45,8, NULL, RELVERIFY,
			STRGADGET, (APTR)&Border5, NULL, &IText1, NULL,
			(APTR)&StrchGgtSInfo, gidSTRCH, NULL },
		QuitGgt = { &StrchGgt, 100,122, 32,9, NULL, RELVERIFY,
			BOOLGADGET, (APTR)&BoolBorder, NULL, &IText2, NULL,
			NULL, gidQUIT, NULL },
		PlotGgt = { &QuitGgt, 60,122, 32,9, NULL, RELVERIFY,
			BOOLGADGET, (APTR)&BoolBorder, NULL, &IText3, NULL,
			NULL, gidPLOT, NULL },
		LonSGgt = { &PlotGgt, 176,28, 66,8, NULL, RELVERIFY+STRINGRIGHT,
			STRGADGET, (APTR)&Border5, NULL, &IText4, NULL,
			(APTR)&LonSGgtSInfo, gidLONS, NULL },
		LatSGgt = { &LonSGgt, 42,15, 56,8, NULL, RELVERIFY+STRINGRIGHT,
			STRGADGET, (APTR)&Border4, NULL, &IText5, NULL,
			(APTR)&LatSGgtSInfo, gidLATS, NULL },
		LonGgt = { &LatSGgt, 60,43, 180,12, NULL, RELVERIFY+GADGIMMEDIATE,
			PROPGADGET, (APTR)&Image1, NULL, NULL, NULL,
			(APTR)&LonGgtSInfo, gidLON, NULL },
		MagSGgt = { &LonGgt, 176,81, 45,8, NULL, RELVERIFY+STRINGRIGHT,
			STRGADGET, (APTR)&Border5, NULL, &IText6, NULL,
			(APTR)&MagSGgtSInfo, gidMAGS, NULL },
		MagGgt = { &MagSGgt, 19,106, 220,11, GADGIMAGE, 
			RELVERIFY+GADGIMMEDIATE,
			PROPGADGET, (APTR)&Image2, NULL, &IText7, NULL,
			(APTR)&MagGgtSInfo, gidMAG, NULL },
		LatGgt = { &MagGgt, 18,14, 14,72, NULL, RELVERIFY+GADGIMMEDIATE,
			PROPGADGET, (APTR)&Image3, NULL, NULL, NULL,
			(APTR)&LatGgtSInfo, gidLAT, NULL };


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

	#define MenuFlags  ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP

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

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


/************** convert Minutes to "ddd'mm" *************/
void MinToStr(str,min)
	char	*str;
	long	min;
{
	short	deg;

	deg = min / 60;
	min = min - deg * 60;
	if(min < 0)
		min = -min;
	sprintf(str,"%d'%d",deg,min);
}
/************* Convert "ddd'mm" to mins ***********/
long	DegToMin(s)
	char	*s;
{
	short	deg,min;
	char	str[10],*strchr(),*cp;

	strcpy(str,s);
	if(cp = strchr(str,'\047'))
	  { *cp = '\0';
		min = atoi(++cp);
	  }
	else
		min = 0;
	if((deg = atoi(str)) < 0)
		min = -min;
	return(deg * 60 + min);
}
/********************* Interpret Window Specs **********************/
void SetSpecs()
{

	Longitude = (Lon = DegToMin(LonSGgtSIBuff)) * 100;
	Latitude  = (Lat = DegToMin(LatSGgtSIBuff)) * 100;
	zoom      = atof(MagSGgtSIBuff);
		/* 120/100 is correction for vertical stretch of 1080 Monitor	*/
	X_Scale   = zoom * 100.0 * stretch * 320.0 / 10800.0;	
	Y_Scale   = zoom * 100.0 * 200.0 /  5400.0;	
	ymax = QSPAN/zoom;
	ymin = -ymax;
	xmax = HSPAN / (zoom * stretch);
	xmin = -xmax;
	xspan = xmax - xmin;
	yspan = ymax - ymin;
}

/*******************  Initialize Graphics ****************/
struct NewScreen ns = {
	0,0,640,400,3,2,1,HIRES|LACE,CUSTOMSCREEN,&ta,
	NULL,NULL,NULL
};

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

void init_gfx()
{
	void quit();

	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;
	nw.IDCMPFlags = MENUPICK | MOUSEBUTTONS;
	nw.Title = (UBYTE *)"Micro WorldDataBase-II  Version 2.0";

	if (!(w = OpenWindow(&nw)))
		quit();
	SetMenuStrip(w,&m);
	rp = w->RPort;
}

/************************** 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);
}

/*********************** Open Window ************************/
void OpenContrWindow()
{
	nw.Flags = SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH;
	nw.IDCMPFlags = GADGETUP | VANILLAKEY;
	nw.TopEdge = 200;
	nw.LeftEdge = 10;
	nw.Width = 256;
	nw.Height = 138;
	nw.FirstGadget = &LatGgt;
	nw.DetailPen = 3;
	nw.Title = "Specs Control";
	Contr = (struct Window *)OpenWindow(&nw);
}

/******************** nitty gritty ***************************/
void load(fn)
	char	*fn;
{
	register long x, y, LonPrv,LatPrv;
	register PNT	*pp;
	PNT	*pend;
	struct FileHandle	*fh,*Open();
	long	xx,yy,z,xprv=0,yprv;
	short	is_out=0,was_out=0,
			n,ColorNum,SegNum,SegPrv,newseg;

	LonPrv = LatPrv = 0;
	if(fh = Open(fn,MODE_OLDFILE))
	  {
		while (n = (short) Read(fh, 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;

				if (pp->Code > (int)5)
				  {	
				  	SetAPen(rp, colr[ColorNum = (pp->Code / 1000)]);
					SegNum = pp->Code - 1000 * ColorNum;
				  	newseg = 1;
				  }
							/* ignore pts outside magnified area	*/
				if((x < xmin || x > xmax || y < ymin || y > ymax))
				  {	
				  	is_out = 1;
					if(was_out)				/* out to out	*/
					  {
						LonPrv = x;
						LatPrv = y;
						SegPrv = SegNum;
					  	goto go_on;
					  }
					  						/* in to out	*/
					xx = 320 + (LonPrv * X_Scale)/10000;
					yy = 200 - (LatPrv * Y_Scale)/10000;
					Move(rp, xx, yy);
				  }
				else
				  {							/* out to in	*/
					is_out = 0;
					if(was_out)
					  {
						xx = 320 + (LonPrv * X_Scale)/10000;
						yy = 200 - (LatPrv * Y_Scale)/10000;
						Move(rp, xx, yy);
					  }
					  						/* in to in	*/
				  }
				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 (newseg  == 0 && x == xprv && y == yprv)
					continue;
								/* if new segment, move to place	*/
				if (newseg == 1 || ABS(z - pp->Lon) > 10800)
				  {	
					Move(rp, x, y);
					WritePixel(rp, x, y);
				  }
				else			/* draw next point of seg	*/
					Draw(rp, x, y);
				SegPrv = SegNum;
				xprv = x;
				yprv = y;
				z = pp->Lon;
go_on:
				was_out = is_out;
				newseg = 0;
			}
		  }
		Close(fh);
	  }
}
/***************************** main routine ********************************/
main(argc, argv)
	int argc;
	char *argv[];
{
	void load();
	struct IntuiMessage *im;
	long seetitle = FALSE,
		MsgBits,MainMsgBit, ContrMsgBit;
	struct FileLock	*lock,*Lock();
	char	*infile,*PickFile();
	short	NewLon,NewLat,deflt = 1;
	USHORT newCenter = 0,code;

	if (argv[1][1] == '?')
	  {
		Write(Output(), "Usage: WDB [data_file]\n", 14L);
		exit(10);
	  }

	if (argc == 2)
	  {	if ((lock = Lock(argv[1], ACCESS_READ)) == NULL)
			goto nofind;
		UnLock(lock);
		infile = argv[1];
		deflt = 0;
	  }
	else if ((infile = PickFile(1.0)) == NULL)
nofind:
	  { Write(Output(), "Cannot find data file\n",21L);
	  	exit(10);
	  }
	if ((p = (USHORT *)AllocMem(code = PCount*PNTSiz,MEMF_FAST)) == NULL)
	{
		Write(Output(), "Insufficient memory for buffer\n", 31L);
		exit(0);
	}
	init_gfx();
	OpenContrWindow();
	ModifyProp(&MagGgt,Contr,NULL,MagGgtSInfo.Flags,
	 (short)(0xffff/120.0 - 1.0), MagGgtSInfo.VertPot,
	 MagGgtSInfo.HorizBody, MagGgtSInfo.VertBody);
	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;
			xx = im->MouseX;
			yy = im->MouseY;
			ReplyMsg(im);
			switch(class)
			  {	case GADGETUP:
			  		switch(gg_ix)
					  {	case gidPLOT:
draw_map:					SetSpecs();				 /* redo parameters	*/
							WindowToBack(Contr);
							SetAPen(rp,0);	 /* clear screen	*/
							RectFill(rp,0,0,639,399);
							SetAPen(rp,1);
							if(newCenter)
							  {	Lon = NewLon;
							  	Lat = NewLat;
								newCenter = 0;
							  }
							load(infile);		 /* redisplay map	*/
							ActivateWindow(Contr);
							WindowToFront(Contr);
					  		break;
						case gidQUIT:
							goto exit;
						case gidLAT:
							Lat =
							 5400L - (((LatGgtSInfo.VertPot+1) * 10800L) >> 16);
							MinToStr(LatSGgtSIBuff,Lat);
							RefreshGadgets(&LatSGgt,Contr,NULL,1);
							break;
						case gidLON:
							Lon =
							 (((LonGgtSInfo.HorizPot+1) * 21600L) >> 16)-10800L;
							MinToStr(LonSGgtSIBuff,Lon);
							RefreshGadgets(&LonSGgt,Contr,NULL,1);
							break;
					  	case gidMAG:
							zoom = ((MagGgtSInfo.HorizPot+1) * 120.0) / 0xffff;
new_zoom:					if(zoom < .86) 
								zoom = .86;
							if(deflt)
								infile = PickFile(zoom);
							Move(Contr->RPort,148,128);
							Text(Contr->RPort,infile,strlen(infile));
							sprintf(MagSGgtSIBuff,"%5.2f",zoom);
							RefreshGadgets(&MagSGgt,Contr,NULL,1);
					  		break;
						case gidLONS:
							Lon = DegToMin(LonSGgtSIBuff);
							ModifyProp(&LonGgt,Contr,NULL,LonGgtSInfo.Flags,
							 (short)(((Lon + 10800L) << 16) / 21600 - 1),
							 LonGgtSInfo.VertPot,
							 LonGgtSInfo.HorizBody,
							 LonGgtSInfo.VertBody);
							break;
						case gidLATS:
							Lat = DegToMin(LatSGgtSIBuff);
							ModifyProp(&LatGgt,Contr,NULL,LatGgtSInfo.Flags,
							 LatGgtSInfo.HorizPot,
							 (short)(1 - ((Lat + 5400L) << 16) / 21600L),
							 LatGgtSInfo.HorizBody,
							 LatGgtSInfo.VertBody);
							break;
						case gidMAGS:
							zoom = atof(MagSGgtSIBuff);
							ModifyProp(&MagGgt,Contr,NULL,MagGgtSInfo.Flags,
							 (short)((zoom * 0xffff)/120.0 - 1.0),
							 MagGgtSInfo.VertPot,
							 MagGgtSInfo.HorizBody,
							 MagGgtSInfo.VertBody);
							goto new_zoom;
						case gidSTRCH:
							stretch = atof(StrchGgtSIBuff);
							break;
					  }
					break;
				case VANILLAKEY:
					switch(code)
					  {
						case 'c':
							ActivateGadget(&MagSGgt,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:
							seetitle ^= TRUE;
							ShowTitle(s, seetitle);
							break;
						case 2:
							/*
							dbug = dbug ? 0 : 1;
							*/
							break;
						case 3:
exit:						quit();
							break;
					  }
				case MOUSEBUTTONS:
					if (zoom && code == SELECTUP)
					  { 
						NewLon = Lon + 
						 ((xx - 320.0) * 10800.0) / (320.0 * zoom * stretch);
						NewLat = Lat +
						 ((200.0 - yy) * 5400.0) / (200.0 * zoom);
						newCenter = 1;
						MinToStr(LonSGgtSIBuff,NewLon); 
						MinToStr(LatSGgtSIBuff,NewLat); 
						RefreshGadgets(&LatSGgt,Contr,NULL,2);
						ModifyProp(&LonGgt,Contr,NULL,LonGgtSInfo.Flags,
						 (short)(((NewLon + 10800L) << 16) / 21600 - 1),
						 LonGgtSInfo.VertPot,
						 LonGgtSInfo.HorizBody,LonGgtSInfo.VertBody);
						ModifyProp(&LatGgt,Contr,NULL,LatGgtSInfo.Flags,
						 LatGgtSInfo.HorizPot,
						 (short)(1 - ((NewLat + 5400L) << 16) / 10800),
						 LatGgtSInfo.HorizBody,LatGgtSInfo.VertBody);
					  }
					break;
			  }
		  }
	  }
}

/********************************************/
char	*PickFile(mag)
	double	mag;
{
	static double	maglvl[] = { 0.0, 36.0, 12.0, 6.0, 2.0 };
	static char		filename[12];
	struct FileLock	*lock,*Lock();
	short	level;

for(level = 1; level < 5; level++)
  {
	if(mag > maglvl[level])
		break;
  }

for( ; level < 6; level++)
  {
	sprintf(filename,"wdb.%d.all",level);
	if (lock = Lock(filename, ACCESS_READ))
	  { UnLock(lock);
		return(filename);
	  }
  }
return(NULL);
}

_wb_parse() {}
