/*  :ts=8 bk=0
 *
 * demo.c:	Demonstrates The Incredible New Iconification Program!!!!!!
 *
 * Leo L. Schwab			8712.10
 */
#include <exec/types.h>
#include <intuition/intuition.h>
#include "iconify.h"

#define	LENGTH		20

extern void	*OpenLibrary(), *OpenWindow(), *GetMsg();
extern long	VBeamPos();


/*  The Boing icon image  */
UWORD icon[] = { 
	0xFFFF,   0xFFFF,   0xFFFF,   0xC000, 
	0x8000,   0x0,   0x0,   0x4000, 
	0x8000,   0x0,   0x0,   0x4000, 
	0x8000,   0x1DF7,   0x0,   0x4000, 
	0x8001,   0xFBEF,   0xB000,   0x4000, 
	0x800D,   0xF7DF,   0x7C00,   0x4000, 
	0x803B,   0xEFBE,   0xFB80,   0x4000, 
	0x8077,   0xDF7D,   0xF7C0,   0x4000, 
	0x80EF,   0xBEFB,   0xEFA0,   0x4000, 
	0x81DF,   0x7DF7,   0xDF70,   0x4000, 
	0x83BE,   0xFBEF,   0xBEF8,   0x4000, 
	0x837D,   0xF7DF,   0x7DF0,   0x4000, 
	0x82FB,   0xEFBE,   0xFBE8,   0x4000, 
	0x81F7,   0xDF7D,   0xF7D8,   0x4000, 
	0x83EF,   0xBEFB,   0xEFB8,   0x4000, 
	0x81DF,   0x7DF7,   0xDF70,   0x4000, 
	0x80BE,   0xFBEF,   0xBEE0,   0x4000, 
	0x807D,   0xF7DF,   0x7DC0,   0x4000, 
	0x803B,   0xEFBE,   0xFB80,   0x4000, 
	0x8007,   0xDF7D,   0xF600,   0x4000, 
	0x8001,   0xBEFB,   0xF000,   0x4000, 
	0x8000,   0x1DF7,   0x0,   0x4000, 
	0x8000,   0x0,   0x0,   0x4000, 
	0x8000,   0x0,   0x0,   0x4000, 
	0xFFFF,   0xFFFF,   0xFFFF,   0xC000,

	0x0,   0x0,   0x0,   0x0, 
	0x0,   0x0,   0x0,   0x0, 
	0x0,   0x0,   0x0,   0x0, 
	0x0,   0x1F0,   0x0,   0x0, 
	0x1,   0xF860,   0x3000,   0x0, 
	0xC,   0x301C,   0x7C00,   0x0, 
	0x18,   0xE3E,   0x1800,   0x0, 
	0x7,   0x1F0C,   0x700,   0x0, 
	0xF,   0x8603,   0x8F80,   0x0, 
	0x1C3,   0x1C7,   0xC300,   0x0, 
	0x180,   0xE3E1,   0x80E0,   0x0, 
	0x71,   0xF0C0,   0x71F0,   0x0, 
	0xF8,   0x6038,   0xF860,   0x0, 
	0x30,   0x1C7C,   0x3018,   0x0, 
	0xE,   0x3E18,   0xE38,   0x0, 
	0x11F,   0xC07,   0x1F00,   0x0, 
	0x86,   0x38F,   0x8600,   0x0, 
	0x1,   0xC7C3,   0x1C0,   0x0, 
	0x3,   0xE180,   0xE380,   0x0, 
	0x0,   0xC071,   0xF000,   0x0, 
	0x0,   0x38F8,   0x7000,   0x0, 
	0x0,   0x1C30,   0x0,   0x0, 
	0x0,   0x0,   0x0,   0x0, 
	0x0,   0x0,   0x0,   0x0, 
	0x0,   0x0,   0x0,   0x0
};

static struct Image iconimg = {		/*  Icon Image  */
 	0, 0,
	50, 25, 2,
	icon,
	0x3, 0,
	NULL
};


static WORD bordbox[] = {	/*  A box with an X in it  */
	0, 0,
	ICONWIDTH-1, 0,
	ICONWIDTH-1, ICONHEIGHT-1,
	0, ICONHEIGHT-1,
	0, 0,
	ICONWIDTH-1, ICONHEIGHT-1,
	ICONWIDTH-1, 0,
	0, ICONHEIGHT-1
};

