/*
 *	LibSup.c - Copyright © 1990 by S.R. & P.C.
 *
 *	Created:	22 Sep 1990  20:52:16
 *	Modified:	18 Feb 1992  19:42:22
 *
 *	Make>> make
 */

#include "ParMBase.h"

#define PARMREVISION	7	/* would be nice to auto-increment this */

char ParMLibName[] = "parm.library";
char ParMLibId[] = "V4.7 (18 Feb 1992)\r\n";

void InstallHandler(void);
void RemoveHandler(void);
BOOL LoadMouseOpt(char *MouseOptFileName, struct MouseOpt *MouseOpt);

void ParMLibInit(void);
long ParMLibOpen(void);
long ParMLibClose(void);
long ParMLibExpunge(void);

#pragma amicall(ParMBase, 0x06, ParMLibOpen())
#pragma amicall(ParMBase, 0x0c, ParMLibClose())
#pragma amicall(ParMBase, 0x12, ParMLibExpunge())

long DosWrite(BPTR file, char *buffer, long length);
#pragma amicall(DOSBase, 0x30, DosWrite(d1,d2,d3))


extern struct ExecBase *SysBase;
extern struct Library *DOSBase;
extern struct Resident ParMLibRomTag;

struct ParMBase *ParMBase;	/* Have a global ParMBase for internal functions */
struct ArpBase *ArpBase;
struct ReqLib *ReqBase;
struct IconBase *IconBase;
struct GfxBase *GfxBase;
struct LayersBase *LayersBase;
struct IntuitionBase *IntuitionBase;
/* default mouse opts values */
struct MouseOpt MouseOpt = {MOUSEOPT_VERSION, 51, 0, 0, 2, 0, -1, 0, 0, IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RELATIVEMOUSE};


/* library initialization table, used for AUTOINIT libraries */

struct InitTable {
	ULONG it_DataSize;			/* library data space size			*/
	void **it_FuncTable;		/* table of entry points			*/
	void *it_DataInit;			/* table of data initializers		*/
	void (*it_InitFunc)(void);	/* initialization function to run	*/
};


void *libfunctab[] = {	/* my function table */
	ParMLibOpen,		/* standard open	*/
	ParMLibClose,		/* standard close	*/
	ParMLibExpunge,		/* standard expunge	*/
	0,

/* real lib functions */

	ParseMenus,
	FreeMenus,
	ARun,
	Run,
	WBRun,
	GetTool,
	MakeWBArg,
	MakeWBStartup,
	WBFree,
	Command,
	ParseLine,
	DosError,
	StrIoErr,
	MakeMenuShortCut,
	InitDefaults,
	FreeRepliedWBMessages,
	NewMinList,
	CopyStr,
	FreeStr,
	IsHidden,
	GetWindow,
	CreateExtIO,
	CleanUp,
	NewCleanUp,
	UpdateParMEventsWindow,
	UpdateMouseOpt,
	GetCurrentMouseOpt,
	(void *) -1L		/* end of function vector table */
};


struct InitTable ParMLibInitTab = {
	sizeof(struct ParMBase),
	libfunctab,
	0,			/* will initialize my data in funkymain()	*/
	ParMLibInit
};


/* Init the global ParMBase */

void StoreParMBase(struct ParMBase *pb)
{
	ParMBase = pb;
}


void _main(struct ParMBase * ParMBase, unsigned long seglist)
{
	ParMBase->pb_SegList = seglist;

	/* -----  init. library structure  ----- */
	ParMBase->pb_Lib.lib_Node.ln_Type = NT_LIBRARY;
	ParMBase->pb_Lib.lib_Node.ln_Name = (char *) ParMLibName;
	ParMBase->pb_Lib.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
	ParMBase->pb_Lib.lib_Version = ParMLibRomTag.rt_Version;
	ParMBase->pb_Lib.lib_Revision = PARMREVISION;
	ParMBase->pb_Lib.lib_IdString = (APTR) ParMLibId;
	ParMBase->pb_MsgPort.mp_Flags = PA_IGNORE;
	NewMinList((struct MinList *) & ParMBase->pb_MsgPort.mp_MsgList);
	StoreParMBase(ParMBase);
	LoadMouseOpt(DEFAULT_MOUSEOPT_FILE, &MouseOpt);
}


