/*
**	classbase.c - implementation of standard function for XPK DataType class
**	Copyright © 1995 Michael Letowski
*/

#include <exec/types.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <support/types.h>

#include <proto/exec.h>
#include <proto/intuition.h>

#include "classbase.h"
#include "dispatch.h"


/*
**	Private constants
*/
#define INT_NAME		"intuition.library"
#define INT_VERN		39
#define DOS_NAME		"dos.library"
#define DOS_VERN		39
#define UTIL_NAME		"utility.library"
#define UTIL_VERN		39
#define DT_NAME			"datatypes.library"
#define DT_VERN			39
#define XPK_NAME		"xpkmaster.library"
#define XPK_VERN		0


/*
**	Public functions
*/
ASM Class *ObtainEngine(R_A6 struct ClassBase *cb)
{
	return(cb->cb_Class);
}	/* ObtainEngine */

ASM struct ClassBase *LibInit(R_D0 struct ClassBase *cb, R_A0 BPTR segList,
															R_A6 struct Library *sysBase)
{
	cb->cb_SegList=segList;
	cb->cb_SysBase=(struct ExecBase *)sysBase;

	InitSemaphore(&cb->cb_Lock);									/* Initialize locking */

	try(cb->cb_IntuitionBase=	OpenLibrary(INT_NAME,INT_VERN),		NO_INT);
	try(cb->cb_DOSBase=				OpenLibrary(DOS_NAME,DOS_VERN),		NO_DOS);
	try(cb->cb_UtilityBase=		OpenLibrary(UTIL_NAME,UTIL_VERN),	NO_UTIL);
	return(cb);

	/* Exceptions */
	catch(FOO,			);
	catch(NO_UTIL,	CloseLibrary(cb->cb_UtilityBase));
	catch(NO_DOS,		CloseLibrary(cb->cb_DOSBase));
	catch(NO_INT,		CloseLibrary(cb->cb_IntuitionBase));
	return(NULL);
}	/* LibInit */

ASM struct ClassBase *LibOpen(R_A6 struct ClassBase *cb)
{
	ObtainSemaphore(&cb->cb_Lock);								/* Protect library base */
	fclr(cb->cb_Lib.lib_Flags,LIBF_DELEXP);				/* No delayed expunge */

	if(cb->cb_Lib.lib_OpenCnt==0 && cb->cb_Class==NULL)
	{																							/* First open */
		try(cb->cb_DataTypesBase=		OpenLibrary(DT_NAME,DT_VERN),		NO_DT);
		try(cb->cb_XpkBase=					OpenLibrary(XPK_NAME,XPK_VERN),	NO_XPK);
		try(cb->cb_Class=InitClass(cb),															NO_CLASS);
	}

	cb->cb_Lib.lib_OpenCnt++;											/* Mark successfull opening */
	ReleaseSemaphore(&cb->cb_Lock);								/* Data modified */
	return(cb);																		/* Return success */

	/* Exceptions */
	catch(FOO,			);
	catch(NO_CLASS,	FreeClass(cb->cb_Class));
	catch(NO_XPK,		CloseLibrary(cb->cb_XpkBase));
	catch(NO_DT,		CloseLibrary(cb->cb_DataTypesBase));
	ReleaseSemaphore(&cb->cb_Lock);								/* Unlock base */
	return(NULL);																	/* Return failure */
}	/* LibOpen */

ASM BPTR LibClose(R_A6 struct ClassBase *cb)
{
	BPTR Seg=0;

	ObtainSemaphore(&cb->cb_Lock);								/* Protect library base */
	if(cb->cb_Lib.lib_OpenCnt)
		cb->cb_Lib.lib_OpenCnt--;										/* Decrease open count */
	if(cb->cb_Lib.lib_OpenCnt==0 && cb->cb_Class)
		if(FreeClass(cb->cb_Class))
		{
			cb->cb_Class=NULL;
			CloseLibrary(cb->cb_XpkBase);
			CloseLibrary(cb->cb_DataTypesBase);
		}
		else
			fset(cb->cb_Lib.lib_Flags,LIBF_DELEXP);
	ReleaseSemaphore(&cb->cb_Lock);								/* Unlock base */
	if(ftst(cb->cb_Lib.lib_Flags,LIBF_DELEXP))		/* Delayed expunge set? */
		Seg=LibExpunge(cb);
	return(Seg);
}	/* LibClose */

ASM BPTR LibExpunge(R_A6 struct ClassBase *cb)
{
	BPTR Seg=0;

	if(cb->cb_Class==NULL)												/* No accesors? */
	{
		Seg=cb->cb_SegList;
		Remove((struct Node *)cb);									/* Remove from library list */
		CloseLibrary(cb->cb_UtilityBase);
		CloseLibrary(cb->cb_DOSBase);
		CloseLibrary(cb->cb_IntuitionBase);
		FreeMem((APTR)((ULONG)(cb)-(ULONG)(cb->cb_Lib.lib_NegSize)),
						cb->cb_Lib.lib_NegSize + cb->cb_Lib.lib_PosSize);
	}
	return(Seg);
}	/* LibExpunge */