static struct Border iconbord = {	/*  Icon border  */
 	0, 0,
	1, 0, JAM1,
	8,
	bordbox,
	NULL,
};


/**************************************************************************
* Gadgets for the application's window.
*/

static WORD box[] = {
	-1, -1,
	48, -1,
	48, 10,
	-1, 10,
	-1, -1
};

static struct Border bord = {	/*  Window gadget border  */
 	0, 0,
	1, 0, JAM1,
	5,
	box,
	NULL,
};

static struct IntuiText text[] = {
 {
	1, 0, JAM1,
	4, 1,
	NULL,
	(UBYTE *) "Image",
	NULL,
 }, {
	1, 0, JAM1,
	4, 1,
	NULL,
	(UBYTE *) "Bordr",
	NULL,
 }, {
	1, 0, JAM1,
	4, 1,
	NULL,
	(UBYTE *) "Funct",
	NULL,
 }
};

static struct Gadget gads[] = {
 {			/*  Image  */
	&gads[1],
	0, -10, 48, 10,
	GADGHCOMP | GRELBOTTOM,
	RELVERIFY | BOTTOMBORDER,
	BOOLGADGET,
	(APTR) &bord,
	NULL,
	&text[0],
	NULL, NULL,
	ICON_IMAGE, 0
 }, {			/*  Border  */
	&gads[2],
	48, -10, 48, 10,
	GADGHCOMP | GRELBOTTOM,
	RELVERIFY | BOTTOMBORDER,
	BOOLGADGET,
	(APTR) &bord,
	NULL,
	&text[1],
	NULL, NULL,
	ICON_BORDER, 0
 }, {			/*  Function  */
	NULL,
	96, -10, 48, 10,
	GADGHCOMP | GRELBOTTOM,
	RELVERIFY | BOTTOMBORDER,
	BOOLGADGET,
	(APTR) &bord,
	NULL,
	&text[2],
	NULL, NULL,
	ICON_FUNCTION, 0
 }
};

struct NewWindow windef = {
	0, 0, 400, 100,
	-1, -1,
	CLOSEWINDOW | GADGETUP,
	WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SMART_REFRESH |
	 NOCAREREFRESH | ACTIVATE,
	gads,
	NULL,
	(UBYTE *) "Click on gadgets below and be amazed!",
	NULL, NULL,
	0, 0, 0, 0,
	WBENCHSCREEN
};

struct Window	*win;
long		xa1[LENGTH], xa2[LENGTH], ya1[LENGTH], ya2[LENGTH];
short		rnd();				/*  Forward reference  */
void		iconfunc();			/*  Forward reference  */
void		*IntuitionBase, *GfxBase;


main ()
{
	register struct IntuiMessage	*msg;
	register struct Gadget		*gad;
	long				class;
	UWORD				x = 0, y = 0;
	int				type;
	void				*ptr;

	openstuff ();
	rnd ((int) -VBeamPos());
	doline (win, 1);

	while (1) {
		if (msg = GetMsg (win -> UserPort)) {
			class = msg -> Class;
			gad = (struct Gadget *) msg -> IAddress;
			ReplyMsg (msg);

			if (class == CLOSEWINDOW)
				break;
			else {
				switch (gad -> GadgetID) {
				case ICON_IMAGE:
					ptr = &iconimg;
					break;

				case ICON_BORDER:
					ptr = &iconbord;
					break;

				case ICON_FUNCTION:
					ptr = (void *) iconfunc;
					break;
				}

				/*
				 * And now!  The moment you've been waiting
				 * for!
				 */
				windef.LeftEdge = win -> LeftEdge;
				windef.TopEdge	= win -> TopEdge;
				CloseWindow (win);  win = NULL;

				iconify (&x, &y, ICONWIDTH, ICONHEIGHT,
					 NULL, ptr, (int) gad -> GadgetID);

				if (!(win = OpenWindow (&windef)))
					die ("Window re-open failed\n");

				doline (win, 1);
			}
		}
		doline (win, 0);
		WaitTOF ();
	}
	closestuff ();
}

