
/*
March 1 87
======================  Geodesic Publications  ========================

#define DEBUG      1
*/

#define LO				long
#define REV               31L
#define WIDTH            320L
#define HEIGHT           200L
#define N_MAPS             1
#define N_BIT_PLANES       4L
#define MAXPOINTS         16L
#define	MENUMAX				2
#define	MENUIMAX		    3

int
	viewon, drawon, *ctab, colorcount, colorcycle, cyclerate, cycler,
	code, menunum, itemnum, subnum, version,
	areabuffer[(MAXPOINTS/2)*5], *pointersprite,
    trace, err, going, i, j, k, n,  *colortab;

int radius, ang, rotation, sides, sidecount, delta, color,
	x1, y1, x2, y2, xcent, ycent;

#define	TWOPIE				256
#define	OFF					0
#define	ON					1
#define	NL					0L

struct DosBase        *DosBase;
struct IntuitionBase  *IntuitionBase;
struct GfxBase        *GfxBase;
struct LayersBase     *LayersBase;
struct Screen         *screen;
struct Window         *window;
struct RastPort       *rp, rptmp;
struct BitMap         bitmapA[ N_MAPS], bitmaptmp;
struct TmpRas         tmpras;
struct AreaInfo       areainfo;
struct MenuItem       menuitem [MENUIMAX];
struct IntuiText      intuitext[MENUIMAX];
struct Menu           menu[MENUMAX];
struct IntuiMessage   *message;
struct ViewPort       *VPort;
struct ColorMap       *CMap;

USHORT default_color[] = {
	0x000, 0x00c, 0x04e, 0x08f, 0x0cc, 0x0e5, 0x0f0, 0xdf0,
	0xee0, 0xfc0, 0xe90, 0xf42, 0xe06, 0xd0a, 0xb0c, 0x90c,
	0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777,
	0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff};


char title[]= "      GEONET 1.0 Source Kit         ";
long *longptr, class, titleon;

WORD	pointer[]= {
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 000000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0081, 0x00c1, /* Center of pointer */
	0x0081, 0x00c1,
	0x0041, 0x0063,
	0x0041, 0x0063,
	0x0022, 0x0036,
	0x0022, 0x0036,
	0x0014, 0x001c,
	0x0014, 0x001c,
	0x0008, 0x0008
};

struct NewScreen ns = {
	0, 0, WIDTH, HEIGHT, N_BIT_PLANES, 0, 1, 0,
	  CUSTOMSCREEN
	| CUSTOMBITMAP
	,NULL, NULL, NULL, NULL
};

struct NewWindow nw = {
	0, 0, WIDTH, HEIGHT, -1,-1, 0
	| MOUSEBUTTONS
	| MENUPICK
	| VANILLAKEY
/*
	| REQVERIFY
	| REQCLEAR
	| MENUVERIFY
	| MOUSEMOVE
*/
	,0					 /*  Regular flags */
	| SUPER_BITMAP 
	| BACKDROP
	| REPORTMOUSE
	| BORDERLESS
	| ACTIVATE
	, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
};

LONG  OpenLibrary();
LONG  AllocRaster();
LONG  AllocMem();
LONG  OpenScreen();
LONG  OpenWindow();
LONG  GetMsg();
LONG  ViewPortAddress();
LONG  GetColorMap();

