/*
 *	SetMouse.c - Copyright © 1990 by S.R. & P.C.
 *
 *	Created:	27 Oct 1991  18:04:16
 *	Modified:	18 Jan 1992  19:31:40
 *
 *	Make>> make
 */

#include "ParMBase.h"

extern struct ExecBase *SysBase;

struct ParMBase *ParMBase;
struct ArpBase *ArpBase;
struct ReqLib *ReqBase;
struct IconBase *IconBase;
struct IntuitionBase *IntuitionBase;
struct LayersBase *LayersBase;
struct GfxBase *GfxBase;
struct WBStartup *WBenchMsg;
int _argc;
char **_argv;
struct GetLongStruct GLS = {NULL, 0, 0, 0, 0, NULL, REQVERSION - 1, 0, 0};
char ReqTitle[] = "SetMouse";
char HelpUsage[] = "[32mSetMouse[31m V1.1 © 1991 by [33mS.R. & P.C.[31m\n";
char Template[] = "Nothing";

long DosWrite(BPTR file, char *buffer, long length);

#pragma amicall(DOSBase, 0x30, DosWrite(d1,d2,d3))

static struct IntuiText IText10 =
{
	1, 1, JAM1,		/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "SaveOpt",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem10 =
{
	NULL,			/* next MenuItem structure */
	0, 56,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText10,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText9 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "Handler Pri",/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem9 =
{
	&MenuItem10,		/* next MenuItem structure */
	0, 48,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText9,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText8 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "ScreenBlank",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem8 =
{
	&MenuItem9,		/* next MenuItem structure */
	0, 40,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText8,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText7 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "MouseBlank",/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem7 =
{
	&MenuItem8,		/* next MenuItem structure */
	0, 32,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText7,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText6 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "Threshold",/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem6 =
{
	&MenuItem7,		/* next MenuItem structure */
	0, 32,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText6,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText5 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "Acceleration",/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem5 =
{
	&MenuItem6,		/* next MenuItem structure */
	0, 32,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText5,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText4 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	19, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "SunMouse",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem4 =
{
	&MenuItem5,		/* next MenuItem structure */
	0, 24,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	CHECKIT + ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText4,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText3 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	19, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "ScreenToBack",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem3 =
{
	&MenuItem4,		/* next MenuItem structure */
	0, 16,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	CHECKIT + ITEMTEXT + MENUTOGGLE + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText3,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText2 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	19, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "WindowToBack",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem2 =
{
	&MenuItem3,		/* next MenuItem structure */
	0, 8,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	CHECKIT + ITEMTEXT + MENUTOGGLE + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText2,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText1 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	19, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "WindowToFront",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem1 =
{
	&MenuItem2,		/* next MenuItem structure */
	0, 0,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	CHECKIT + ITEMTEXT + MENUTOGGLE + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText1,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText01 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "WinToFront Qual",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem01 =
{
	&MenuItem1,		/* next MenuItem structure */
	0, 24,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	123, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText01,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct Menu Menu2 =
{
	NULL,			/* next Menu structure */
	54, 0,			/* XY origin of Menu hit box relative to screen TopLeft */
	71, 0,			/* Menu hit box width and height */
	MENUENABLED,		/* Menu flags */
	"SetMouse",		/* text of Menu name */
	&MenuItem01		/* MenuItem linked list pointer */
};

static struct IntuiText ITextQ =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "Quit",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItemQ =
{
	NULL,			/* next MenuItem structure */
	0, 0,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	64, 8,			/* hit box width and height */
	ITEMTEXT+ITEMENABLED+HIGHCOMP+COMMSEQ,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & ITextQ,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	'Q',			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct IntuiText IText0 =
{
	3, 1, COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
	2, 1,			/* XY origin relative to container TopLeft */
	NULL,			/* font pointer or NULL for default */
	(UBYTE *) "About...",	/* pointer to text */
	NULL			/* next IntuiText structure */
};

static struct MenuItem MenuItem0 =
{
	&MenuItemQ,			/* next MenuItem structure */
	0, 0,			/* XY of Item hitbox relative to TopLeft of parent hitbox */
	64, 8,			/* hit box width and height */
	ITEMTEXT + ITEMENABLED + HIGHCOMP,	/* Item flags */
	0,			/* each bit mutually-excludes a same-level Item */
	(APTR) & IText0,	/* Item render  (IntuiText or Image or NULL) */
	NULL,			/* Select render */
	NULL,			/* alternate command-key */
	NULL,			/* SubItem list */
	MENUNULL		/* filled in by Intuition for drag selections */
};

static struct Menu Menu1 =
{
	&Menu2,			/* next Menu structure */
	0, 0,			/* XY origin of Menu hit box relative to screen TopLeft */
	47, 0,			/* Menu hit box width and height */
	MENUENABLED,		/* Menu flags */
	"About",		/* text of Menu name */
	&MenuItem0		/* MenuItem linked list pointer */
};


static struct NewWindow NWS = {
	0, 0,		/* window XY origin relative to TopLeft of screen */
	191, 10,		/* window width and height */
	1, 0,			/* detail and block pens */
	MENUPICK | CLOSEWINDOW,	/* IDCMP flags */
	WINDOWDRAG + WINDOWDEPTH + WINDOWCLOSE + ACTIVATE + NOCAREREFRESH,	/* other window flags */
	NULL,			/* first gadget in gadget list */
	NULL,			/* custom CHECKMARK imagery */
	(UBYTE *) "SetMouse V1.1",	/* window title */
	NULL,			/* custom screen pointer */
	NULL,			/* custom bitmap */
	5, 5,			/* minimum width and height */
	-1, -1,			/* maximum width and height */
	WBENCHSCREEN		/* destination screen type */
};


int main(int argc, char **argv);

void exit(int code)
{
	if (WBenchMsg) {
		Forbid();
		ReplyMsg((struct Message *) WBenchMsg);
	}
	CloseLibrary(ParMBase);
	Exit(code);
}

void _main(long alen, char *aptr)
{
	struct Library *DOSBase;
	struct Process *pp;

	pp = (struct Process *) SysBase->ThisTask;
	if (!pp->pr_CLI) {
		WaitPort(&pp->pr_MsgPort);
		WBenchMsg = (struct WBStartup *) GetMsg(&pp->pr_MsgPort);
	}
	if (!(ParMBase = (struct ParMBase *) OpenLibrary("parm.library", 4L))) {
		if (pp->pr_CLI && (DOSBase = OpenLibrary("dos.library", 0L))) {
			DosWrite(pp->pr_COS, "You need parm.library V4+\n", 26L);
			CloseLibrary(DOSBase);
		}
		if (WBenchMsg) {
			Forbid();
			ReplyMsg((struct Message *) WBenchMsg);
		}
		return;
	}
	ArpBase = ParMBase->ArpBase;
	ReqBase = ParMBase->ReqBase;
	IconBase = ParMBase->IconBase;
	LayersBase = ParMBase->LayersBase;
	IntuitionBase = (struct IntuitionBase *) ArpBase->IntuiBase;
	GfxBase = (struct GfxBase *) ArpBase->GfxBase;

	if (WBenchMsg) {
		CurrentDir(WBenchMsg->sm_ArgList->wa_Lock);
		_argv = (char **) WBenchMsg;
	}
	else {
		/*
		 *	WARNING: With that function, argv[] array will not start with the program
		 *	name but with it's first argument. If there's no args, argc will be zero.
		 */
		_argv = ArpAlloc(sizeof(APTR) * 18);
		_argc = (int) GADS(aptr, alen, HelpUsage, _argv, Template);
		if (_argc < 0) {
			Puts(_argv[0]);
			exit(20);
		}
	}
	exit(main(_argc, _argv));
}


void SaveMouseOpt(struct MouseOpt *MouseOpt)
{
	BPTR fh;

	if (fh = Open(DEFAULT_MOUSEOPT_FILE, MODE_NEWFILE)) {
		Write(fh, (char *) MouseOpt, sizeof(struct MouseOpt));
		Close(fh);
	}
	else
		SimpleRequest(ReqTitle, "Couldn't save configuration.");
}


BOOL GetNumber(char *Title, long DefaultVal, long Min, long Max)
{
	GLS.titlebar = Title;
	GLS.defaultval = DefaultVal;
	GLS.minlimit = Min;
	GLS.maxlimit = Max;
	return GetLong(&GLS);
}


int main(int argc, char **argv)
{
	struct Window *Window;
	struct IntuiMessage *IMsg;
	struct MouseOpt MouseOpt;
	/* allocate some stack space to prevent crashes if incompatible version
	 * of setmouse with current library */
	char DummyBuffer[40];
	struct TextAttr ScreenTextAttr;
	BOOL DoNextSelect, Quit = FALSE;
	ULONG Class;
	USHORT Code;

	GetCurrentMouseOpt(&MouseOpt);
	if (MouseOpt.Version != MOUSEOPT_VERSION) {
		SimpleRequest(ReqTitle, "Invalid Mouse Opts version.");
		return 20;
	}
	NWS.Height = OpenWorkBench()->BarHeight + (IntuitionBase->LibNode.lib_Version >= 36);
/*	Center(&NWS, 0, 0); */
	if (Window = OpenWindow(&NWS)) {
		AskFont(&Window->WScreen->RastPort, &ScreenTextAttr);
		NewCleanUp(&Menu1, &ScreenTextAttr, 0);
		SetMenuStrip(Window, &Menu1);

		/* Set the CheckMark acording current MouseOpt */
		if (MouseOpt.NClick)
			MenuItem1.Flags |= CHECKED;
		if (MouseOpt.Flags & MO_WINDOWTOBACK)
			MenuItem2.Flags |= CHECKED;
		if (MouseOpt.Flags & MO_SCREENTOBACK)
			MenuItem3.Flags |= CHECKED;
		if (MouseOpt.SunMouse >= 0)
			MenuItem4.Flags |= CHECKED;

		while (!Quit) {
			WaitPort(Window->UserPort);
			while (IMsg = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
				Class = IMsg->Class;
				Code = IMsg->Code;
				ReplyMsg((struct Message *)IMsg);
				switch (Class) {
				case CLOSEWINDOW:
					Quit = TRUE;
					break;
				case MENUPICK:
					DoNextSelect = TRUE;
					if (Code != MENUNULL) {
						do {
							switch (MENUNUM(Code)) {
							case 0:
								if (ITEMNUM(Code) == 0)
									SimpleRequest(ReqTitle, "ParM and BrowserII are\nCopyRight S.R. & P.C.\nand     ShareWare\nIf you use them, please send $20US to:\nSylvain Rougier\n39 rue carnot\n86000 Poitiers\nFrance.");
								else {
									Quit = TRUE;
									DoNextSelect = FALSE;
								}
								break;
							case 1:
								switch (ITEMNUM(Code)) {
								case 0:	/* Win To Front Qualifier */
									if (GetNumber("WToFront Qualifier", (long)(MouseOpt.WTFQual & ~(IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RELATIVEMOUSE)), 0, 32767))
										 MouseOpt.WTFQual = (USHORT)GLS.result | (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RELATIVEMOUSE);
								case 1:	/* WindowToFront */
									MouseOpt.NClick = (MenuItem1.Flags & CHECKED) ? 2 : 0;
									break;
								case 2:	/* WindowToBack() */
									if (MenuItem2.Flags & CHECKED)
										MouseOpt.Flags |= MO_WINDOWTOBACK;
									else
										MouseOpt.Flags &= ~MO_WINDOWTOBACK;
									break;
								case 3:	/* ScreenToBack */
									if (MenuItem3.Flags & CHECKED)
										MouseOpt.Flags |= MO_SCREENTOBACK;
									else
										MouseOpt.Flags &= ~MO_SCREENTOBACK;
									break;
								case 4:	/* SunMouse */
									if (GetNumber("Sun: -1 Disable", MouseOpt.SunMouse, -1, 100))
										MouseOpt.SunMouse = (USHORT)GLS.result;
									if (MouseOpt.SunMouse >= 0)
										MenuItem4.Flags |= CHECKED;
									else
										MenuItem4.Flags &= ~CHECKED;
									break;
								case 5:	/* acclerator */
									if (GetNumber("Accel: 0 disable.", MouseOpt.Acc, 0, 10))
										 MouseOpt.Acc = (USHORT)GLS.result;
									break;
								case 6:	/* Threshold */
									if (GetNumber("Threshold", MouseOpt.Threshold, 1, 10))
										MouseOpt.Threshold = (USHORT)GLS.result;
									break;
								case 7:	/* MouseBlank */
									if (GetNumber("Delay in sec", MouseOpt.MouseBlank, 0, 65535))
										MouseOpt.MouseBlank = (USHORT)GLS.result;
									break;
								case 8:	/* ScreenBlank */
									if (GetNumber("Delay in sec", MouseOpt.ScreenBlank, 0, 65535))
										MouseOpt.ScreenBlank = (USHORT)GLS.result;
									break;
								case 9:	/* HandlerPri */
									if (GetNumber("HandlerPri, active next reset", MouseOpt.HandlerPri, 51, 127))
										MouseOpt.HandlerPri = (USHORT)GLS.result;
									break;
								case 10:	/* SaveOpt */
									SaveMouseOpt(&MouseOpt);
									break;
								}
								break;
							}
						} while (DoNextSelect && (Code = ItemAddress(&Menu1, Code)->NextSelect) != MENUNULL);
					}
					break;
				}
			}
			UpdateMouseOpt(&MouseOpt);
		}
		CloseWindowSafely(Window, NULL);
	}
	return 0;
}


