/* mylib.c	-- exec library routines for mylib 	*/

#include <exec/lists.h>
#include <exec/resident.h>
#include <graphics/text.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include "undefs.h"
#include "handleiff.h"

void myInit(void);
long myOpen(long d);
long myClose(long d);
long myExpunge(long d);

#pragma amicall(IFFParseBase, 0x06, myOpen(d0))
#pragma amicall(IFFParseBase, 0x0c, myClose(d0))
#pragma amicall(IFFParseBase, 0x12, myExpunge(d0))

/* The actual library. */
struct IFFParseBase {
    struct Library Lib;
    ULONG   SegList;
};

/* library initialization table, used for AUTOINIT libraries			*/
struct InitTable {
	unsigned long	it_DataSize;		  /* library data space size		*/
	void			**it_FuncTable;		  /* table of entry points			*/
	void 			*it_DataInit;		  /* table of data initializers		*/
	void			(*it_InitFunc)(void); /* initialization function to run	*/
};

void *libfunctab[] = {	/* my function table */
	myOpen,					/* standard open	*/
	myClose,				/* standard close	*/
	myExpunge,				/* standard expunge	*/
	0,

/*------ Basic functions ------*/
    AllocIFF, 
    OpenIFF, 
    ParseIFF, 
    CloseIFF, 
    FreeIFF, 
/*------ Read/Write functions ------*/
    ReadChunkBytes, 
    WriteChunkBytes, 
    ReadChunkRecords, 
    WriteChunkRecords, 
/*------ Context entry/exit ------*/
    PushChunk, 
    PopChunk, 
    Reserved, /*--- (1 function slot reserved here) ---*/
/*------ Low-level handler installation ------*/
    EntryHandler, 
    ExitHandler, 
/*------ Built-in chunk/property handlers ------*/
    PropChunk, 
    PropChunks, 
    StopChunk, 
    StopChunks, 
    CollectionChunk, 
    CollectionChunks, 
    StopOnExit, 
/*------ Context utilities ------*/
    FindProp, 
    FindCollection, 
    FindPropContext, 
    CurrentChunk, 
    ParentChunk, 
/*------ LocalContextItem support functions ------*/
    AllocLocalItem, 
    LocalItemData, 
    SetLocalItemPurge, 
    FreeLocalItem, 
    FindLocalItem, 
    StoreLocalItem, 
    StoreItemInContext, 
/*------ IFFHandle initialization ------*/
    InitIFF, 
    InitIFFasDOS, 
    InitIFFasClip, 
/*------ Internal clipboard support ------*/
    OpenClipboard, 
    CloseClipboard, 
/*------ Miscellaneous ------*/
    GoodID, 
    GoodType, 
    IDtoStr, 
                        
	(void *)-1				/* end of function vector table */
};

struct InitTable myInitTab =  {
	sizeof (struct IFFParseBase),
	libfunctab,
	0,						/* will initialize my data in funkymain()	*/
	myInit
};

#define MYREVISION	40		/* would be nice to auto-increment this		*/

char myname[] = "iffparse.library";
char myid[] = "Subset of the iffparse.library - By Michael Jansson\r\n";

extern struct Resident	myRomTag;


long
_main(struct IFFParseBase *IFFParseBase, unsigned long seglist)
{
	IFFParseBase->SegList = seglist;

    geta4();
    TraceCall;
	/* ----- init. library structure  -----		*/
	IFFParseBase->Lib.lib_Node.ln_Type = NT_LIBRARY;
	IFFParseBase->Lib.lib_Node.ln_Name = (char *) myname;	
	IFFParseBase->Lib.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
	IFFParseBase->Lib.lib_Version = myRomTag.rt_Version;
	IFFParseBase->Lib.lib_Revision = MYREVISION;
	IFFParseBase->Lib.lib_IdString = (APTR) myid;

    TraceCall;
    return 1L;
}

#ifdef SAFE_OPEN

struct TextAttr safeFont = {
    (UBYTE *)"topaz.font", 
    9,
    FS_NORMAL, 
    FPF_ROMFONT
};

struct IntuiText Body = {
    -1, -1, 
    JAM1, 
    36, 16, 
    NULL, 
    (UBYTE *)"Use Small-IFFParse.library?",
    NULL
};

struct IntuiText Positive = {
    -1, -1,
    0, 
    7, 4, 
    NULL, 
    (UBYTE *)"Do it!", 
    NULL
};

struct IntuiText Negative = {
    -1, -1, 
    JAM1, 
    7, 4, 
    &safeFont, 
    (UBYTE *)"Oh no!",
    NULL
};

IBase *IntuitionBase;
#endif

long
myOpen(long d)
{
	struct IFFParseBase *IFFParseBase;

    geta4();
    TraceCall;
#ifdef SAFE_OPEN
	long response = TRUE;

    /* Open some other libraries. */
    if ((IntuitionBase=(IBase *)OpenLibrary("intuition.library",0L))==NULL) {
        return 0L;
    }
    response = AutoRequest(NULL, 
                           &Body, &Positive, &Negative,
                           VANILLAKEY, 0UL, 
                           320L, 80L);
    CloseLibrary(IntuitionBase);
    if (response==FALSE)
        return 0L;
#endif

	/* mark us as having another customer					*/
	IFFParseBase->Lib.lib_OpenCnt++;

	/* prevent delayed expunges (standard procedure)		*/
	IFFParseBase->Lib.lib_Flags &= ~LIBF_DELEXP;

    TraceCall;
	return ((long) IFFParseBase);
}

long
myClose(long d)
{
	struct IFFParseBase *IFFParseBase;
	long retval = 0;


    geta4();
    TraceCall;
	if (--IFFParseBase->Lib.lib_OpenCnt == 0) {

		if  (IFFParseBase->Lib.lib_Flags & LIBF_DELEXP) {
			/* no more people have me open,
			 * and I have a delayed expunge pending
			 */
			retval = myExpunge(0); /* return segment list	*/
		}
	}

    TraceCall;
	return (retval);
}

long
myExpunge(long d)
{
	struct IFFParseBase *IFFParseBase;
	unsigned long seglist = 0;
	long libsize;
	extern struct Library *DOSBase;

    geta4();
    TraceCall;
	if (IFFParseBase->Lib.lib_OpenCnt == 0) {
		/* really expunge: remove libbase and freemem	*/

		seglist	= IFFParseBase->SegList;

		Remove(&IFFParseBase->Lib.lib_Node);
								/* i'm no longer an installed library	*/

		libsize = IFFParseBase->Lib.lib_NegSize+IFFParseBase->Lib.lib_PosSize;
		FreeMem((char *)IFFParseBase-IFFParseBase->Lib.lib_NegSize, libsize);
		CloseLibrary(DOSBase);		/* keep the counts even */

	}
	else
		IFFParseBase->Lib.lib_Flags |= LIBF_DELEXP;

	/* return NULL or real seglist				*/
    TraceCall;
	return ((long) seglist);
}