main(argc, argv)
int argc;
char *argv[];
{
	trace = argc > 1;

	#ifdef DEBUG
	trace = 1;
	printf("\nmain: Start Debug Tracer...\n");
	#endif

	if ( !(IntuitionBase = OpenLibrary("intuition.library",REV) ))
		exit_program("Can not open Intuition ", 1);
	if ( !(GfxBase = OpenLibrary("graphics.library",REV) )) 
		exit_program("Can not open graphics ", 2);
	if( !(LayersBase = OpenLibrary("layers.library",REV)))
		exit_program("Can not open layers ", 3);

	#ifdef DEBUG
	printf("main: Intuition= %8lx Graphics= %8lx Layers= %8lx\n",
		IntuitionBase, GfxBase, LayersBase);
	#endif

	for (i=0; i< N_MAPS; i++){
		InitBitMap( &bitmapA[i], N_BIT_PLANES, WIDTH, HEIGHT);
		for (j=0; j< N_BIT_PLANES; j++){
			if(!(bitmapA[i].Planes[j]= (PLANEPTR)AllocRaster(WIDTH,HEIGHT))){
				exit_program("Can not allocate bitmap memory", 4);
			} else {
				if(trace)
				printf("Bitmap[%4x ]P[%4x ]=%8lx\n",i,j,bitmapA[i].Planes[j]);
			}
		}
	}

	InitBitMap( &bitmaptmp, 1L, WIDTH, HEIGHT);
	if( !( bitmaptmp.Planes[0] = (PLANEPTR)AllocRaster( WIDTH, HEIGHT) ) ){
		exit_program("Can not allocate tmp bitmap memory", 5);
	} else {
		if(trace)
		printf("           Bitmap_tmp=%8lx\n",bitmaptmp.Planes[0]);
	}

	ns.DefaultTitle =  title;
	ns.CustomBitMap =  nw.BitMap = &bitmapA[0];
	if( !(screen = (struct Screen *)OpenScreen(&ns)))
	    exit_program("Can not open a custom screen", 6);

	nw.Screen = screen;
	if( !(window = (struct Window *)OpenWindow(&nw)) )
	    exit_program("Can not open a new window", 7);
	initmenuitems();
	initmenu();
	SetMenuStrip(window, &menu[0]);

	#ifdef DEBUG
	WBenchToFront();
	printf("main: initialize areainfo to this screen's rastport...\n");
	#endif

	if( window->RPort ){
		InitArea( &areainfo, areabuffer, MAXPOINTS);
		InitTmpRas( &tmpras, bitmaptmp.Planes[0], RASSIZE( WIDTH, HEIGHT ) );
		rp           = &rptmp;
		rptmp        = *window->RPort;
		rp->BitMap   = &bitmapA[0];
		rp->AreaInfo = &areainfo;
		rp->TmpRas   = &tmpras;
	} else exit_program("Null window rastport pointer", 8);

	if( !( pointersprite =AllocMem(64L, MEMF_CHIP) ) )
		exit_program("No memory for pointer buffer", 9);
	for(i=0; i<32; i++) pointersprite[i] = pointer[i];

	if( !( colortab =AllocMem(64L, MEMF_CHIP) ) )
		exit_program("No memory for color buffer", 10);

	init_palette();

	#ifdef DEBUG
	printf("main: Calling the mainloop ...\n");
	Delay( 100L );
	WBenchToBack();
	#endif

	mainloop();

	cleanitup();

	#ifdef DEBUG
	printf("main: Mainloop done ...\n");
	#endif

	exit( 1 );
}

exit_program( errormessage, code )
char *errormessage;
int code;
{
	cleanitup();
	printf("\n%s\nGEONET Exit Code= %d\n", errormessage, code);
	exit( 99 );
}

cleanitup()    /* release allocated resources */
{
	if( colortab ) FreeMem( colortab, 64L );
	if( pointersprite ) FreeMem( pointersprite, 64L );
	if(        window ){
		ClearMenuStrip(window);
		CloseWindow( window );
	}
	if(        screen )CloseScreen( screen );
	if( ( bitmaptmp.Planes[0] ) )
		FreeRaster( bitmaptmp.Planes[0], WIDTH, HEIGHT );
	for (i=0; i< N_MAPS; i++){
		for (j=0; j< N_BIT_PLANES; j++){
			if( ( bitmapA[i].Planes[j] ) ){
				FreeRaster( bitmapA[i].Planes[j], WIDTH, HEIGHT );
			}
		}
	}
	if ( LayersBase     ) CloseLibrary( LayersBase     );
	if ( GfxBase        ) CloseLibrary( GfxBase        );
	if ( IntuitionBase  ) CloseLibrary( IntuitionBase  );
}

initmenuitems()
{
	for(i = 0; i < MENUIMAX; i++) {  /* One struct for each item */
		switch( i ){
		case  0 :  j=  0; k= 50; n=  0; break;
		case  2 :  j=  0; k= 56; n=  0; break;
		}
		menuitem[i].NextItem = &menuitem[i+1]; /* next item */
		menuitem[i].LeftEdge = n;
		menuitem[i].TopEdge = 5 * j; j+=2;
		menuitem[i].Width = k;
		menuitem[i].Height = 10;
		menuitem[i].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
		menuitem[i].MutualExclude = 0;
		menuitem[i].SelectFill = NULL;
		menuitem[i].Command = 0;
		menuitem[i].SubItem = NULL;
		menuitem[i].NextSelect = 0;
		menuitem[i].ItemFill = (APTR)&intuitext[i];
		intuitext[i].FrontPen = 5;
		intuitext[i].BackPen = 11;
		intuitext[i].DrawMode = JAM2;
		intuitext[i].LeftEdge = 0;
		intuitext[i].TopEdge = 1;
		intuitext[i].ITextFont = NULL;
		intuitext[i].NextText = NULL;
	}

	i=0;
	intuitext[i+ 0].IText = (UBYTE *)"Quit";
	intuitext[i+ 1].IText = (UBYTE *)"Info";
	menuitem [i+ 1].NextItem = NULL;

	i=2;
	intuitext[i+ 0].IText = (UBYTE *)"  Cycle";
	menuitem [i+ 0].NextItem = NULL;
	menuitem [i+ 0].MutualExclude =  0x0000;
	menuitem [i+ 0].Flags |= CHECKIT;

}

