/*

	Example program to demonstrate usage of the GenHAM() function.
	Created 4th July 1989 By Danny Ross BSc(Hons)

	Another fine product from Johnny Appleseed S/W Development

*/

#include <exec/types.h>
#include <exec/memory.h>

#include <math.h>

#include <graphics/gfx.h>
#include <graphics/clip.h>
#include <graphics/view.h>
#include <graphics/rastport.h>

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <stdio.h>

#include "GenHAM.h"

extern double drand48();
extern void srand48();

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;

#define SINEWAVE (PI/180*2)

struct NewScreen ns =
	{
	0,0,320,200,6,0,1,HAM,CUSTOMSCREEN,
	NULL,NULL,NULL,NULL
	} ;

struct NewWindow nw =
	{
	0,0,320,200,0,0,CLOSEWINDOW|MOUSEBUTTONS,
	BACKDROP|BORDERLESS|NOCAREREFRESH|SIMPLE_REFRESH|WINDOWCLOSE,
	NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN
	} ;

void main(), abend();

struct Window *wndo = NULL;
struct Screen *scrn = NULL;

struct RastPort wholerp, lower8rp, upper4rp;
struct extraBitMap mbm12, mbm4, mbm8;

int r,g,b;

USHORT cinc[] = { 0x001, 0x010, 0x100 } ;

void abend(char *s)
	{
	int i,j;

	if (s) printf("%s\n",s);

	j=mbm12.BytesPerRow*mbm12.Row;
	for (i=0; i<mbm12.Depth; i++)
		{
		if (mbm12.Planes[i]) FreeMem(mbm12.Planes[i],j);
		}

	if (wndo) CloseWindow(wndo);
	if (scrn) CloseScreen(scrn);
	if (GfxBase) CloseLibrary(GfxBase);
	if (IntuitionBase) CloseLibrary(IntuitionBase);
	if (s) exit(1000); else exit(0);
	}

void extractrgb(int i)
	{
	struct ViewPort *vp;
	struct ColorMap *cm;
	USHORT *ct;

	int c;

	vp=&(scrn->ViewPort); cm=vp->ColorMap;

	if (cm->Type==0)
		{
		ct=(USHORT *)(cm->ColorTable);
		c=ct[i];
		EXTRACTRGB(c,r,g,b);
		}
	}

int myRand(int n)
	{
	int i;
	double d;

	d=drand48()*((double)n);
	i=(int)d;
	return(i);
	}

void showcolour(int x, int y)
	{
	int i,j,k,c,mv;
	int mdit[3], mdi;

	i=ReadPixel(wndo->RPort,x,y); printf("Pixel at (%3d,%3d) is ",x,y);
	c=i&0xF; i=(i&0x30)>>4;
	switch (i)
		{
		case 00 : { printf("Colour Index "); break; }
		case 01 : { printf("Modify Blue  "); break; }
		case 02 : { printf("Modify Red   "); break; }
		case 03 : { printf("Modify Green "); break; }
		}
	printf("[%02d]. ",c);
	if (i==0)
		{
		extractrgb(c);
		}
	else
		{
		mv=i; for (i=0; i<3; i++) mdit[i]=(-1);
		mdit[mv-1]=c;

		for (i=(-1), j=(x-1); ((j>=0) && (i==(-1))); j--)
			{
			k=ReadPixel(wndo->RPort,j,y);
			mdi=((k&0x30)>>4)-1;
			if (mdi<0) i=k&0xF; else if (mdit[mdi]<0) mdit[mdi]=k&0xF;
			}
		if (i<0) i=0;
		extractrgb(i);

		if (mdit[0]>0) b=mdit[0];
		if (mdit[1]>0) r=mdit[1];
		if (mdit[2]>0) g=mdit[2];
		}

	printf("Red=%03d, Green=%03d, Blue=%03d\n",r,g,b);
	}

