/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1990 by MXM
 *
 *	Name .....: LibMain.c
 *	Created ..: Saturday 06-Jan-90 23:30
 *	Revision .: 8
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	01-Apr-90       Olsen           Rework for Aztec 5.0
 *	25-Jan-90       Olsen           Did some cleanups
 *	14-Jan-90       Olsen           Renamed to mxm.library
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           Appended new functions
 *	06-Jan-90       Olsen           - Empty log message -
 *	06-Jan-90       Olsen           - Empty log message -
 *	06-Jan-90       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

	/* Imported from MXM.c */

extern LONG Revision;

	/* ASCII library ID. */

char *LibName	= "mxm.library";
char *LibId	= "mxm.library 34.14 (01 Apr 1990)\r\n";

	/* External data, defined in asm startup code. */

extern struct Resident	 LibRomTag;
extern LONG		 LibInit();

	/* Protos for this module. */

struct MXMBase *	LibMain(struct MXMBase *,BPTR);
struct MXMBase *	LibOpen(VOID);
BPTR			LibClose(VOID);
BPTR			LibExpunge(VOID);

	/* And now for the pragmas... */

#pragma amicall(MXMBase,0x06,LibOpen())
#pragma amicall(MXMBase,0x0C,LibClose())
#pragma amicall(MXMBase,0x12,LibExpunge())

	/* The library initialization. */

#pragma regcall(LibMain(d0,a0))

	/* The structure expected by the library loader (auto-init). */

struct InitTable
{
	ULONG	 it_DataSize;	/* Data size to allocate. */
	APTR	*it_FuncTable;	/* Pointer to function table. */
	APTR	 it_DataInit;	/* Pointer to data initializers (remember InitStruct()?). */
	APTR	 it_InitFunc;	/* The real library init function. */
};

	/* The list of library functions. */

VOID *LibFuncTab[] =
{
	LibOpen,		/* Standard library routines. */
	LibClose,
	LibExpunge,
	NULL,			/* Reserved, leave it NULL. */

	AllocRem,
	FreeRem,
	CreateFuncTask,
	DeleteFuncTask,
	CreateFuncProc,
	MovePointer,
	WriteConsole,
	DeletePrinterSupport,
	CreatePrinterSupport,
	StartPrinterDump,
	StopPrinterDump,
	DeleteTimer,
	CreateTimer,
	WaitForTimer,
	TimeDelay,
	KeyConvert,
	InvertKey,
	EraseGadget,
	RefreshGadget,
	GetLongInt,
	SetLongInt,
	GetGadgetString,
	SetGadgetString,
	GetToggleGadget,
	SetToggleGadget,
	SetWaitPointer,
	PopRequest,
	PopMenu,
	Announce,
	CheckSumCRC,
	CheckSumSimple,
	CryptBlock,
	IsASCII,
	IsPrintable,
	ToUpper,
	UStrCmp,
	Random,
	FindFileWindow,
	DeleteHiddenRPort,
	CreateHiddenRPort,
	EnableWindow,
	DisableWindow,

	(VOID *)-1		/* End marker. */
};

	/* The romtag needs this. */

struct InitTable LibInitTab =
{
	(ULONG)sizeof(struct MXMBase),	/* Lib base. */
	(APTR)LibFuncTab,		/* Function table. */
	NULL,				/* No data init table (we'll do autoinit). */
	(APTR)LibInit			/* Lib init routine. */
};

	/* Library auxilary data. */

struct IOStdReq		*kc_ConStdReq;
struct KeyEquivalent	*EquList;
struct KeyMap		*ik_KeyMap;
struct SignalSemaphore	*PopSemaphore;

	/* The libraries this library needs. */

APTR			 IntuitionBase;
APTR			 GfxBase;
APTR			 LayersBase;
APTR			 DOSBase;
APTR			 ConsoleDevice;

	/* Global segment list (we only need one). */

BPTR			 LibSegList = ZERO;

	/* LibMain(MXMBase,SegList):
	 *
	 *	Does the main library initialization, expects
	 *	arguments in registers.
	 */

