
/******************************************************************************
*
*  lbnc.c - Copyright 1988 Commodore-Amiga, Inc.
*
*	Source Control
*	--------------
*	$Header: lbnc.c,v 36.0 88/05/18 20:18:42 bart Exp $
*
*	$Locker: bart $
*
*	$Log:	lbnc.c,v $
*   Revision 36.0  88/05/18  20:18:42  bart
*   added to rcs for updating
*   
*
******************************************************************************/


#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <graphics/gfx.h>
#include <graphics/clip.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/layers.h>
#include <intuition/intuition.h>

#define COPY    NANBC|NABC|ABNC|ABC

long seed[] = {0xB807C324, 0x9E8732B5, 0x4E50957BC};


/* random number generator */

rand(i)
register short i;
{
	return(seed[i] = seed[i] < 0 ? seed[i] << 1 ^ 0x1D872B41 : seed[i] << 1);
}

#define RWidth	Get_RWidth(w)
#define RHeight	Get_RHeight(w)
#define MAX_CLOSEWINDOW 1

/* #define DEBUG */
/* #define KPRINTF */

#ifdef KPRINTF
#define printf kprintf
#endif

#ifndef DEBUG
#define printf ;
#endif

int close_count;

extern struct Gadget *vgadget_ptr;
extern struct Gadget *hgadget_ptr;

struct BitMap *savesuperbitmap;

#define CLIPPING

clip_for_me(window)
struct Window *window;
{
#ifdef CLIPPING
        struct Rectangle Bounds;
		struct Region *clipregion = NewRegion();

		if(clipregion)
		{

			Bounds.MinX = 0;
			Bounds.MinY = 0;
			Bounds.MaxX = window->Width - window->BorderRight;
			Bounds.MaxY = window->Height - window->BorderBottom;

			/* include only "positive" regions */

			if((Bounds.MinX < Bounds.MaxX)&&(Bounds.MinY < Bounds.MaxY))
			{
				printf("orrectregion:\n");
						printf("Bounds.MinX = %ld\n",Bounds.MinX);
						printf("Bounds.MinY = %ld\n",Bounds.MinY);
						printf("Bounds.MaxX = %ld\n",Bounds.MaxX);
						printf("Bounds.MaxY = %ld\n",Bounds.MaxY);
				OrRectRegion(clipregion,&Bounds);
			}

			/* calculate the rectangle that holds that little piece */
			/* above the size gadget */

			if(TRUE)
			{
				USHORT exclude = SYSGADGET;
				struct Gadget *g;
				for (g = window->FirstGadget; g ; g = g->NextGadget)
				{
					if (!(g->GadgetType & exclude))
					{
						Bounds.MinX = g->LeftEdge-window->BorderLeft;
						Bounds.MinY = g->TopEdge-window->BorderTop;
						Bounds.MaxX = g->LeftEdge+g->Width-1;
						Bounds.MaxY = g->TopEdge+g->Height-1;

						printf("!(g->GadgetType & exclude):\n");
						
						printf("g->Flags== %04lx:\n",g->Flags);
						if(g->Flags & GRELWIDTH)
						{
							printf("(g->Flags & GRELWIDTH):\n");
							Bounds.MaxX = g->Width+window->Width;
						}
						else
						{
							printf("!(g->Flags & GRELWIDTH):\n");
							Bounds.MaxX = Bounds.MinX+g->Width-1;
						}
						if(g->Flags & GRELHEIGHT)
						{
							printf("(g->Flags & GRELHEIGHT):\n");
							Bounds.MaxY = g->Height+window->Height;
						}
						else
						{
							printf("!(g->Flags & GRELHEIGHT):\n");
							Bounds.MaxY = Bounds.MinY+g->Height-1;
						}
						printf("Bounds.MinX = %ld\n",Bounds.MinX);
						printf("Bounds.MinY = %ld\n",Bounds.MinY);
						printf("Bounds.MaxX = %ld\n",Bounds.MaxX);
						printf("Bounds.MaxY = %ld\n",Bounds.MaxY);
						if(g->Flags & GRELRIGHT)
						{
							printf("(g->Flags & GRELRIGHT):\n");
							Bounds.MinX += window->Width;
							Bounds.MaxX += window->Width;
						}
						if(g->Flags & GRELBOTTOM)
						{
							printf("(g->Flags & GRELBOTTOM):\n");
							Bounds.MinY += window->Height;
							Bounds.MaxY += window->Height;
						}

						if (!(g->GadgetType & GZZGADGET))
						{
							Bounds.MinX -= window->BorderRight+1;
							Bounds.MaxX -= window->BorderRight+1;
							Bounds.MinY -= window->BorderBottom
										 + window->BorderTop
										 + 1;
							Bounds.MaxY -= window->BorderBottom
										 + window->BorderTop
										 + 1;
						}

						printf("test inversion:\n");
						printf("Bounds.MinX = %ld\n",Bounds.MinX);
						printf("Bounds.MinY = %ld\n",Bounds.MinY);
						printf("Bounds.MaxX = %ld\n",Bounds.MaxX);
						printf("Bounds.MaxY = %ld\n",Bounds.MaxY);

						/* include only "positive" regions */
						if((Bounds.MinX < Bounds.MaxX)&&
						   (Bounds.MinY < Bounds.MaxY))
						{

							printf("xorrectregion:\n");
							printf("Bounds.MinX = %ld\n",Bounds.MinX);
							printf("Bounds.MinY = %ld\n",Bounds.MinY);
							printf("Bounds.MaxX = %ld\n",Bounds.MaxX);
							printf("Bounds.MaxY = %ld\n",Bounds.MaxY);
						   	XorRectRegion(clipregion,&Bounds);
						}
					}
				}
			}
		/* swap new one in */
		clipregion = InstallClipRegion(window->WLayer,clipregion);
		if (clipregion)
		{
			DisposeRegion(clipregion);
		}
	}
#endif
}

