/*
 * ping.c
 *
 * Yes, it's sloppy, but it works.
 *
 * By Chris Saulit,	28-Mar-87.
 *
 *	...!ihnp4!alberta!uqv-mts!saul
 *	CSAULIT@UALTAVM.BITNET
 *	73007,3267 (CIS)
 *
 */

#include <intuition/intuition.h>
#include <devices/input.h>

#define ESC	27

extern SHORT rnd();

struct Window *w=NULL, *OpenWindow();
struct Screen *s;

#define FLAGS ACTIVATE|WINDOWDEPTH|WINDOWCLOSE|WINDOWDRAG|SIMPLE_REFRESH

struct NewWindow nw = {
	200,12,200,10,			/* origin, dimensions */
	-1,-1,				/* pens */
	CLOSEWINDOW | VANILLAKEY,	/* IDCMP flags */
	FLAGS,				/* Flags */
	NULL, NULL,			/* FirstGadget, CheckMark */
	"\253< Ping! >\273",		/* Title */
	NULL, NULL,			/* Screen, BitMap */
	0,0,0,0,			/* Min and Max dimensions */
	WBENCHSCREEN			/* Type */
};

ULONG	IntuitionBase, OpenLibrary();
struct	MsgPort		*ioPort, *CreatePort();
struct	IOStdReq	*ioReq,  *CreateStdIO();
struct	InputEvent	fake;

_main()
{
   initstuff();
   bounce();
   cleanexit(0);
}


initstuff()
{
   if ( ! (IntuitionBase = OpenLibrary("intuition.library",0L)) )
      cleanexit("No intuition?");

   if ( ! (ioPort = CreatePort("ping",NULL)) )
      cleanexit("Can't create port.");

   if ( ! (ioReq = CreateStdIO(ioPort)) )
      cleanexit("Can't create I/O req");

   if ( OpenDevice("input.device",0,ioReq,0) )
      cleanexit("Can't open input.device");

   ioReq->io_Command	= IND_WRITEEVENT;
   ioReq->io_Flags	= 0;
   ioReq->io_Length	= sizeof(struct InputEvent);
   ioReq->io_Data	= (APTR) &fake;

   fake.ie_NextEvent		= NULL;
   fake.ie_Class		= IECLASS_RAWMOUSE;
   fake.ie_TimeStamp.tv_secs	= 0;
   fake.ie_TimeStamp.tv_micro	= 0;
   fake.ie_Code			= IECODE_NOBUTTON;
   fake.ie_Qualifier		= IEQUALIFIER_RELATIVEMOUSE;

   if ( ! (w = OpenWindow(&nw)) )
      cleanexit("Can't open window.");

   s = w->WScreen;

   rnd( - s->MouseX );		/* plant a seed */
}


/* grav acceleration */
#define	Y_ACC	1
/* size of pointer */
#define PTR_H	11
#define PTR_W	11

bounce()
{
   ULONG class;
   USHORT code;
   struct IntuiMessage *iMsg;

   SHORT y_vel = 0,		/* start at rest */
         x_vel = 0;

   for (;;) {
      fake.ie_Y = y_vel;		/* relative motion */
      fake.ie_X = x_vel;
      DoIO(ioReq);
      Delay(1);
      if (iMsg = (struct IntuiMessage *) GetMsg(w->UserPort)) {
         class = iMsg->Class;
	 code = iMsg->Code;
         ReplyMsg(iMsg);
         if (class == CLOSEWINDOW  ||  class==VANILLAKEY && code==ESC)
            return;
      }

      y_vel += Y_ACC;		 /* increase downward velocity */

      if (s->MouseY >= s->Height-PTR_H) {	/* hit bottom */
	 x_vel += (rnd(9) - 4);
         y_vel = -y_vel + (rnd(7) - 3) ;
	 y_vel += Y_ACC;
      }
      else if (s->MouseY <= 0) {	/* hit top */
         y_vel = Y_ACC;
      }
      if (s->MouseX >= s->Width - PTR_W   ||   s->MouseX <= 0) {
         x_vel = -x_vel;
      }
   }
}


cleanexit(msg)
   char *msg;
{
   if (ioReq)
      if (ioReq->io_Device)
	 CloseDevice(ioReq);
      DeleteStdIO(ioReq);

   if (ioPort)
      DeletePort(ioPort);

   if (w)		CloseWindow(w);
   if (IntuitionBase)	CloseLibrary(IntuitionBase);

   _exit(0);
}