void main()
	{
	struct IntuiMessage *msg;

	ULONG class;
	USHORT code;

	PLANEPTR x;
	int i,j,k,x1,x2,y1,y2,c,closewindow;

	if ((IntuitionBase=(struct IntuitionBase*)OpenLibrary("intuition.library",0))==NULL) abend("can't open Intuition Library");
	if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))==	NULL) abend("can't open Graphics Library");

	InitRastPort(&wholerp); InitBitMap((struct BitMap *)&mbm12,12,320,200);

	InitRastPort(&lower8rp); InitBitMap((struct BitMap *)&mbm8,8,320,200);
	InitRastPort(&upper4rp); InitBitMap((struct BitMap *)&mbm4,4,320,200);

	for (i=0; i<12; i++) mbm12.Planes[i]=mbm8.Planes[i]=mbm4.Planes[i]=NULL;

	for (i=0; i<12; i++)
		{
		if ((x=(PLANEPTR)AllocRaster(320,200))==NULL) abend("out of memory");
		mbm12.Planes[i]=x;
		BltClear(x,RASSIZE(320,200),0);
		if (i<8) mbm8.Planes[i]=mbm12.Planes[i]; else mbm4.Planes[i-8]=mbm12.Planes[i];
		}

	wholerp.BitMap=(struct BitMap *)&mbm12;
	lower8rp.BitMap=(struct BitMap *)&mbm8;
	upper4rp.BitMap=(struct BitMap *)&mbm4;

	srand(0x434154); /* Initialise seed */

	for (k=0; k<500; k++)
		{
		i=myRand(4096);
		c=(i&0xF00)>>8;

		x2=myRand(50); x1=myRand(319-x2);
		y2=myRand(50); y1=myRand(72-y2)+128;

		SetAPen(&lower8rp,(i&0xFF));
		RectFill(&lower8rp,x1,y1,x1+x2,y1+y2);

		SetAPen(&upper4rp,c);
		RectFill(&upper4rp,x1,y1,x1+x2,y1+y2);

		}

	for (k=i=0; i<320; i+=10)
		{
		for (j=0; j<128; j++)
			{
			c=(k&0xF00)>>8;

			SetAPen(&lower8rp,(k&0xFF));
			Move(&lower8rp,i,j); Draw(&lower8rp,i+9,j);

			SetAPen(&upper4rp,c);
			Move(&upper4rp,i,j); Draw(&upper4rp,i+9,j);

			k++;
			}
		}

	c=0;
	for (k=280; k>20; k--)
		{
		j=(int)(64+27*sin(k*SINEWAVE));

		SetAPen(&lower8rp,(c&0xFF));
		Move(&lower8rp,k,j); Draw(&lower8rp,k+30,j);

		SetAPen(&upper4rp,(c&0xF00)>>8);
		Move(&upper4rp,k,j); Draw(&upper4rp,k+30,j);

		c+=2;
		}

	if ((scrn=(struct Screen *)OpenScreen(&ns))==NULL) abend("ham screen wont open");
	ShowTitle(scrn,FALSE); nw.Screen=scrn;
	if ((wndo=(struct Window *)OpenWindow(&nw))==NULL) abend("ham window wont open");
	printf("GenHAM return code=%d\n",GenHAM(wndo,&wholerp)); closewindow=FALSE;

	while (!closewindow)
		{
		Wait( 1 << ((wndo->UserPort)->mp_SigBit) );
		while ((msg=(struct IntuiMessage *)GetMsg(wndo->UserPort))!=NULL)
			{
			class=msg->Class; code=msg->Code; x1=msg->MouseX; y1=msg->MouseY;
			ReplyMsg(msg);

			switch (class)
				{
				case CLOSEWINDOW : { closewindow=TRUE; break; }
				case MOUSEBUTTONS :
					{
					if (code==SELECTDOWN) showcolour(x1,y1);
					break;
					}
				}
			}
		}

	abend(NULL);
	}