lbnc(w)
struct RastPort *w;
{
	register long i;
	short lx,ly,lvx,lvy;
	short rx,ry,rvx,rvy;
	short clrDepth,linDepth;
	struct Layer *l;
	int counter;
	int lcounter;
	int xoffset,yoffset;
	struct Window *window;
	struct IntuiMessage *message;

	close_count = MAX_CLOSEWINDOW;
	counter = 0;
	lcounter = 0;
	l = w->Layer;
	lx = 0;	ly = 0;
	rx = 30;	ry = 10;
	lvx = 2;	lvy = 3;
	rvx = 5;	rvy = 7;
	clrDepth = 320;
	linDepth = 160;
	SetDrMd(w,1);


	xoffset = Get_xoffset(w);
	yoffset = Get_yoffset(w);

#ifdef DEBUG
	printf("xoffset = %ld yoffset = %ld\n",xoffset,yoffset);
#endif
	if (l)	window = l->Window;

	clip_for_me(window);

restart:
	while ((message = (struct IntuiMessage *)GetMsg(window->UserPort)) == 0)
	{
		if (clrDepth-- == 0)
		{
			clrDepth = 320;
			SetAPen(w,w->FgPen+1);
		}

		if (linDepth-- == 0)
		{
			newvel(&lvx);
			newvel(&lvy);
			newvel(&rvx);
			newvel(&rvy);
			linDepth = 320;
		}

		Move(w,xoffset+lx,yoffset+ly);
		Draw(w,xoffset+rx,yoffset+ry);
		lx += lvx;	ly += lvy;
		rx += rvx;	ry += rvy;
		if (lx<0)	zbounce(&lx,&lvx);
		if (rx<0)	zbounce(&rx,&rvx);
		if (ly<0)	zbounce(&ly,&lvy);
		if (ry<0)	zbounce(&ry,&rvy);
		if (lx>RWidth-1)	mbounce(&lx,&lvx,RWidth-1);
		if (ly>RHeight-1) 	mbounce(&ly,&lvy,RHeight-1);
		if (rx>RWidth-1)	mbounce(&rx,&rvx,RWidth-1);
		if (ry>RHeight-1)	mbounce(&ry,&rvy,RHeight-1);
endit:
	}

