/*  :ts=8 bk=0
 *
 * tiff.c:	ILBM scanner utilizing builtin chunk handlers (PropChunk(),
 *		StopChunk(), CollectionChunk(), StopOnExit()).
 *
 * All the code needed for an ILBM reader, except the stuff to process the
 * ILBM itself.
 *
 * Stuart Ferguson (Created)				8807.??
 * ewhac: Adjusted for new semantics			8808.16
 * ewhac: Adjustments; added "Not an ILBM" feature.	8811.02
 * shf:   Updated to Dec 88 design revision		8812.15
 * ewhac: Updated to 1.4 Beta				8912.06
 * ewhac: Latticeification				9005.30
 */
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include "iffparse_protos.h"
#include "iffparse.p"

#define	ID_ILBM	MAKE_ID('I','L','B','M')
#define	ID_BODY	MAKE_ID('B','O','D','Y')
#define	ID_BMHD	MAKE_ID('B','M','H','D')
#define	ID_CMAP	MAKE_ID('C','M','A','P')
#define	ID_CAMG	MAKE_ID('C','A','M','G')
#define	ID_CRNG	MAKE_ID('C','R','N','G')


/*
 * Forward function declarations.  (I hate ANSI.)
 */
void ProcessCrng (struct IFFHandle *);
void ProcessBody (struct IFFHandle *);


static long	ilbmprops[] = {
	ID_ILBM, ID_BMHD,
	ID_ILBM, ID_CMAP,
	ID_ILBM, ID_CAMG
};

struct Library	*IFFParseBase;


main (argc, argv)
int	argc;
char	**argv;
{
	struct IFFHandle	*iff;
	struct ContextNode	*cn;
	long			error;
	char			foundbody = 0;

	if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L))) {
		puts ("Cannot open library.");
		goto die;
	}

	/*
	 * Create IFF file and open a DOS stream on it.
	 */
	if (!(iff = AllocIFF())) {
		puts ("AllocIFF() failed.");
		goto die;
	}

	if (!(iff -> iff_Stream = Open (argv[1], MODE_OLDFILE))) {
		puts ("File open failed.");
		goto die;
	}
	InitIFFasDOS (iff);

	/*
	 * Declare property, collection and stop chunks.
	 */
	if (error = PropChunks (iff, ilbmprops, 3L))
		goto err;
	if (error = StopChunk (iff, ID_ILBM, ID_BODY))
		goto err;
	if (error = CollectionChunk (iff, ID_ILBM, ID_CRNG))
		goto err;

	/*
	 * We want to stop at the end of an ILBM context.
	 */
	if (error = StopOnExit (iff, ID_ILBM, ID_FORM))
		goto err;

	if (error = OpenIFF (iff, IFFF_READ))
		goto err;

	/*
	 * Take first parse step to enter main chunk.
	 */
	if (error = ParseIFF (iff, IFFPARSE_STEP))
		goto err;

	/*
	 * Test the chunk info to see if this is a simple ILBM.
	 */
	if (!(cn = CurrentChunk (iff))) {
		puts ("No top chunk!");
		goto die;
	}
	if (cn -> cn_ID != ID_FORM  ||  cn -> cn_Type != ID_ILBM)
		puts ("Not a FORM ILBM.  Blundering on anyway...");

	while (!error) {
		/*
		 * ParseIFF() will return on BODY chunk or end of
		 * context for an ILBM FORM.
		 */
		error = ParseIFF (iff, IFFPARSE_SCAN);

		/*
		 * Test for end of context condition and process
		 * collected CRNG chunks here.
		 */
		if (error == IFFERR_EOC) {
			ProcessCrng (iff);
			/* error = 0;
			   continue;
			 */
			break;
		}

		/*
		 * Other values for error are real errors.
		 */
		if (error)
			break;

		ProcessBody (iff);
		foundbody = 1;
	}
err:
	if (error == IFFERR_EOC) {
		if (foundbody)
			puts ("File scan complete.");
		else
			puts ("Failed to find an ILBM BODY chunk.");
	} else if (error == IFFERR_EOF)
		puts ("Failed to find a FORM ILBM.");
	else
		printf ("File scan aborted (%ld)\n", error);

die:
	if (iff) {
		CloseIFF (iff);
		if (iff -> iff_Stream)
			Close (iff -> iff_Stream);
		FreeIFF (iff);
	}

	if (IFFParseBase)	CloseLibrary (IFFParseBase);
}


void
ProcessBody (iff)
struct IFFHandle *iff;
{
	register struct StoredProperty	*sp;

	if (sp = FindProp (iff, ID_ILBM, ID_BMHD))
		printf ("BMHD chunk, size: %ld\n", sp -> sp_Size);
	else
		puts ("No BMHD chunk.");

	if (sp = FindProp (iff, ID_ILBM, ID_CMAP))
		printf ("CMAP chunk, size: %ld\n", sp -> sp_Size);
	else
		puts ("No CMAP chunk.");

	if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
		printf ("CAMG chunk, size: %ld\n", sp -> sp_Size);
	else
		puts ("No CAMG chunk.");

	printf ("BODY chunk, size: %ld\n", CurrentChunk (iff) -> cn_Size);
}


void
ProcessCrng (iff)
struct IFFHandle *iff;
{
	register struct CollectionItem	*ci;

	ci = FindCollection (iff, ID_ILBM, ID_CRNG);
	if (!ci) {
		puts ("No CRNG chunks.");
		return;
	}

	for ( ;  ci;  ci = ci->ci_Next) {
		printf ("CRNG chunk, size: %ld\n", ci -> ci_Size);
	}
}

/*
 * Disable Lattice's default ^C trap.
 */
chkabort ()
{
	return (0);
}

CXBRK ()
{
	return (0);
}
