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

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

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

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

#define INT_NAME		"intuition.library"
#define INT_VERN		39
#define GFX_NAME		"graphics.library"
#define GFX_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 DF_NAME			"diskfont.library"
#define DF_VERN			39
#define PDT_NAME		"datatypes/picture.datatype"
#define PDT_VERN		39

ASM Class *ObtainFontEngine(R_A6 struct ClassBase *cb)
{
	return(cb->cb_Class);
}	/* ObtainREKOEngine */

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_GfxBase=OpenLibrary(GFX_NAME,GFX_VERN),				NO_GFX);
	try(cb->cb_DOSBase=OpenLibrary(DOS_NAME,DOS_VERN),				NO_DOS);
	try(cb->cb_UtilityBase=OpenLibrary(UTIL_NAME,UTIL_VERN),	NO_UTIL);
	return(cb);

	except(FOO,				);
	except(NO_UTIL,	CloseLibrary(cb->cb_UtilityBase));
	except(NO_DOS,	CloseLibrary(cb->cb_DOSBase));
	except(NO_GFX,	CloseLibrary(cb->cb_GfxBase));
	except(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_DiskfontBase=OpenLibrary(DF_NAME,DF_VERN),			NO_DF);
		try(cb->cb_SuperClassBase=OpenLibrary(PDT_NAME,PDT_VERN),	NO_PDT);
		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 */

	except(FOO,				);
	except(NO_CLASS,FreeClass(cb->cb_Class));
	except(NO_PDT,	CloseLibrary(cb->cb_SuperClassBase));
	except(NO_DF,		CloseLibrary(cb->cb_DiskfontBase));
	except(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_SuperClassBase);
			CloseLibrary(cb->cb_DiskfontBase);
			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_GfxBase);
		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 */