	switch (message->Class)
	{

		case CLOSEWINDOW :
		{
			ReplyMsg(message);
			return;
		}

		case GADGETDOWN:
		{ 
			struct IntuiMessage copymsg;

			/* copy all fields */
			copymsg = *message;

			/* reply to original */
			ReplyMsg(message);

			/* smooth-scroll until gadget is released */
			{
				ULONG old_idcmp_flags;
				ULONG new_idcmp_flags;

				/* save old idcmp_flags */

				old_idcmp_flags = copymsg.IDCMPWindow->IDCMPFlags;

				/* listen for ticks as long as gadget is down */

				new_idcmp_flags = (old_idcmp_flags | INTUITICKS);

				ModifyIDCMP(copymsg.IDCMPWindow,new_idcmp_flags);

				/* loop for intuiticks messages */

				{
					struct IntuiMessage *loopmsg;

					while((loopmsg =  (struct IntuiMessage *) WaitPort(copymsg.IDCMPWindow->UserPort)) && (loopmsg->Class == INTUITICKS))
					{
						if(loopmsg = (struct IntuiMessage *)GetMsg(copymsg.IDCMPWindow->UserPort))
						{
							ReplyMsg(loopmsg);

							do_gadget_up(&copymsg);

							/* draw after smooth scrolling */
							{

								if (clrDepth-- == 0)
								{
									clrDepth = 320;
									SetAPen(w,w->FgPen+1);
								}

								if (linDepth-- == 0)
								{
									newvel(&lvx);
									newvel(&lvy); 
									newvel(&rvx);
									newvel(&rvy);
									linDepth = 320;
								}

								Move(w,xoffset+lx,yoffset+ly);
								Draw(w,xoffset+rx,yoffset+ry);
								lx += lvx;	ly += lvy;
								rx += rvx;	ry += rvy;
								if (lx<0)	zbounce(&lx,&lvx);
								if (rx<0)	zbounce(&rx,&rvx);
								if (ly<0)	zbounce(&ly,&lvy);
								if (ry<0)	zbounce(&ry,&rvy);
								if (lx>RWidth-1)	mbounce(&lx,&lvx,RWidth-1);
								if (ly>RHeight-1) 	mbounce(&ly,&lvy,RHeight-1);
								if (rx>RWidth-1)	mbounce(&rx,&rvx,RWidth-1);
								if (ry>RHeight-1)	mbounce(&ry,&rvy,RHeight-1);

							}
							/* done drawing */

						}

					}

					/* next message was not a tick */
				}

				/* restore old idcmp_flags */

				ModifyIDCMP(copymsg.IDCMPWindow,old_idcmp_flags);
		  }

		}
		break;

		case GADGETUP: 
		{
			struct IntuiMessage copymsg;

			/* copy all fields */
			copymsg = *message;

			/* reply to original */
			ReplyMsg(message);

			/* process message */
			do_gadget_up(&copymsg);
		}
		break;

		case SIZEVERIFY:
		{
			ReplyMsg(message);

			CopySBitMap(window->RPort->Layer);

			/* savesuperbitmap = window->RPort->Layer->SuperBitMap; */
			/* window->RPort->Layer->SuperBitMap = NULL; */

			/* wait for newsize */
			WaitPort(window->UserPort);
		}
		break;

		case NEWSIZE:
		{
			struct IntuiMessage copymsg;
			extern struct Gadget my_gadget;

			/* copy all fields */
			copymsg = *message;

			/* reply to original */
			ReplyMsg(message);

			/* window->RPort->Layer->SuperBitMap = savesuperbitmap; */
			/* savesuperbitmap = NULL; */
			clip_for_me(window);
			RefreshWindowFrame(window);

			/* provide vertical gadget address */
			copymsg.IAddress = vgadget_ptr;

			/* set vertical scroll */
			do_gadget_up(&copymsg);

			/* bart - 04.23.86 */
			/* re-calculate vertical pot body for new size */
			{
				struct Window *w; 
				struct RastPort *rp;
				struct Layer *l;

				if(w = copymsg.IDCMPWindow)
				{
					if(rp = w->RPort)
					{
						if(l = rp->Layer)
						{
							struct PropInfo *pi;
							UWORD sb_height;
							ULONG rel_body;
				 
							pi = (struct PropInfo *)vgadget_ptr->SpecialInfo;
												
							sb_height = l->SuperBitMap->Rows;

							rel_body=(MAXPOT*(usable_height(w)))/(sb_height);

							ModifyProp(vgadget_ptr,
									   window,
									   NULL,
									   pi->Flags,
									   pi->HorizPot,
									   pi->VertPot,
									   pi->HorizBody,
									   rel_body);
						}
					}
				}
			}

			/* provide vertical gadget address */
			copymsg.IAddress = hgadget_ptr;

			/* set horizontal scroll */
			do_gadget_up(&copymsg);

			/* bart - 04.23.86 */
			/* re-calculate horizontal pot body for new size */

			{
				struct Window *w; 
				struct RastPort *rp;
				struct Layer *l;

				if(w = copymsg.IDCMPWindow)
				{
					if(rp = w->RPort)
					{
						if(l = rp->Layer)
						{
							struct PropInfo *pi;
							UWORD bb_width;
							ULONG rel_body;
				 
							pi = (struct PropInfo *)hgadget_ptr->SpecialInfo;
													
							bb_width = l->SuperBitMap->BytesPerRow << 3;

							rel_body=(MAXPOT*(usable_width(w)))/(bb_width);

							ModifyProp(hgadget_ptr,
									   window,
									   NULL,
									   pi->Flags,
									   pi->HorizPot,
									   pi->VertPot,
									   rel_body,
									   pi->VertBody);
						}
					}
				}
			}

		}
		break;

		default:
		{
			ReplyMsg(message);
		}
		break;

	}

	goto restart;

}

newvel(v)
short *v;
{
	*v = (15 & rand(0)) - 7;
}

zbounce(p,v)
short *p,*v;
{
	*p = -*p;
	*v = -*v;
}

mbounce(p,v,c)
short *p,*v;
short c;
{
	*p = 2*c - *p;
	*v = -*v;
}

