/*	Original mouse.c v1.0 by Chris Ludwig
$VER rxpointer v1.1 Geoff Fellows 1-Nov-1994
*/

#include "rxpointer.h"
#include "simplerexx.h"

/* input.device stuff */
struct RXPointerContext {
	AREXXCONTEXT RexxStuff;
	BYTE inputopenerror;
	struct InputEvent phony;
	struct MsgPort *inputdevport;
	struct IOStdReq *inputrequest;
};

void Quit(struct RXPointerContext *rxpc, char whytext[],UBYTE level);
void ClickButton(struct RXPointerContext *rxpc, UWORD code);
void MovePointer(struct RXPointerContext *rxpc, LONG mousex, LONG mousey);

void Quit(struct RXPointerContext *rxpc, char whytext[],UBYTE level) {
	if (!rxpc->inputopenerror)
		CloseDevice((struct IORequest *) rxpc->inputrequest);

	if (rxpc->inputrequest) DeleteStdIO(rxpc->inputrequest);

	if (rxpc->inputdevport) DeletePort(rxpc->inputdevport);

	FreeARexx(rxpc->RexxStuff);

	printf("%s\n",whytext);
	exit(level);
}

void ClickButton(struct RXPointerContext *rxpc, UWORD code) {

	rxpc->phony.ie_NextEvent = NULL;
	rxpc->phony.ie_Class = IECLASS_RAWMOUSE;
	rxpc->phony.ie_TimeStamp.tv_secs = 0;
	rxpc->phony.ie_TimeStamp.tv_micro = 0;
	rxpc->phony.ie_Code = code;					/* button down */
	rxpc->phony.ie_Qualifier = 0;
	rxpc->phony.ie_X = 0;
	rxpc->phony.ie_Y = 0;

	rxpc->inputrequest -> io_Command = IND_WRITEEVENT;
	rxpc->inputrequest -> io_Flags = 0;
	rxpc->inputrequest -> io_Length = sizeof(struct InputEvent);
	rxpc->inputrequest -> io_Data = (APTR)&rxpc->phony;

	DoIO(rxpc->inputrequest);

	rxpc->phony.ie_NextEvent = NULL;
	rxpc->phony.ie_Class = IECLASS_RAWMOUSE;
	rxpc->phony.ie_TimeStamp.tv_secs = 0;
	rxpc->phony.ie_TimeStamp.tv_micro = 0;
	rxpc->phony.ie_Code = code | IECODE_UP_PREFIX;	/* button up */
	rxpc->phony.ie_Qualifier = 0;
	rxpc->phony.ie_X = 0;
	rxpc->phony.ie_Y = 0;

	rxpc->inputrequest -> io_Command = IND_WRITEEVENT;
	rxpc->inputrequest -> io_Flags = 0;
	rxpc->inputrequest -> io_Length = sizeof(struct InputEvent);
	rxpc->inputrequest -> io_Data = (APTR)&rxpc->phony;

	DoIO(rxpc->inputrequest);
}


void MovePointer(struct RXPointerContext *rxpc, LONG mousex, LONG mousey) {
	/* send phony pointer message to input stream */

	rxpc->phony.ie_NextEvent = NULL;
	rxpc->phony.ie_Class = IECLASS_POINTERPOS;
	rxpc->phony.ie_TimeStamp.tv_secs = 0;
	rxpc->phony.ie_TimeStamp.tv_micro = 0;
	rxpc->phony.ie_Code = 0;
	rxpc->phony.ie_Qualifier = 0;
	rxpc->phony.ie_X = mousex;
	rxpc->phony.ie_Y = mousey;

	rxpc->inputrequest -> io_Command = IND_WRITEEVENT;
	rxpc->inputrequest -> io_Flags = 0;
	rxpc->inputrequest -> io_Length = sizeof(struct InputEvent);
	rxpc->inputrequest -> io_Data = (APTR)&rxpc->phony;

	DoIO(rxpc->inputrequest);
}


/*
 * A *VERY* simple and simple-minded example of using the SimpleRexx.c code.
 *
 * Note: You will want to RUN this program or have another shell
 *  available such that you can still have access to ARexx...
 */
void main(int argc, char *argv[]) {
	struct Library *RexxSysBase;
	short	loopflag=TRUE;
	struct RXPointerContext rxpc;

	int x, y, length;

	RexxSysBase = OpenLibrary(RXSNAME, 0);

	if ((rxpc.inputdevport=CreatePort(0,0)) == NULL)
		Quit(&rxpc, "Couldn't create a port for input.device",25);

	if ((rxpc.inputrequest=CreateStdIO(rxpc.inputdevport)) == NULL)
		Quit(&rxpc, "Couldn't create request block for input device",25);

	if ((rxpc.inputopenerror
		=OpenDevice("input.device",0,rxpc.inputrequest,0)) != 0)
		Quit(&rxpc, "Couldn't open input.device",25);

	/*
	 * Note that SimpleRexx is set up such that you do not
	 * need to check for an error to initialize your REXX port
	 * This is so your application could run without REXX...
	 */
	rxpc.RexxStuff=InitARexx("pointer","pointer");

	if (argc) {
		if (rxpc.RexxStuff)
			printf("Send commands to port %s\n",ARexxName(rxpc.RexxStuff));
		else
			printf("ARexx is not available\n");
	}

	while (loopflag) {
		ULONG signals=ARexxSignal(rxpc.RexxStuff);

		if (signals) {
			struct	RexxMsg		*rmsg;

			signals=Wait(signals);

			/*
			 * Process the ARexx messages...
			 */
			while (rmsg=GetARexxMsg(rxpc.RexxStuff)) {
			char	cBuf[24];
			char	*nextchar;
			char	*error=NULL;
			char	*result=NULL;
			long	errlevel=0;

				nextchar=stptok(ARG0(rmsg),cBuf,24," ,");
				if (*nextchar) nextchar++;

				if (!stricmp("CLICK",cBuf)) {
					nextchar=stptok(nextchar,cBuf,24," ,");
					if (*nextchar) nextchar++;

					if (!stricmp("LEFT",cBuf)) {
						ClickButton(&rxpc, IECODE_LBUTTON);
					}
					else if (!stricmp("MIDDLE",cBuf)) {
						ClickButton(&rxpc, IECODE_MBUTTON);
					}
					else if (!stricmp("RIGHT",cBuf)) {
						ClickButton(&rxpc, IECODE_RBUTTON);
					}
					else {
						/* Default to left button */
						ClickButton(&rxpc, IECODE_LBUTTON);
					}
				}
				else if (!stricmp("MOVE",cBuf)) {
					nextchar=stptok(nextchar,cBuf,24," ,");
					if (*nextchar) nextchar++;

					length=stcd_i(cBuf,&x);

					nextchar=stptok(nextchar,cBuf,24," ,");
					if (*nextchar) nextchar++;

					length=stcd_i(cBuf,&y);

					MovePointer(&rxpc, (LONG) x,(LONG) y);
				}
				else if (!stricmp("VERSION",cBuf)) {
					result="mouse v1.0";
				}
				else if (!stricmp("QUIT",cBuf)) {
					loopflag=FALSE;
				}
				else {
					error="Unknown command";
					errlevel=20;
				}

				if (error) {
					SetARexxLastError(rxpc.RexxStuff,rmsg,error);
				}
				ReplyARexxMsg(rxpc.RexxStuff,rmsg,result,errlevel);
			}

		}
		else loopflag=FALSE;
	}
	Quit(&rxpc, "QUIT command received.\n",0);
}
