/*
 *	LibSup.c - Copyright © 1990 by S.R. & P.C.
 *
 *	Created:	22 Sep 1990  20:52:16
 *	Modified:	20 Jul 1991  11:47:47
 *
 *	Make>> make
 */

#include "ParMBase.h"


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

char ParMLibName[] = "parm.library";
char ParMLibId[]   = "V1.7 (20 Jul 1991)\r\n";

void InstallHandler(void);
void RemoveHandler(void);

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 LayersBase *LayersBase;
struct IntuitionBase *IntuitionBase;


/* 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,
	(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);
}


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;
	/* Handler is removed each time OpenCnt becomes zero */
	if (ParMBase->pb_Lib.lib_OpenCnt == 0)
		InstallHandler();
	/* mark us as having another customer */
	ParMBase->pb_Lib.lib_OpenCnt++;
	/* 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 && ParMBase->pb_MsgCnt == 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;
}


