/****************************************************************
 * 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.
 *
 * © 1987 John M. Olsen
 *
 * Permission is given to distribute this code wherever you want as long
 * as this notice remains with it.  Do not use any part of it in a commercial
 * application without written consent of the author:
 *
 * 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;
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 *) "H.A.M. Screen",	/* *DefaultTitle */
	NULL,			/* *Gadgets      */
	NULL			/* *CustomBitMap */
};				/*****************/

struct NewWindow ww =
{				/****************/
	0,			/* LeftEdge	*/
	10,			/* TopEdge	*/
	200,			/* Width	*/
	150,			/* Height	*/
	-1,			/* DetailPen	*/
	-1,			/* BlockPen	*/
	CLOSEWINDOW,		/* IDCMP	*/
	WINDOWCLOSE | ACTIVATE | NOCAREREFRESH | WINDOWDRAG | WINDOWDEPTH
	| WINDOWSIZING,
	NULL,			/* *FirstGadget	*/
	NULL,			/* *CheckMark	*/
	(UBYTE *)"H.A.M. Poly Window",	/* *Title	*/
	NULL,			/* Screen	*/
	NULL,			/* *Bitmap	*/
	100,40,320,200,		/* 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;
	if(!(w = 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(640l, 400l);
	tmpras.Size = (long) RASSIZE(640l, 400l);
	w->RPort->TmpRas = &tmpras;
}

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

	r = w->RPort;
	msg = GetMsg(w->UserPort);
	while(msg->Class != CLOSEWINDOW)
	{
		msg = GetMsg(w->UserPort);

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

		SetDrMd(r, JAM2);
		SetAPen(r, (long)(random(16) + 32));
		SetBPen(r, (long)(random(16) + 48));

		/* 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++)
		{
			x[loop] = (long)random(w->Width - w->BorderLeft
				- w->BorderRight) + w->BorderLeft;
			y[loop] = (long)random(w->Height - w->BorderTop
				- w->BorderBottom) + 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)(random(16) + 16));
		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);
	}
}

/****************************************************************
 * 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,640l,400l);
	if(w)			CloseWindow(w);
	if(s)			CloseScreen(s);
	if(GfxBase)		CloseLibrary(GfxBase);
	if(IntuitionBase)	CloseLibrary(IntuitionBase);
	exit(kind);
}

