#ifndef XPKMASTER_LIBINIT_C
#define XPKMASTER_LIBINIT_C

/* Programmheader

	Name:		libinit.c
	Main:		xpkmaster
	Versionstring:	$VER: libinit.c 1.0 (21.02.1998)
	Author:		SDI
	Distribution:	Freeware
	Description:	all the library initialization stuff

 1.0   21.02.98 : first version, based on libdata.a and work of Gunther Nikl
*/

#include <proto/exec.h>
#include <proto/locale.h>
#include <exec/resident.h>
#include <exec/initializers.h>
#include "xpkmaster.h"
#include "texts.h"
#include "version.h"

struct LibInitData {
 UBYTE i_Type;     UBYTE o_Type;     UBYTE  d_Type;	UBYTE p_Type;
 UBYTE i_Name;     UBYTE o_Name;     STRPTR d_Name;
 UBYTE i_Flags;    UBYTE o_Flags;    UBYTE  d_Flags;	UBYTE p_Flags;
 UBYTE i_Version;  UBYTE o_Version;  UWORD  d_Version;
 UBYTE i_Revision; UBYTE o_Revision; UWORD  d_Revision;
 UBYTE i_IdString; UBYTE o_IdString; STRPTR d_IdString;
 ULONG endmark;
};

/************************************************************************/

LONG ReturnError(void);
static void CloseLibraries(void);
static void LocaleStrings(STRPTR *, ULONG, ULONG);

ULONG LibReserved(void);
ASM(BPTR) LibExpunge(REG(a6, struct Library *));
ASM(BPTR) LibClose(REG(a6, struct Library *));
ASM(struct Library *) LibOpen(REG(a6, struct Library *));
ASM(struct Library *) LibInit(REG(a0, BPTR), REG(d0, struct Library *));

/************************************************************************/

struct DosLibrary *		DOSBase		= 0;
struct IntuitionBase *		IntuitionBase	= 0;
struct UtilityBase *		UtilityBase	= 0;
struct Library *		GadToolsBase	= 0;
struct LocaleBase *		LocaleBase	= 0;
struct Library *		XpkBase		= 0;
static struct Catalog * 	Catalog		= 0;
static BPTR			SegList		= 0;

/************************************************************************/

/* First executable routine of this library; must return an error
   to the unsuspecting caller */
LONG ReturnError(void)
{
  return -1;
}

/************************************************************************/

/* The mandatory reserved library function */
ULONG LibReserved(void)
{
  return 0;
}

/* Close the library, as called by CloseLibrary() */
ASM(BPTR) LibClose(REG(a6, struct Library * xpkLib))
{
  if(!(--xpkLib->lib_OpenCnt))
  {
    if(xpkLib->lib_Flags & LIBF_DELEXP)
      return LibExpunge(xpkLib);
  }
  return 0;
}

/* Open the library, as called via OpenLibrary() */
ASM(struct Library *) LibOpen(REG(a6, struct Library * xpkLib))
{
  /* Prevent delayed expunge and increment opencnt */
  xpkLib->lib_Flags &= ~LIBF_DELEXP;
  xpkLib->lib_OpenCnt++;

  return xpkLib;
}

/* Expunge the library, remove it from memory */
ASM(BPTR) LibExpunge(REG(a6, struct Library * xpkLib))
{
  if(!xpkLib->lib_OpenCnt)
  {
    CloseLibraries();

    /* Remove the library from the public list */
    Remove((struct Node *) xpkLib);

    /* Free the vector table and the library data */
    FreeMem((STRPTR) xpkLib - xpkLib->lib_NegSize, xpkLib->lib_NegSize +
    xpkLib->lib_PosSize);

    return SegList;
  }
  else
    xpkLib->lib_Flags |= LIBF_DELEXP;

  /* Return the segment pointer, if any */
  return 0;
}

/* Closes all the libraries opened by LibrarySetup() */
static void CloseLibraries(void)
{
  if(LocaleBase)
  {
    if(Catalog)
      CloseCatalog(Catalog);
    CloseLibrary((struct Library *) LocaleBase);
  }
  if(GadToolsBase)
    CloseLibrary(GadToolsBase);
  if(UtilityBase)
    CloseLibrary((struct Library *) UtilityBase);
  if(IntuitionBase)
    CloseLibrary((struct Library *) IntuitionBase);
  if(DOSBase)
    CloseLibrary((struct Library *) DOSBase);
}

