#define LIB_CODE 1

#include "gtlayout.h"

#include <dos/dos.h>

#include <exec/execbase.h>
#include <exec/libraries.h>

#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>

STATIC struct Library * __asm __saveds	LibInit(register __a0 BPTR Segment,register __d0 struct Library *Base);
STATIC struct Library * __asm __saveds	LibOpen(register __a6 struct Library *Base);
STATIC BPTR __asm __saveds		LibExpunge(register __a6 struct Library *Base);
STATIC BPTR __asm __saveds		LibClose(register __a6 struct Library *Base);
STATIC LONG __asm __saveds		LibNull(register __a6 struct Library *Base);

extern __far struct Resident RomTag;

STATIC APTR LibVectors[] =
{
	LibOpen,
	LibClose,
	LibExpunge,
	LibNull,

	LT_LevelWidth,
	LT_DeleteHandle,
	LT_CreateHandle,
	LT_CreateHandleTagList,
	LT_Rebuild,
	LT_HandleInput,
	LT_BeginRefresh,
	LT_EndRefresh,
	LT_GetAttributesA,
	LT_SetAttributesA,
	LT_AddA,
	LT_NewA,
	LT_EndGroup,
	LT_LayoutA,
	LT_LayoutMenusA,
	LT_Fixed2String,
	LT_String2Fixed,
	LT_FixedMult,
	LT_LabelWidth,
	LT_LabelChars,
	LT_LockWindow,
	LT_UnlockWindow,
	LT_DeleteWindowLock,
	LT_ShowWindow,
	LT_Activate,
	LT_PressButton,
	LT_GetCode,
	LT_GetIMsg,
	LT_ReplyIMsg,

	(APTR)-1
};

STATIC struct ExecBase		*SysBase;
STATIC struct SignalSemaphore	 LockSemaphore;

struct Library			*UtilityBase;

extern UBYTE __far		 LibName[],LibID[];
extern LONG __far		 LibVersion,LibRevision;

struct { ULONG DataSize; APTR Table; APTR Data; struct Library * (*Init)(); } __aligned LibInitTab =
{
	sizeof(struct Library),
	LibVectors,
	NULL,
	LibInit
};

STATIC BPTR LibSegment;

STATIC struct Library * __asm __saveds
LibInit(register __a0 BPTR Segment,register __d0 struct Library *Base)
{
	Base -> lib_Node . ln_Type	= NT_LIBRARY;
	Base -> lib_Node . ln_Name	= LibName;
	Base -> lib_Flags		= LIBF_CHANGED | LIBF_SUMUSED;
	Base -> lib_Version		= LibVersion;
	Base -> lib_Revision		= LibRevision;
	Base -> lib_IdString		= (APTR)LibID;

	LibSegment = Segment;

	SysBase = *(struct ExecBase **)4;

	InitSemaphore(&LockSemaphore);

#ifdef CPU_ANY
	if(SysBase -> LibNode . lib_Version < 37)
#else
	if(SysBase -> LibNode . lib_Version < 37 || !(SysBase -> AttnFlags & AFF_68020))
#endif	/* CPU_ANY */
		return(NULL);
	else
		return(Base);
}

STATIC struct Library * __asm __saveds
LibOpen(register __a6 struct Library *Base)
{
	Base -> lib_Flags &= ~LIBF_DELEXP;

	Base -> lib_OpenCnt++;

	if(Base -> lib_OpenCnt == 1)
	{
		ObtainSemaphore(&LockSemaphore);

		if(UtilityBase = OpenLibrary("utility.library",0))
		{
			if(LT_Init())
			{
				ReleaseSemaphore(&LockSemaphore);

				return(Base);
			}

			LT_Exit();

			CloseLibrary(UtilityBase);

			UtilityBase = NULL;
		}

		ReleaseSemaphore(&LockSemaphore);

		return(NULL);
	}
	else
		return(Base);
}

STATIC BPTR __asm __saveds
LibExpunge(register __a6 struct Library *Base)
{
	if(!Base -> lib_OpenCnt && LibSegment)
	{
		BPTR TempSegment = LibSegment;

		Remove((struct Node *)Base);

		FreeMem((BYTE *)Base - Base -> lib_NegSize,Base -> lib_NegSize + Base -> lib_PosSize);

		LibSegment = NULL;

		return(TempSegment);
	}
	else
	{
		Base -> lib_Flags &= ~LIBF_DELEXP;

		return(NULL);
	}
}

STATIC BPTR __asm __saveds
LibClose(register __a6 struct Library *Base)
{
	Base -> lib_OpenCnt--;

	if(!Base -> lib_OpenCnt)
	{
		ObtainSemaphore(&LockSemaphore);

		LT_Exit();

		CloseLibrary(UtilityBase);

		UtilityBase = NULL;

		ReleaseSemaphore(&LockSemaphore);

		if(Base -> lib_Flags & LIBF_DELEXP)
			return(LibExpunge(Base));
	}

	return(NULL);
}

STATIC LONG __asm __saveds
LibNull(register __a6 struct Library *Base)
{
	return(NULL);
}