struct MXMBase *
LibMain(MXMBase,SegList)
struct MXMBase *MXMBase;
BPTR SegList;
{
		/* We don't wish to be initialized twice,
		 * the check for LibSegList will hopefully
		 * insure this.
		 */

	if(!LibSegList)
	{
			/* Remember segment list. */

		LibSegList = SegList;

			/* Try to open the required libraries. */

		if(!(IntuitionBase = (APTR)OpenLibrary("intuition.library",LIBRARY_MINIMUM)))
			goto Failed;

		if(!(GfxBase = (APTR)OpenLibrary("graphics.library",LIBRARY_MINIMUM)))
			goto Failed;

		if(!(LayersBase = (APTR)OpenLibrary("layers.library",LIBRARY_MINIMUM)))
			goto Failed;

		if(!(DOSBase = (APTR)OpenLibrary("dos.library",LIBRARY_MINIMUM)))
			goto Failed;

		if(!(kc_ConStdReq = (struct IOStdReq *)AllocMem(sizeof(struct IOStdReq),MEMF_PUBLIC | MEMF_CLEAR)))
			goto Failed;

		if(OpenDevice("console.device",-1,kc_ConStdReq,0))
			goto Failed;

		if(!(EquList = (struct KeyEquivalent *)AllocMem(sizeof(struct KeyEquivalent) * 94,MEMF_PUBLIC | MEMF_CLEAR)))
			goto Failed;

		if(!(ik_KeyMap = (struct KeyMap *)AllocMem(sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR)))
			goto Failed;

		if(!(PopSemaphore = (struct SignalSemaphore *)AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC | MEMF_CLEAR)))
			goto Failed;

		InitSemaphore(PopSemaphore);

		ConsoleDevice = (APTR)kc_ConStdReq -> io_Device;

			/* Fill in the library head. */

		MXMBase -> LibNode . lib_Node . ln_Type	= NT_LIBRARY;
		MXMBase -> LibNode . lib_Node . ln_Name	= LibName;
		MXMBase -> LibNode . lib_Flags		= LIBF_SUMUSED | LIBF_CHANGED;
		MXMBase -> LibNode . lib_Version	= LibRomTag . rt_Version;
		MXMBase -> LibNode . lib_Revision	= Revision;
		MXMBase -> LibNode . lib_IdString	= (APTR)LibId;

		MXMBase -> IntuitionBase	= IntuitionBase;
		MXMBase -> GfxBase		= GfxBase;
		MXMBase -> LayersBase		= LayersBase;
		MXMBase -> DOSBase		= DOSBase;
		MXMBase -> ConsoleDevice	= ConsoleDevice;

		return(MXMBase);

Failed:		if(IntuitionBase)
			CloseLibrary(IntuitionBase);

		if(GfxBase)
			CloseLibrary(GfxBase);

		if(LayersBase)
			CloseLibrary(LayersBase);

		if(ConsoleDevice)
			CloseDevice(kc_ConStdReq);

		if(DOSBase)
			CloseLibrary(DOSBase);

		if(EquList)
			FreeMem(EquList,sizeof(struct KeyEquivalent) * 94);

		if(kc_ConStdReq)
			FreeMem(kc_ConStdReq,sizeof(struct IOStdReq));

		if(ik_KeyMap)
			FreeMem(ik_KeyMap,sizeof(struct KeyMap));

		if(PopSemaphore)
			FreeMem(PopSemaphore,sizeof(struct SignalSemaphore));

		LibSegList = ZERO;

		return(NULL);
	}
}

	/* LibOpen():
	 *
	 *	Library open routine.
	 */

struct MXMBase *
LibOpen()
{
	struct MXMBase *MXMBase;

		/* Check if everything is in good shape. */

	if(!IntuitionBase || !GfxBase || !LayersBase || !DOSBase || !ConsoleDevice || !EquList || !kc_ConStdReq || !ik_KeyMap)
		return(NULL);

		/* Increment open count. */

	MXMBase -> LibNode . lib_OpenCnt++;
	MXMBase -> LibNode . lib_Flags &= ~LIBF_DELEXP;

		/* Return base pointer. */

	return(MXMBase);
}

	/* LibClose():
	 *
	 *	Closes the library.
	 */

BPTR
LibClose()
{
	struct MXMBase	*MXMBase;
	BPTR		 SegList = ZERO;

		/* Time for an expunge? */

	if(MXMBase -> LibNode . lib_OpenCnt > 0)
	{
		MXMBase -> LibNode . lib_OpenCnt--;

		SegList = LibExpunge();
	}
	else
		Alert(AT_Recovery | AG_CloseLib,"MXM");

	return(SegList);
}

	/* LibExpunge(MXMBase):
	 *
	 *	Expunge library, careful: this can be called by
	 *	ramlib while the rest of the library doesn't know
	 *	about it.
	 */

BPTR
LibExpunge()
{
	struct MXMBase	*MXMBase;
	BPTR		 SegList = ZERO;

		/* Is user count zero, the delayed expunge flag
		 * set and the library seglist valid?
		 */

	if(MXMBase -> LibNode . lib_OpenCnt == 0 && (MXMBase -> LibNode . lib_Flags & LIBF_DELEXP) && LibSegList)
	{
			/* Remember segment list. */

		SegList = LibSegList;

		LibSegList = ZERO;

			/* Remove library from lib list. */

		Remove((struct Node *)MXMBase);

			/* Some paranoid action. */

		MXMBase -> LibNode . lib_Flags &= ~LIBF_DELEXP;

			/* Close what we've opened. */

		if(IntuitionBase)
			CloseLibrary(IntuitionBase);

		if(GfxBase)
			CloseLibrary(GfxBase);

		if(LayersBase)
			CloseLibrary(LayersBase);

		if(ConsoleDevice)
			CloseDevice(kc_ConStdReq);

		if(DOSBase)
			CloseLibrary(DOSBase);

		if(EquList)
			FreeMem(EquList,sizeof(struct KeyEquivalent) * 94);

		if(kc_ConStdReq)
			FreeMem(kc_ConStdReq,sizeof(struct IOStdReq));

		if(ik_KeyMap)
			FreeMem(ik_KeyMap,sizeof(struct KeyMap));

		if(PopSemaphore)
			FreeMem(PopSemaphore,sizeof(struct SignalSemaphore));

			/* Free library mem. */

		FreeMem((char *)MXMBase - MXMBase -> LibNode . lib_NegSize,MXMBase -> LibNode . lib_NegSize + MXMBase -> LibNode .lib_PosSize);
	}
	else
	{
			/* In any other case we'll set the delayed
			 * expunge flag (so next expunge call will
			 * hopefully wipe us from the lib list.
			 */

		MXMBase -> LibNode . lib_Flags |= LIBF_DELEXP;
	}

		/* Return segment list pointer. */

	return(SegList);
}