/* Initialize library */
ASM(struct Library *) LibInit(REG(a0, BPTR seglist),
REG(d0, struct Library * xpkLib))
{
  /* Remember the segment pointer */
  SegList = seglist;

  /* get required data */

  if((DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  {
    if((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37)))
    {
      if((UtilityBase = (struct UtilityBase *) OpenLibrary("utility.library", 37)))
      {
        if((GadToolsBase = OpenLibrary("gadtools.library", 37)))
        {
          if((LocaleBase = (struct LocaleBase *) OpenLibrary("locale.library", 38)))
          {
            if((Catalog = OpenCatalog(0, "xpkmaster.catalog",
            OC_Version, 2, TAG_DONE)))
            {
	      LocaleStrings(strings, LOCALE_STRINGSTART, LOCALE_STRINGCNT);
	      LocaleStrings(XpkErrs, LOCALE_ERRSTRINGSTART, LOCALE_ERRSTRINGCNT);
	    }
          }
          return (XpkBase = xpkLib);
        }
      }
    }
    CloseLibraries();
  }

  /*
  FreeMem((STRPTR) xpkLib - xpkLib->lib_NegSize, xpkLib->lib_NegSize +
  xpkLib->lib_PosSize);
  */

  return 0;
}

static void LocaleStrings(STRPTR * string, ULONG start, ULONG count)
{
  while(count--)
  {
    *string = GetCatalogStr(Catalog, start++, *string);
    ++string;
  }
}

/************************************************************************/

/* This is the table of functions that make up the library. The first
   four are mandatory, everything following it are user callable
   routines. The table is terminated by the value -1. */

static const APTR LibVectors[20] = {
  LibOpen,
  LibClose,
  LibExpunge,
  LibReserved,
  LibReserved,
  LIBXpkExamine,
  LIBXpkPack,
  LIBXpkUnpack,
  LIBXpkOpen,
  LIBXpkRead,
  LIBXpkWrite,
  LIBXpkSeek,
  LIBXpkClose,
  LIBXpkQuery,
  LIBXpkAllocObject,
  LIBXpkFreeObject,
  LIBXpkPrintFault,
  LIBXpkFault,
  LIBXpkPassRequest,
  (APTR)-1
};

static const struct LibInitData LibInitData = {
 0xA0, (UBYTE) OFFSET(Node,    ln_Type),      NT_LIBRARY,		 0,
 0x80, (UBYTE) OFFSET(Node,    ln_Name),      LIBNAME,
 0xA0, (UBYTE) OFFSET(Library, lib_Flags),    LIBF_SUMUSED|LIBF_CHANGED, 0,
 0x90, (UBYTE) OFFSET(Library, lib_Version),  VERSION,
 0x90, (UBYTE) OFFSET(Library, lib_Revision), REVISION,
 0x80, (UBYTE) OFFSET(Library, lib_IdString), IDSTRING,
 0
};

/* The following data structures and data are responsible for
   setting up the Library base data structure and the library
   function vector. */

static const ULONG LibInitTable[4] = {
  (ULONG)sizeof(struct Library), /* Size of the base data structure */
  (ULONG)LibVectors,             /* Points to the function vector */
  (ULONG)&LibInitData,           /* Library base data structure setup table */
  (ULONG)LibInit                 /* The address of the routine to do the setup */
};

/************************************************************************/

/* The library loader looks for this marker in the memory
   the library code and data will occupy. It is responsible
   setting up the Library base data structure.
*/

static const struct Resident RomTag = {
  RTC_MATCHWORD,                /* Marker value. */
  (struct Resident *)&RomTag,   /* This points back to itself. */
  (struct Resident *)&RomTag+1, /* This points behind this marker. */
  RTF_AUTOINIT,                 /* The Library should be set up according to the given table. */
  VERSION,                      /* The version of this Library. */
  NT_LIBRARY,                   /* This defines this module as a Library. */
  0,                            /* Initialization priority of this Library; unused. */
  LIBNAME,                      /* Points to the name of the Library. */
  IDSTRING,                     /* The identification string of this Library. */
  (APTR)&LibInitTable           /* This table is for initializing the Library. */
};

#endif /* XPKMASTER_LIBINIT_C */