initmenu()
{
	for(i = 0; i < MENUMAX; i++) {  /* One struct for each item */
		menu[i].NextMenu =  &menu[i+1];
		menu[i].TopEdge = 0;
		menu[i].Height = 10;
		menu[i].Flags = MENUENABLED;			/* All items selectable */
	}
	menu[ 0].MenuName  = "Source";
	menu[ 0].Width     = 50;
	menu[ 0].LeftEdge  = 4;
	menu[ 0].FirstItem = &menuitem[ 0];

	menu[ 1].MenuName  = "Color";
	menu[ 1].Width     = 42;
	menu[ 1].LeftEdge  = 69;
	menu[ 1].FirstItem = &menuitem[ 2];

	menu[ 1].NextMenu  = NULL;
}

mainloop()
{
	ShowTitle(screen, titleon=1L );
	viewon=0;
	for( going=1; going; ){
		if (!(message = (struct IntuiMessage *)GetMsg(window->UserPort)))  {
			if( window->MouseY < 10){
				window->Flags &= ~RMBTRAP;
				if( viewon ){
					viewon= 0;
					ClearPointer( window );
				}
				if(!titleon  )ShowTitle(screen, titleon=1L );
			} else if( !(window->Flags & MENUSTATE) ){
				window->Flags |=  RMBTRAP;
				if( !viewon ){
					viewon = 1;
					SetPointer( window, pointersprite, 15L, 15L, -7L, -7L );
				}
				if( titleon ) ShowTitle(screen, titleon=0L );
			}
			if( viewon ){
				viewer();
			}
			continue;
		}
		ReplyMsg(message);
		class = message->Class;
		code  = message->Code;
		switch (class) {
		case MOUSEMOVE   :/*mousemove();*/ break;
		case MOUSEBUTTONS:
			switch ( code ){
			case SELECTDOWN: mouseselectdown(); break;
			case SELECTUP  : mouseselectup();   break;
			case MENUDOWN  : mousemenudown();   break;
			case MENUUP    : mousemenuup();     break;
			}
			break;
		case VANILLAKEY:
			keyfunction (code);
			break;
		case MENUPICK    : 
			if( code == MENUNULL ) break;
			menunum = MENUNUM( code );
			itemnum = ITEMNUM( code );
			subnum  =  SUBNUM( code );
			switch ( menunum ){
			case 0: menu_source    ( itemnum ); break;
			case 1: menu_color     ( itemnum ); break;
			}
			break;
		}
	}
}

menu_source( item )
int item;
{
	switch( item ){
	case 0: going= OFF;  break;
	case 1: show_info(); break;
	}
}

menu_color ( item )
int item;
{
	switch( item ){
	case 0:
		if( colorcycle= !colorcycle ) menuitem [2].Flags |=  CHECKED;
		else{ set_defmap();           menuitem [2].Flags &= ~CHECKED;}
		break;
	}
}

char line01[] = { "***********************************",0};
char line02[] = { "| GEONET 1.0  KEYBOARD SELECTION: |",0};
char line03[] = { "| q             Quit              |",0};
char line04[] = { "| c             Color Cycle       |",0};
char line05[] = { "| []            Cycle Rate        |",0};
char line06[] = { "| b             Blank the screen  |",0};
char line07[] = { "|                                 |",0};
char line08[] = { "|To return move mouse to top.     |",0};
char line09[] = { "***********************************",0};

struct IntuiText stxt01 = {11,0,JAM2,0,0,NL,(UBYTE *)line01,NL};
struct IntuiText stxt02 = {11,0,JAM2,0,0,NL,(UBYTE *)line02,NL};
struct IntuiText stxt03 = {11,0,JAM2,0,0,NL,(UBYTE *)line03,NL};
struct IntuiText stxt04 = {11,0,JAM2,0,0,NL,(UBYTE *)line04,NL};
struct IntuiText stxt05 = {11,0,JAM2,0,0,NL,(UBYTE *)line05,NL};
struct IntuiText stxt06 = {11,0,JAM2,0,0,NL,(UBYTE *)line06,NL};
struct IntuiText stxt07 = {11,0,JAM2,0,0,NL,(UBYTE *)line07,NL};
struct IntuiText stxt08 = {11,0,JAM2,0,0,NL,(UBYTE *)line08,NL};
struct IntuiText stxt09 = {11,0,JAM2,0,0,NL,(UBYTE *)line09,NL};

