/*
**	GadTools layout toolkit
**
**	Copyright © 1993-1995 by Olaf `Olsen' Barthel
**	Freely distributable.
*/

#include "gtlayout_global.h"

struct GTLayoutBase
{
	struct Library		 LibNode;

	struct ExecBase		*ExecBase;
	struct SignalSemaphore	 LockSemaphore;
	BPTR			 LibSegment;
};

#define SysBase GTLayoutBase -> ExecBase

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

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,
#ifdef DO_FRACTION_KIND
	LT_Fixed2String,
	LT_String2Fixed,
	LT_FixedMult,
#else
	LibNull,
	LibNull,
	LibNull,
#endif	// DO_FRACTION_KIND
	LT_LabelWidth,
	LT_LabelChars,
	LT_LockWindow,
	LT_UnlockWindow,
	LT_DeleteWindowLock,
	LT_ShowWindow,
	LT_Activate,
	LT_PressButton,
	LT_GetCode,
	LT_GetIMsg,
	LT_ReplyIMsg,
	LT_BuildA,
	LT_RebuildTagList,
	LT_UpdateStrings,

#ifdef DO_MENUS
	LT_DisposeMenu,
	LT_NewMenuTemplate,
	LT_NewMenuTagList,
	LT_MenuControlTagList,
	LT_GetMenuItem,
	LT_FindMenuCommand,
#else
	LibNull,
	LibNull,
	LibNull,
	LibNull,
	LibNull,
	LibNull,
#endif	// DO_MENUS

	LT_NewLevelWidth,

	(APTR)-1
};

extern UBYTE __far	LibName[],
			LibID[];

extern LONG __far	LibVersion,
			LibRevision;

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

struct Library * __saveds __asm
LibInit(register __a0 BPTR Segment,register __d0 struct GTLayoutBase *GTLayoutBase,register __a6 struct ExecBase *ExecBase)
{
#if defined(CPU_68020) || defined(CPU_68030) || defined(CPU_68040)
	if(ExecBase -> LibNode . lib_Version < 37 || !(ExecBase -> AttnFlags & AFF_68020))
		return(NULL);
#else
	if(ExecBase -> LibNode . lib_Version < 37)
		return(NULL);
#endif	// CPU_...

	GTLayoutBase -> LibNode . lib_Node . ln_Type	= NT_LIBRARY;
	GTLayoutBase -> LibNode . lib_Node . ln_Name	= LibName;
	GTLayoutBase -> LibNode . lib_Flags		= LIBF_CHANGED | LIBF_SUMUSED;
	GTLayoutBase -> LibNode . lib_Version		= LibVersion;
	GTLayoutBase -> LibNode . lib_Revision		= LibRevision;
	GTLayoutBase -> LibNode . lib_IdString		= (APTR)LibID;

	GTLayoutBase -> LibSegment	= Segment;
	GTLayoutBase -> ExecBase	= ExecBase;

	InitSemaphore(&GTLayoutBase -> LockSemaphore);

	return(GTLayoutBase);
}

struct Library * __saveds __asm
LibOpen(register __a6 struct GTLayoutBase *GTLayoutBase)
{
	GTLayoutBase -> LibNode . lib_Flags &= ~LIBF_DELEXP;

	GTLayoutBase -> LibNode . lib_OpenCnt++;

	ObtainSemaphore(&GTLayoutBase -> LockSemaphore);

	if(GTLayoutBase -> LibNode . lib_OpenCnt == 1)
	{
		if(!LT_Init())
		{
			LT_Exit();

			GTLayoutBase -> LibNode . lib_OpenCnt--;

			ReleaseSemaphore(&GTLayoutBase -> LockSemaphore);

			return(NULL);
		}
	}

	ReleaseSemaphore(&GTLayoutBase -> LockSemaphore);

	return(GTLayoutBase);
}

BPTR __saveds __asm
LibExpunge(register __a6 struct GTLayoutBase *GTLayoutBase)
{
	if(!GTLayoutBase -> LibNode . lib_OpenCnt && GTLayoutBase -> LibSegment)
	{
		BPTR TempSegment = GTLayoutBase -> LibSegment;

		Remove((struct Node *)GTLayoutBase);

		FreeMem((BYTE *)GTLayoutBase - GTLayoutBase -> LibNode . lib_NegSize,GTLayoutBase -> LibNode . lib_NegSize + GTLayoutBase -> LibNode . lib_PosSize);

		return(TempSegment);
	}
	else
	{
		GTLayoutBase -> LibNode . lib_Flags |= LIBF_DELEXP;

		return(NULL);
	}
}

BPTR __saveds __asm
LibClose(register __a6 struct GTLayoutBase *GTLayoutBase)
{
	if(GTLayoutBase -> LibNode . lib_OpenCnt)
		GTLayoutBase -> LibNode . lib_OpenCnt--;

	ObtainSemaphore(&GTLayoutBase -> LockSemaphore);

	if(!GTLayoutBase -> LibNode . lib_OpenCnt)
	{
		LT_Exit();

		ReleaseSemaphore(&GTLayoutBase -> LockSemaphore);

		if(GTLayoutBase -> LibNode . lib_Flags & LIBF_DELEXP)
			return(LibExpunge(GTLayoutBase));
	}
	else
		ReleaseSemaphore(&GTLayoutBase -> LockSemaphore);

	return(NULL);
}

LONG __saveds __asm
LibNull(register __a6 struct GTLayoutBase *GTLayoutBase)
{
	return(NULL);
}
