
/*FS*//* ------------------------------- includes ------------------------------- */

#include "classbase.h"
/*FE*/

/*FS*//* ------------------------------ prototypes ------------------------------ */

LibCall struct Library *LibInit (REGD0 struct ClassBase *cb, REGA0 BPTR seglist, REGA6 struct Library * sysbase);
LibCall LONG LibOpen (REGA6 struct ClassBase *cb);
LibCall LONG LibClose (REGA6 struct ClassBase *cb);
LibCall LONG LibExpunge (REGA6 struct ClassBase *cb);

static Class *initClass(struct ClassBase *cb);

extern const UWORD LibDataTable[];
extern const UWORD LibFuncTable[];

#ifdef USERCLASSBASEINIT
extern BOOL UserClassBaseInit(struct ClassBase *cb);
extern void UserClassBaseClean(struct ClassBase *cb);
#endif
/*FE*/

/*FS*//* --------------------------------- data --------------------------------- */

const ULONG LibInitTable[4] = {
   (ULONG) sizeof(struct ClassBase),
   (ULONG) LibFuncTable,
   (ULONG) LibDataTable,
   (ULONG) LibInit
   };
/*FE*/

/* ---------------------------- implementation ---------------------------- */

/*FS*/ static Class *initClass(struct ClassBase *cb)
{
   Class *cl;

   if((cl = MakeClass(CLASSNAME,SUPERCLASSNAME,NULL,INSTANCESIZE,0)) != NULL)
   {
      DB(("dispatcher : %lx,size : %ld\n",dispatcher,INSTANCESIZE));

      cl->cl_Dispatcher.h_Entry = (HOOKFUNC) dispatcher;
      cl->cl_UserData = (ULONG) cb;

      AddClass(cl);
   }

   DB(("class : %lx\n",cl));

   return(cl);
}
/*FE*/

/*FS*/ LibCall Class *ObtainEngine (REGA6 struct ClassBase *cb)
{
   return(cb->cb_Class);
}
/*FE*/

/*FS*/ LibCall struct Library *LibInit (REGD0 struct ClassBase *cb, REGA0 BPTR seglist, REGA6 struct Library * sysbase)
{
   cb->cb_SegList = seglist;
   cb->cb_SysBase = sysbase;

   if(cb->cb_SysBase->lib_Version >= 39)
   {
      cb->cb_IntuitionBase = OpenLibrary("intuition.library",39);
      cb->cb_DOSBase       = OpenLibrary("dos.library",      39);
      cb->cb_UtilityBase   = OpenLibrary("utility.library",  39);
      cb->cb_DataTypesBase = OpenLibrary("datatypes.library",39);
#ifdef USE_GFXLIB
      cb->cb_GfxBase       = OpenLibrary("graphics.library", 39);
#endif
#ifdef USE_IFFPARSELIB
      cb->cb_IFFParseBase  = OpenLibrary("iffparse.library", 39);
#endif
#ifdef USERCLASSBASEINIT
      if(!UserClassBaseInit(cb))
      {
	 CloseLibrary(cb->cb_IntuitionBase);
	 CloseLibrary(cb->cb_DOSBase);
	 CloseLibrary(cb->cb_UtilityBase);
	 CloseLibrary(cb->cb_DataTypesBase);
#ifdef USE_GFXLIB
	 CloseLibrary(cb->cb_GfxBase;
#endif
#ifdef USE_IFFPARSELIB
	 CloseLibrary(cb->cb_IFFParseBase);
#endif
	 cb = NULL;
      }
#endif

   } else
      cb = NULL;

  return((struct Library *) cb);
}
/*FE*/
/*FS*/LibCall LONG LibOpen (REGA6 struct ClassBase *cb)
{
   LONG retval = (LONG) cb;

   cb->cb_Lib.lib_Flags &= ~LIBF_DELEXP;

   if(cb->cb_Class == NULL)
   {
#ifdef SUPERCLASSLIBRARY
      if((cb->cb_SuperClassBase = OpenLibrary(SUPERCLASSLIBRARY,SUPERCLASSLIBRARYVERSION)) != NULL)
      {
#endif
	 cb->cb_Class = initClass(cb);

#ifdef SUPERCLASSLIBRARY
	 if(cb->cb_Class == NULL)
	 {
	    CloseLibrary(cb->cb_SuperClassBase);
	    cb->cb_SuperClassBase = NULL;
	 }
      }
#endif

   }
   if(cb->cb_Class != NULL)
      cb->cb_Lib.lib_OpenCnt++;
   else
      retval = 0;

   DB(("return = 0x%lx\n",retval));

   return retval;
}
/*FE*/
/*FS*/LibCall LONG LibClose (REGA6 struct ClassBase *cb)
{
   LONG retval = NULL;

   DB(("cnt = %ld, class = 0x%lx\n",cb->cb_Lib.lib_OpenCnt,cb->cb_Class));

   cb->cb_Lib.lib_OpenCnt--;

   if(cb->cb_Lib.lib_OpenCnt == 0 && cb->cb_Class != NULL)
   {
      if(FreeClass(cb->cb_Class))
	 cb->cb_Class = NULL;

#ifdef SUPERCLASSLIBRARY
      if(cb->cb_Class == NULL)
      {
	 CloseLibrary(cb->cb_SuperClassBase);
	 cb->cb_SuperClassBase = NULL;
      }
#endif

   }

   DB(("cnt = %ld, class = 0x%lx\n",cb->cb_Lib.lib_OpenCnt,cb->cb_Class));

   if(cb->cb_Lib.lib_Flags & LIBF_DELEXP)
      retval = LibExpunge (cb);

   DB(("return = 0x%lx\n",retval));

   return retval;
}
/*FE*/
/*FS*/LibCall LONG LibExpunge(REGA6 struct ClassBase *cb)
{
   BPTR seg = NULL;

   cb->cb_Lib.lib_Flags |= LIBF_DELEXP;

   DB(("cnt = %ld, class = 0x%lx\n",cb->cb_Lib.lib_OpenCnt,cb->cb_Class));

   if(cb->cb_Lib.lib_OpenCnt == 0)
   {
      if(cb->cb_Class != NULL)
      {
	 if(FreeClass(cb->cb_Class))
	    cb->cb_Class = NULL;

#ifdef SUPERCLASSLIBRARY
	 if(cb->cb_Class == NULL)
	    CloseLibrary(cb->cb_SuperClassBase);
#endif
      }

      if(cb->cb_Class == NULL)
      {
	 seg = cb->cb_SegList;

	 Remove((struct Node *) cb);

#ifdef USERCLASSBASEINIT
	 UserClassBaseClean(cb);
#endif

	 CloseLibrary((struct Library *) UtilityBase);
	 CloseLibrary((struct Library *) DOSBase);
	 CloseLibrary((struct Library *) IntuitionBase);
	 CloseLibrary((struct Library *) DataTypesBase);

#ifdef USE_GFXLIB
	 CloseLibrary((struct Library *) GfxBase);
#endif
#ifdef USE_IFFPARSELIB
	 CloseLibrary((struct Library *) IFFParseBase);
#endif

	 FreeMem((APTR)((ULONG)(cb) - (ULONG)(cb->cb_Lib.lib_NegSize)), cb->cb_Lib.lib_NegSize + cb->cb_Lib.lib_PosSize);
      }
   }

   DB(("return = 0x%lx\n",seg));

   return (LONG) seg;
}
/*FE*/