long ParMLibOpen(void)
{
	struct ParMBase *ParMBase;
	struct Process *pp;

	pp = (struct Process *) SysBase->ThisTask;
	if (!ReqBase && !(ReqBase = (struct ReqLib *) OpenLibrary("req.library", 1))) {
		if (pp->pr_COS)
			DosWrite(pp->pr_COS, "You need req.library\n", 21L);
		return NULL;
	}
	if (!IconBase && !(IconBase = (struct IconBase *) OpenLibrary("icon.library", 0L))) {
		SimpleRequest("parm.library", "You need icon.library!");
		return NULL;
	}
	if (!LayersBase && !(LayersBase = (struct LayersBase *) OpenLibrary("layers.library", 0L)))
		return NULL;
	/* Each user must open arp.library for individual tracked resources */
	if (!(ArpBase = (struct ArpBase *) OpenLibrary("arp.library", 39))) {
		SimpleRequest("parm.library", "You need arp.library V39+\n");
		return NULL;
	}
	ParMBase->ArpBase = ArpBase;
	ParMBase->ReqBase = ReqBase;
	ParMBase->IconBase = IconBase;
	ParMBase->LayersBase = LayersBase;
	IntuitionBase = (struct IntuitionBase *)ArpBase->IntuiBase;
	GfxBase = (struct GfxBase *)ArpBase->GfxBase;
	/* Handler is removed each time OpenCnt becomes zero */
	/* mark us as having another customer */
	if (ParMBase->pb_Lib.lib_OpenCnt++ == 0)
		InstallHandler();
	/* prevent delayed expunges (standard procedure) */
	ParMBase->pb_Lib.lib_Flags &= ~LIBF_DELEXP;
	return (long)ParMBase;
}


long ParMLibClose(void)
{
	struct ParMBase *ParMBase;

	CloseLibrary(ArpBase);
	if (--ParMBase->pb_Lib.lib_OpenCnt == 0) {
		RemoveHandler();
		if (ParMBase->pb_Lib.lib_Flags & LIBF_DELEXP) {
			/* no more people have me open, and I have a delayed expunge pending */
			return ParMLibExpunge(); 	/* return segment list	*/
		}
	}
	return NULL;
}


long ParMLibExpunge(void)
{
	struct ParMBase *ParMBase;
	ULONG seglist = 0;
	long libsize;
	extern struct Library *DOSBase;

	if (ParMBase->pb_Lib.lib_OpenCnt == 0 && ParMBase->pb_MsgCnt == 0) {
		if (ReqBase)
			CloseLibrary(ReqBase);
		if (IconBase)
			CloseLibrary(IconBase);
		if (LayersBase)
			CloseLibrary(LayersBase);
		/* really expunge: remove libbase and freemem */
		seglist = ParMBase->pb_SegList;
		Remove(&ParMBase->pb_Lib.lib_Node);	/* I'm no longer an installed library */
		libsize = ParMBase->pb_Lib.lib_NegSize + ParMBase->pb_Lib.lib_PosSize;
		FreeMem((char *) ParMBase - ParMBase->pb_Lib.lib_NegSize, libsize);
		CloseLibrary(DOSBase);
	}
	else
		ParMBase->pb_Lib.lib_Flags |= LIBF_DELEXP;

	/* return NULL or real seglist */
	return (long) seglist;
}


void GetCurrentMouseOpt(struct MouseOpt *YourMouseOpt)
{
	*YourMouseOpt = MouseOpt;
}


