/****************************************************************
 * Polygon drawing demo by John M. Olsen
 * This demo uses the AreaMove, AreaDraw and AreaEnd Functions.
 * It uses a hold and modify (HAM) screen, and the polygons can be
 * any of the possible 4096 colors.  This is done by using a patterned
 * area fill, using separate patterns to modify the red, green, and blue
 * to get to the correct color as fast as possible.
 *
 * My appologies for the sparceness of comments.  It is hopefully clear
 * what I was doing for the most part.
 *
 * This is meant to be compiled with the Manx compiler, and has not been
 * tried under Lettuce.
 *
 * This software is in the public domain, and you can do whatever you want
 * to or with it.
 *
 * John M. Olsen
 * 1547 Jamestown Drive
 * Salt Lake City, UT  84121
 ****************************************************************/

#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <intuition/intuition.h>
#include <stdio.h>

void *OpenLibrary();
struct Window *OpenWindow(), *w, *w2;
struct Screen *OpenScreen(), *s;
struct IntuiMessage *GetMsg(), *msg;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

BYTE *AllocRaster();
WORD areabuffer[250];
struct TmpRas tmpras;
struct AreaInfo myAreaInfo;

USHORT a[] = { 0x9429, 0x4294 };
USHORT b[] = { 0x4294, 0x2942 };

/*****************************************************************
definition of the 320 X 200 HAM screen.
*****************************************************************/
struct NewScreen ss =
{				/*****************/
	0,			/* LeftEdge      */
	0,			/* TopEdge       */
	320,			/* Width         */
	200,			/* Height        */
	6,			/* Depth         */
	0,			/* DetailPen     */
	1,			/* BlockPen      */
	HAM,			/* ViewModes     */
	CUSTOMSCREEN,		/* Type          */
	NULL,			/* *Font         */
	(UBYTE *) "A Dancing Polygon",	/* *DefaultTitle */
	NULL,			/* *Gadgets      */
	NULL			/* *CustomBitMap */
};				/*****************/

struct NewWindow ww =
{				/****************/
	0,			/* LeftEdge	*/
	10,			/* TopEdge	*/
	320,			/* Width	*/
	190,			/* Height	*/
	-1,			/* DetailPen	*/
	-1,			/* BlockPen	*/
	CLOSEWINDOW,		/* IDCMP	*/
	WINDOWCLOSE | ACTIVATE | NOCAREREFRESH | WINDOWDRAG,
	NULL,			/* *FirstGadget	*/
	NULL,			/* *CheckMark	*/
	(UBYTE *)"By John M. Olsen",	/* *Title	*/
	NULL,			/* Screen	*/
	NULL,			/* *Bitmap	*/
	0,0,0,0,		/* Min/Max w,h	*/
	CUSTOMSCREEN		/* Type		*/
};
struct NewWindow ww2 =
{				/****************/
	0,			/* LeftEdge	*/
	0,			/* TopEdge	*/
	320,			/* Width	*/
	190,			/* Height	*/
	-1,			/* DetailPen	*/
	-1,			/* BlockPen	*/
	NULL,			/* IDCMP	*/
	BACKDROP | NOCAREREFRESH,
	NULL,			/* *FirstGadget	*/
	NULL,			/* *CheckMark	*/
	(UBYTE *)NULL,		/* *Title	*/
	NULL,			/* Screen	*/
	NULL,			/* *Bitmap	*/
	0,0,0,0,		/* Min/Max w,h	*/
	CUSTOMSCREEN		/* Type		*/
};

main(argc,argv)
int argc;
char *argv[];
{
	setup();
	drawstuff();
	die(0);
}

setup()
{
	if(!(GfxBase = OpenLibrary("graphics.library",0l)))
		die(1);
	if(!(IntuitionBase = OpenLibrary("intuition.library", 0l)))
		die(2);
	if(!(s = OpenScreen(&ss)))
		die(4);
	ww.Screen = s;
	ww2.Screen = s;
	if(!(w = OpenWindow(&ww2)))
		die(4);
	if(!(w2 = OpenWindow(&ww)))
		die(4);

	/* Set up a buffer for the AreaMove, AreaDraw, and AreaEnd commands */

	InitArea(&myAreaInfo, areabuffer, 100l);
	w->RPort->AreaInfo = &myAreaInfo;
	tmpras.RasPtr = (BYTE *) AllocRaster(320l, 200l);
	tmpras.Size = (long) RASSIZE(320l, 200l);
	w->RPort->TmpRas = &tmpras;
}

