/*  This software is distributed under GPL license - see gpl.txt
    This is a part of WheelBusMouse and ps2m packages,
    you can obtain latest versions at Aminet:

ftp://ftp.wustl.edu/pub/aminet/util/mouse/WheelBusMouse.lha
ftp://ftp.wustl.edu/pub/aminet/util/mouse/WheelBusMouse.readme

ftp://ftp.wustl.edu/pub/aminet/hard/hack/ps2m.lha
ftp://ftp.wustl.edu/pub/aminet/hard/hack/ps2m.readme

For any questions: rdc@mindless.com

Don't forget to disable startup code! */

#include <exec/memory.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <dos/dostags.h>

#include <devices/input.h>
#include <devices/inputevent.h>
#include "newmouse.h"

struct Library *DOSBase, *SysBase, *GfxBase;
struct IOStdReq *req;
struct InputEvent FakeEvent;

ULONG code;

#define COORD *((STRPTR)0xdff00c)
#define TEMPLATE "REVERSE/S,PRIORITY/N,QUIET/S"

struct {
	ULONG reverse;
	ULONG *pri;
	ULONG quiet;
} arg = { 0, 0, 0 };

void event(LONG);
void process(void);

__saveds main()
{
	SysBase = *((struct Library **)4L);
	if(DOSBase = OpenLibrary("dos.library",0))
	{
		if(GfxBase = OpenLibrary("graphics.library",36))
		{
			struct RDArgs *rda;
			if(rda = ReadArgs(TEMPLATE,(LONG *)&arg,NULL))
			{
				if(!arg.quiet)
				{
					Printf("%s  © Russian Digital Computing\n",6+"$VER: WheelBusMouse 1.1 "__AMIGADATE__);
				}
				if(FindTask("WheelBusMouse"))
				{
					Printf("%s already installed!\n","WheelBusMouse");
				}
				else
				{
					if(CreateNewProcTags(NP_Entry,process,NP_Name,"WheelBusMouse",NP_Priority,arg.pri?*arg.pri:0,NULL))
					{
						((struct CommandLineInterface *)((((struct Process *)FindTask(NULL))->pr_CLI)<<2))->cli_Module = NULL;
						return(0);
					}
					if(!arg.quiet)
					{
						Printf("Can't create daughter process\n");
					}
				}
				CloseLibrary(GfxBase);
			}
		}
		else
		{
			Write(Output(),"OS 2.0+ required\n",17);
		}
		CloseLibrary(DOSBase);
	}
	return(20);
}

void __saveds process(void)
{
	struct MsgPort *replyport;
	if(replyport = CreateMsgPort())
	{
		if(req = CreateIORequest(replyport,sizeof(struct IOStdReq)))
		{
			if(!OpenDevice("input.device",NULL,(struct IORequest *)req,NULL))
			{
				BYTE CurrByte, LastByte = COORD;
				LONG diff;
				while(!CheckSignal(0xf000))
				{
					WaitTOF();
					CurrByte = COORD;
					diff = (BYTE)(CurrByte - LastByte);
					if(arg.reverse)
					{
						diff = -diff;
					}
					if(diff)
					{
						code = NM_WHEEL_UP;
						if(diff<0)
						{
							code = NM_WHEEL_DOWN;
							diff = -diff;
						}
						while(diff--)
						{
							event(IECLASS_RAWKEY);
							event(IECLASS_NEWMOUSE);
						}
						LastByte=CurrByte;
					}
				}
				CloseDevice((struct IORequest *)req);
			}
			DeleteIORequest(req);
		}
		DeleteMsgPort(replyport);
	}
	CloseLibrary(GfxBase);
	CloseLibrary(DOSBase);
}

void event(LONG class)
{
	FakeEvent.ie_NextEvent = NULL;
	FakeEvent.ie_Class = class;
	FakeEvent.ie_Code = code;
	FakeEvent.ie_Qualifier = NULL;
	req->io_Data = (APTR)&FakeEvent;
	req->io_Length = sizeof(struct InputEvent);
	req->io_Command = IND_WRITEEVENT;
	DoIO((struct IORequest *)req);
}