show_info()
{
	PrintIText(rp,&stxt01,  20L,   (long)(50    ));
	PrintIText(rp,&stxt02,  20L,   (long)(50+  8));
	PrintIText(rp,&stxt03,  20L,   (long)(50+ 16));
	PrintIText(rp,&stxt04,  20L,   (long)(50+ 24));
	PrintIText(rp,&stxt05,  20L,   (long)(50+ 32));
	PrintIText(rp,&stxt06,  20L,   (long)(50+ 40));
	PrintIText(rp,&stxt07,  20L,   (long)(50+ 48));
	PrintIText(rp,&stxt08,  20L,   (long)(50+ 56));
	PrintIText(rp,&stxt09,  20L,   (long)(50+ 64));
	while( window->MouseY > 10);
}

keyfunction (key)
int key;
{
	switch( key ){
	case 'q' :
	case 'Q' :
		going= OFF;
		break;
	case 'b' : 
		fill( rp->BitMap, 0, 0, 319, 199, 0 ); /* Clear the Screen */
		break;
	case 'c' : 
		if( colorcycle= !colorcycle ) menuitem [2].Flags |=  CHECKED;
		else{ set_defmap();           menuitem [2].Flags &= ~CHECKED;}
		break;
	case '[' : cyclerate = (cyclerate>  20)?  cyclerate- 10 :   20; break;
	case ']' : cyclerate = (cyclerate< 500)?  cyclerate+ 10 :  500; break;
	}
}

init_palette()
{
	VPort = (struct ViewPort *)ViewPortAddress(window);
	CMap = (struct ColorMap *)GetColorMap(32L);
	ctab = (USHORT *)CMap->ColorTable;
	set_defmap();
	cyclerate = 50;
	sides=3;
}
 
set_defmap()
{
	int i;
	for (i=0; i<16; i++) ctab[i] = default_color[ i%16 ];
	LoadRGB4(VPort,ctab, 16L);
}

set_cyclemap()
{
	int i, j;
	j= abs( colorcount++ );
	j %= 16;
	for (i=1; i<16 ; i++) colortab[i] = ctab[ (i+j)%16 ];
	colortab[0] = ctab[0];
	LoadRGB4(VPort, colortab, 16L);
}
 
abs( num )
int num;
{ return( (num>0)? num: -num ); }

mouseselectup(){ drawon = OFF; }
mouseselectdown()
{
	drawon = ON;
	sides = abs( ++sidecount % 4) + 3;       /* 3, 4, 5, 6, 3, 4, ... */
	xcent = window->MouseX;
	ycent = window->MouseY;
}

mousemenuup  (){}
mousemenudown()
{
	OwnBlitter();
	fill( rp->BitMap, 0, 0, 319, 199, 0 ); /* Clear the Screen */
	DisownBlitter();
}

viewer()
{
	if( drawon ){
		OwnBlitter();
		radius= distance( window->MouseX - xcent, window->MouseY - ycent, 0)*2;
		ang    = rotation++;
		delta  = TWOPIE / sides;
		for( i=0; i<sides; i++, ang += delta ){

			x1 = mult( radius, cosi( ang         ) ) + xcent;
			y1 = mult( radius, sini( ang         ) ) + ycent;
			x2 = mult( radius, cosi( ang + delta ) ) + xcent;
			y2 = mult( radius, sini( ang + delta ) ) + ycent;

			x1 = (x1>   0)? x1:   0; /* Clipping */
			x2 = (x2>   0)? x2:   0;
			y1 = (y1>   0)? y1:   0;
			y2 = (y2>   0)? y2:   0;
			x1 = (x1< 319)? x1: 319;
			x2 = (x2< 319)? x2: 319;
			y1 = (y1< 199)? y1: 199;
			y2 = (y2< 199)? y2: 199;

			line( color, x1, y1, x2, y2);

		}
		color++;
		if( !(color& 0xf) ) color++;  /* Skip color 0 */
		DisownBlitter();
	}
	if( colorcycle && !( ++cycler % cyclerate) ) set_cyclemap();
}

/*
Geodesic Publications                      Visual Aural Animations
                               or          PO Box 4898
                                           Arcata, CA 95521
(916) 629-2514                             (707) 822-4800
*/