drawstuff()
{
	struct RastPort *r;
	register long loop;
	long red, green, blue, x[10], y[10], dx[10], dy[10];


	for(loop = 0l; loop < 5l; loop++)
	{ /* init the position */
		x[loop] = (long)random(w->Width - w->BorderLeft
			- w->BorderRight) + w->BorderLeft;
		y[loop] = (long)random(w->Height - w->BorderTop
			- w->BorderBottom) + w->BorderTop;
		dx[loop] = dy[loop] = 0L;
	}
	r = w->RPort;
	msg = GetMsg(w2->UserPort);
	while(msg->Class != CLOSEWINDOW)
	{
		if(msg)
			ReplyMsg(msg);
		msg = GetMsg(w2->UserPort);

		/* draw with 2 colors this time, and just one the next to */
		/* get all 3 colors modified. */

		SetDrMd(r, JAM2);

		red += random(3) - 1;
		green += random(3) - 1;
		blue += random(3) - 1;

		if(red < 32L) red = 32L;
		if(red > 47L) red = 47L;
		if(green < 48L) green = 48L;
		if(green > 63L) green = 63L;
		if(blue < 16L) blue = 16L;
		if(blue > 31L) blue = 31L;

		SetAPen(r, (long)red);
		SetBPen(r, (long)green);

		/* use 1L as the last parameter if you want to use a 2 word */
		/* pattern, which will give sevier jaggies. */

		SetAfPt(r, &a, 0L);

		/* Do a 5 point polygon */
		for(loop = 0l; loop < 5l; loop++)
		{
			dx[loop] += (long)random(3) - 1L;
			dy[loop] += (long)random(3) - 1L;

			if(dy[loop] > 5L) dy[loop] = 5L;
			if(dx[loop] > 5L) dx[loop] = 5L;
			if(dy[loop] < -5L) dy[loop] = -5L;
			if(dx[loop] < -5L) dx[loop] = -5L;

			if(x[loop] + dx[loop] >  w->Width - w->BorderRight
			|| x[loop] + dx[loop] <  w->BorderLeft)
				dx[loop] *= -1;

			if(y[loop] + dy[loop] >  w->Height - w->BorderBottom
			|| y[loop] + dy[loop]<  w->BorderTop)
				dy[loop] *= -1;

			x[loop] += dx[loop];
			y[loop] += dy[loop];

			if(x[loop] > w->Width - w->BorderRight)
				x[loop] = w->Width - w->BorderRight;
			if(x[loop] < w->BorderLeft)
				x[loop] = w->BorderLeft;
			if(y[loop] > w->Height - w->BorderBottom)
				y[loop] = w->Height - w->BorderBottom;
			if(y[loop] < w->BorderTop)
				y[loop] = w->BorderTop;

			if(loop == 0l)
				AreaMove(r, x[loop], y[loop]);
			else
				AreaDraw(r, x[loop], y[loop]);
		}
		AreaEnd(r);

		SetDrMd(r, JAM1);
		SetAPen(r, (long)blue);
		SetAfPt(r, &b, 0L);
		for(loop = 0l; loop < 5l; loop++)
		{
			if(loop == 0l)
				AreaMove(r, x[loop], y[loop]);
			else
				AreaDraw(r, x[loop], y[loop]);
		}
		AreaEnd(r);
WaitTOF();
		ClipBlit(r, 0L, 10L, w2->RPort, 0L, 10L,
			(long)w->Width, (long)w->Height-10L, 0xc0L);
	}
	if(msg)
		ReplyMsg(msg);
}

/****************************************************************
 * I don't think this random number will set any speed records, but
 * it is guaranteed to be as random as you can get.
 ****************************************************************/
random(max)
int max;
{
	static ULONG num;
	ULONG sec, mic;

	CurrentTime(&sec, &mic);
	num *= sec;
	num += mic;
	while(num > 32000)
		num = num >> 1;
	return((int)(num % (ULONG)max));
}

die(kind)
int kind;
{
	static char *msgs[] = {	"",
		/* err 1 */	"Unable to open graphics library.\n",
		/* err 2 */	"Unable to open intuition library.\n",
		/* err 4 */	"Unable to open a window.\n",
				"\n"
				};

	if(kind)		puts(msgs[kind]);
	if(tmpras.RasPtr)	FreeRaster(tmpras.RasPtr,320l,200l);
	if(w)			CloseWindow(w);
	if(w2)			CloseWindow(w2);
	if(s)			CloseScreen(s);
	if(GfxBase)		CloseLibrary(GfxBase);
	if(IntuitionBase)	CloseLibrary(IntuitionBase);
	exit(kind);
}