doline (win, reset)
struct Window *win;
int reset;
{
	register struct RastPort	*rp = win -> RPort;
	static long			x1, x2, y1, y2, dx1, dx2, dy1, dy2;
	static long			xmin, ymin, xmax, ymax;
	static int			i, flag;

	if (reset) {
		xmin	= win -> BorderLeft;
		ymin	= win -> BorderTop;
		xmax	= win->Width - win->BorderRight - 1;
		ymax	= win->Height - win->BorderBottom - 1;
		x1 = rnd ((int) xmax);  y1 = rnd ((int) ymax);
		x2 = rnd ((int) xmax);  y2 = rnd ((int) ymax);
		setdisp (&dx1, &dy1);
		setdisp (&dx2, &dy2);
		SetDrMd (rp, COMPLEMENT);
		i = flag = 0;
	}

	if (!rnd (20))
		if (rnd (2))
			setdisp (&dx1, &dy1);
		else
			setdisp (&dx2, &dy2);

	x1 += dx1;  y1 += dy1;
	if (x1 > xmax || x1 < xmin) {
		dx1 = -dx1;
		x1 = x1<xmin ? xmin : xmax;
	}
	if (y1 > ymax || y1 < ymin) {
		dy1 = -dy1;
		y1 = y1<ymin ? ymin : ymax;
	}

	x2 += dx2;  y2 += dy2;
	if (x2 > xmax || x2 < xmin) {
		dx2 = -dx2;
		x2 = x2<xmin ? xmin : xmax;
	}
	if (y2 > ymax || y2 < ymin) {
		dy2 = -dy2;
		y2 = y2<ymin ? ymin : ymax;
	}

	Move (rp, x1, y1);
	Draw (rp, x2, y2);
	if (flag) {
		Move (rp, xa1[i], ya1[i]);
		Draw (rp, xa2[i], ya2[i]);
	}
	xa1[i] = x1;  ya1[i] = y1;
	xa2[i] = x2;  ya2[i] = y2;

	if (++i >= LENGTH) {
		i = 0;
		flag = 1;
	}
}

setdisp (x, y)
register long *x, *y;
{
	*x = rnd (9) - 4;
	*y = rnd (9) - 4;
}

void
iconfunc (win, init)
struct Window *win;
WORD init;
{
	if (init) {
		/*  Initialization pass, draw a border in the icon  */
		SetAPen (win -> RPort, 1L);
		Move (win -> RPort, 0L, 0L);
		Draw (win -> RPort, win -> Width - 1L, 0L);
		Draw (win -> RPort, win -> Width - 1L, win -> Height - 1L);
		Draw (win -> RPort, 0L, win -> Height - 1L);
		Draw (win -> RPort, 0L, 0L);
		doline (win, 1);
	}
	doline (win, 0);
}

openstuff ()
{
	if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L)))
		die ("-=RJ=-'s missing.\n");

	if (!(GfxBase = OpenLibrary ("graphics.library", 0L)))
		die ("Dale, where are you?\n");

	if (!(win = OpenWindow (&windef)))
		die ("Window painted shut.\n");
}

closestuff ()
{
	if (win)		CloseWindow (win);
	if (GfxBase)		CloseLibrary (GfxBase);
	if (IntuitionBase)	CloseLibrary (IntuitionBase);
}

die (str)
char *str;
{
	extern long	Output();

	Write (Output (), str, (long) strlen (str));
	closestuff ();
	exit (20);
}

/***********************************************************************/
#asm
*\
*  :ts=8
* Yet Another random number generator.  By Leo Schwab.
* Based on an idea posted on the USENET (Thanks, Sam Dicker!)
* For the Manx assembler.
*
* Calling convention:
*  short rnd (range);
*  short range;
*
* 8606.30
*/

		public    _rnd

_rnd		lea	rndseed,a0	Get address of seed
		move.w	4(sp),d1	Get range argument
		tst.w	d1
		ble.s	setseed		Go reset seed


		move.l	(a0),d0		Get seed
		ADD.L   D0,D0
		BHI.S   over
		EORI.L  #$1D872B41,D0
over
		move.l	d0,(a0)		Save new seed
		andi.l	#$ffff,d0	Coerce into word
		divu	d1,d0		Divide by range
		swap	d0		 and get remainder (modulus)
		rts

setseed		neg.w	d1		Probably don't need this
		move.l	d1,(a0)
		rts

		dseg
rndseed		dc.l	0
		cseg
#endasm
