/* cancel.c */

/*		Copyright © 1989 by Donald T. Meyer, Stormgate Software
 *		All Rights Reserved
 */



#include "rxil.h"

#include <exec/memory.h>

#include <proto/intuition.h>




#define REQ_LEFT		  3
#define REQ_TOP			 11
#define REQ_WIDTH		180
#define REQ_HEIGHT		 50

#define GADGET_LEFT		20
#define GADGET_TOP		8
#define GADGET_WIDTH	REQ_WIDTH - 40
#define GADGET_HEIGHT	REQ_HEIGHT - 16



static struct IntuiText itext[2] = {
	{ 1, 0, JAM1, 12, 10, NULL, (UBYTE *)"Click Here To", &itext[1] },
	{ 1, 0, JAM1, 16, 20, NULL, (UBYTE *)"Cancel Macro", NULL },
};



static SHORT vectors[4][10] = {
	{
	0, 0,   REQ_WIDTH-1, 0,   REQ_WIDTH-1, REQ_HEIGHT-1,
	0, REQ_HEIGHT-1,   0, 0
	},
	{
	0, 0,   REQ_WIDTH-9, 0,   REQ_WIDTH-9, REQ_HEIGHT-7,
	0, REQ_HEIGHT-7,   0, 0
	},
	{
	0, 0,   GADGET_WIDTH-1, 0,   GADGET_WIDTH-1, GADGET_HEIGHT-1,
	0, GADGET_HEIGHT-1,   0, 0
	},
	{
	0, 0,   GADGET_WIDTH-9, 0,   GADGET_WIDTH-9, GADGET_HEIGHT-7,
	0, GADGET_HEIGHT-7,   0, 0
	}
};


static struct Border border[4] = {
	{
	0, 0, 1, 0, JAM1, 5, (SHORT *)&vectors[0][0], &border[1]
	},
	{
	4, 3, 1, 0, JAM1, 5, (SHORT *)&vectors[1][0], NULL
	},
	{
	0, 0, 3, 0, JAM1, 5, (SHORT *)&vectors[2][0], &border[3]
	},
	{
	4, 3, 3, 0, JAM1, 5, (SHORT *)&vectors[3][0], NULL
	}
};


static struct Gadget gadget = {
	NULL,					/* NextGadget */
	GADGET_LEFT, GADGET_TOP,	/* LeftEdge, TopEdge */
	GADGET_WIDTH,			/* Width */
	GADGET_HEIGHT,			/* Height */
	GADGHCOMP,				/* Flags */
/*	ENDGADGET | */
	RELVERIFY,				/* Activation */
	REQGADGET |
	BOOLGADGET,				/* GadgetType */
	(APTR)&border[2],		/* GadgetRender */
	NULL,					/* SelectRender */
	&itext[0],				/* GadgetText */
	NULL,					/* MutualExclude */
	NULL,					/* SpecialInfo */
	0,						/* GadgetID */
	NULL					/* UserData */
};


static struct NewWindow newwin_template = {
	20, 14,						/* LeftEdge, TopEdge */
	REQ_WIDTH + 6,				/* Width */
	REQ_HEIGHT + 14,			/* Height */
	0, 1,						/* DetailPen, BlockPen */
	GADGETUP,					/* IDCMP Flags */
	WINDOWDEPTH |
	WINDOWDRAG |
	SMART_REFRESH |
	NOCAREREFRESH,				/* Flags */
	NULL,						/* FirstGadget */
	NULL,						/* CheckMark */
	(UBYTE *)"ARexx Macro",		/* Title */
	NULL,						/* Screen */
	NULL,						/* BitMap */
	0, 0,						/* MinWidth, MinHeight */
	0, 0,						/* MaxWidth, MaxHeight */
	WBENCHSCREEN				/* Type */
};


static struct Requester req_template = {
	NULL,					/* OlderRequester */
	REQ_LEFT, REQ_TOP,		/* LeftEdge, TopEdge */
	REQ_WIDTH, REQ_HEIGHT,	/* Width, Height */
	0, 0,					/* RelLeft, RelTop */
	&gadget,				/* ReqGadget */
	&border[0],				/* ReqBorder */
	NULL,					/* ReqText */
	NULL,					/* Flags */
	2,						/* BackFill */
	NULL,					/* ReqLayer */
	{NULL},					/* Pad */
	{NULL},					/* BitMap */
	NULL,					/* RWindow */
	{NULL},					/* Pad */
};




/* NAME
 *		RxilCancel
 *
 * SYNOPSIS
 *		RxilCancel();
 *
 * FUNCTION
 *		Sets the abort condition for ARexx macros.  This is accomplished
 *		by setting the Abort flag in the RxilDef structure.
 *		All ARexx messages received at the ARexx ports while this flag
 *		is set will be returned with an error code.
 *		Unless the RXIL_NO_CLEAR_ABORT flag is set, the Abort flag will
 *		be cleared automaticly when the last ARexx program launched by
 *		this application has finished.
 *
 *
 * INPUTS
 *		None
 *
 * RESULT
 *		None
 *
 * SIDES
 *
 * HISTORY
 *		01-Aug-89	Creation.
 *		18-Nov-89	Fixed bug whereby cancel requesters would post
 *					more than once.
 *
 * BUGS
 *
 * SEE ALSO
 *
 */

void RxilCancel( void )
{
	/* Make call "safe" even if RxilInit() failed */
	if( global_rdef != NULL )
	{
		global_rdef->Abort = TRUE;
	}
}



/* NAME
 *		RxilCheckCancel
 *
 * SYNOPSIS
 *		flag = RxilCheckCancel();
 *
 *		BOOL flag;
 *
 * FUNCTION
 *		Checks to see if the button on the cancel macro requester has
 *		been clicked by the user or not.
 *		This will return FALSE if the cancel requester is not posted. 
 *
 * INPUTS
 *		None
 *
 * RESULT
 *		A boolean TRUE if the cancel requester has been clicked.
 *
 * SIDES
 *
 * HISTORY
 *		01-Aug-89	Creation.
 *
 * BUGS
 *
 * SEE ALSO
 *		RxilPostCancel(), RxilEndCancel()
 */

BOOL RxilCheckCancel( void )
{
	struct IntuiMessage *message;
	ULONG class;
	struct RxilCancelReq *creq;


	if( global_rdef == NULL )
	{
		return( FALSE );
	}

	creq = global_rdef->CReq;

	if( creq == NULL )
	{
		return( FALSE );
	}


	/* See if user clicked the CANCEL gadget */

	message = (struct IntuiMessage *)GetMsg( creq->win->UserPort );
	if( message )
	{
		class = message->Class;

		ReplyMsg( (struct Message *)message );

		if( class == GADGETUP )
		{
			RxilEndCancel();
			return( TRUE );
		}
	}

	return( FALSE );
}



/* NAME
 *		RxilPostCancel
 *
 * SYNOPSIS
 *		RxilPostCancel();
 *
 * FUNCTION
 *		This will post a cancel requester to allow the user to halt
 *		macro execution by clicking a button on the requester.
 *		The CancelWindow member of the RxilDef structure controls
 *		where the requester is posted.
 *		In the current version, the cancel requester always opens it's
 *		own window on the same screen as the Window whose pointer is
 *		in CancelWindow.  If CancelWindow is NULL, the window will open
 *		on the WorkBench.
 *
 * INPUTS
 *		None
 *
 * RESULT
 *		None
 *
 * SIDES
 *
 * HISTORY
 *		01-Aug-89	Creation.
 *
 * BUGS
 *
 * SEE ALSO
 *		RxilCheckCancel(), RxilEndCancel()
 */

void RxilPostCancel( void )
{
	struct RxilCancelReq *creq;
	struct NewWindow *newwin;


	if( global_rdef == NULL )
	{
		return;
	}

	/* On the off-chance that Intuition is not open... */
	if(  IntuitionBase == NULL  )
	{
		return;
	}

	if( global_rdef->CReq != NULL )
	{
		/* Already a cancel requester posted.  Don't post another one!
		 */
		return;
	}


	creq = AllocMem( sizeof(struct RxilCancelReq),
		MEMF_PUBLIC | MEMF_CLEAR );
	if( creq == NULL )
	{
		return;
	}


	/* Open our window */

	newwin = AllocMem( sizeof(struct NewWindow),
		MEMF_PUBLIC | MEMF_CLEAR );
	if( newwin == NULL )
	{
		FreeMem( creq, sizeof(struct RxilCancelReq) );
		return;
	}

	CopyMem( (char *)&newwin_template, (char *)newwin,
		sizeof(struct NewWindow) );

	if( global_rdef->CancelWindow != NULL )
	{
		/* Client has set a window for us to (currently) derive the
		 * screen from.
		 */
		if( global_rdef->CancelWindow->WScreen != NULL )
		{
			/* And it's not the WorkBench (which is our default), so
			 * set things up to open our window on that screen.
			 */
			newwin->Screen = global_rdef->CancelWindow->WScreen;
			newwin->Type = CUSTOMSCREEN;
		}
	}

	creq->win = OpenWindow( newwin );

	FreeMem( newwin, sizeof(struct NewWindow) );

	if( creq->win == NULL )
	{
		FreeMem( creq, sizeof(struct RxilCancelReq) );
		return;
	}


	CopyMem( (char *)&req_template, (char *)&creq->req,
		sizeof(struct Requester) );

	if(  Request( &creq->req, creq->win ) == FALSE  )
	{
		/* Unable to post the requester for some reason */
		CloseWindow( creq->win );
		FreeMem( creq, sizeof(struct RxilCancelReq) );
		return;
	}


	global_rdef->CReq = creq;

	return;
}



/* NAME
 *		RxilEndCancel
 *
 * SYNOPSIS
 *		RxilEndCancel();
 *
 * FUNCTION
 *		Removes the cancel requester.
 *
 * INPUTS
 *		None
 *
 * RESULT
 *		None
 *
 * SIDES
 *
 * HISTORY
 *		01-Aug-89	Creation.
 *
 * BUGS
 *
 * SEE ALSO
 *		RxilPostCancel(), RxilCheckCancel()
 */

void RxilEndCancel( void )
{
	struct RxilCancelReq *creq;


	if( global_rdef == NULL )
	{
		return;
	}

	creq = global_rdef->CReq;

	if( creq == NULL )
	{
		return;
	}

	EndRequest( &creq->req, creq->win );

	CloseWindow( creq->win ); 

	FreeMem( creq, sizeof(struct RxilCancelReq) );

	global_rdef->CReq = NULL;
}

