/*  :ts=8 bk=0
 *
 * iffparse.h:	Structure definitions for the all new good nifty IFF code.
 *
 * Stuart Ferguson (created)				8807.??
 * ewhac: Semantic changes				8808.15
 * shf:   Added rudimentary callback vectors and
 *	  read/write mode bits.  Added clipboard
 *	  functions and structures.			8808.31
 * shf:   Modified for revised design Oct 88.		8810.12
 * shf:   Updated to Dec 88 design revision.		8812.15
 * shf:   Added IFF_PRIVATE symbol for denoting private
 *	  data structures.				8902.07
 * ewhac: New InitIFF() declaration, and a change to
 *	  IFFM_MODE declaration.			8902.22
 * ewhac: Removed private parts.			8903.07
 * ewhac: Attempt at Lattice-ification and retrofit of
 *	  1.4 hooks.					8912.06
 * ewhac: Re-commenting.				9005.31
 * ewhac: {Entry,Exit}Handler() redesign.		9006.04
 */
#ifndef IFF_IFFPARSE_H
#define IFF_IFFPARSE_H

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif
#ifndef DEVICES_CLIPBOARD_H
#include <devices/clipboard.h>
#endif

/*
 * Struct associated with an active IFF stream.
 * "iff_Stream" is a value used by the client's read/write/seek functions -
 * it will not be accessed by the library itself and can have any value
 * (could even be a pointer or a BPTR).
 */
struct IFFHandle {
	ULONG	iff_Stream;
	ULONG	iff_Flags;
	LONG	iff_Depth;	/*  Depth of context stack.  */
	/*  There are private fields hiding here.  */
};

/*
 * Bit masks for "iff_Flags" field.
 */
#define IFFF_READ	0L			/* read mode - default */
#define IFFF_WRITE	1L			/* write mode */
#define IFFF_RWBITS	(IFFF_READ | IFFF_WRITE)	/* read/write bits */
#define IFFF_FSEEK	(1L<<1)			/* forward seek only */
#define IFFF_RSEEK	(1L<<2)			/* random seek */
#define	IFFF_RESERVED	0xFFFF0000L		/* Don't touch these bits. */

/*
 * When the library calls your stream handler, you'll be passed a pointer
 * to this structure as the "message packet".
 */
struct IFFStreamCmd {
	LONG	sc_Command;	/*  Operation to be performed (IFFCMD_)	*/
	APTR	sc_Buf;		/*  Pointer to data buffer		*/
	LONG	sc_NBytes;	/*  Number of bytes to be affected	*/
};

/*
 * A node associated with a context on the iff_Stack.  Each node
 * represents a chunk, the stack representing the current nesting 
 * of chunks in the open IFF file.  Each context node has associated
 * local context items in the (private) LocalItems list.  The ID, type,
 * size and scan values describe the chunk associated with this node.
 */
struct ContextNode {
	struct MinNode	cn_Node;
	LONG		cn_ID;
	LONG		cn_Type;
	LONG		cn_Size;	/*  Size of this chunk		   */
	LONG		cn_Scan;	/*  # of bytes read/written so far */
	/*  There are private fields hiding here.  */
};

/*
 * Local context items live in the ContextNode's.  Each class is identified
 * by its lci_Ident code and has a (private) purge vector for when the
 * parent context node is popped.
 */
struct LocalContextItem {
	struct MinNode	lci_Node;
	ULONG		lci_ID,
			lci_Type,
			lci_Ident;
	/*  There are private fields hiding here.  */
};

/*
 * StoredProperty: a local context item containing the data stored
 * from a previously encountered property chunk.
 */
struct StoredProperty {
	LONG	sp_Size;
	UBYTE	*sp_Data;
};

/*
 * Collection Item: the actual node in the collection list at which
 * client will look.  The next pointers cross context boundaries so
 * that the complete list is accessable.
 */
struct CollectionItem {
	struct CollectionItem	*ci_Next;
	LONG			ci_Size;
	UBYTE			*ci_Data;
};

/*
 * Structure returned by OpenClipboard().  You may do CMD_POSTs and such
 * using this structure.  However, once you call OpenIFF(), you may not
 * do any more of your own I/O to the clipboard until you call CloseIFF().
 */
struct ClipboardHandle {
	struct IOClipReq	cbh_Req;
	struct MsgPort		cbh_CBport;
	struct MsgPort		cbh_SatisfyPort;
};

/*
 * IFF return codes.  Most functions return either zero for success or
 * one of these codes.  The exceptions are the read/write functions which
 * return positive values for number of bytes or records read or written,
 * or a negative error code.  Some of these codes are not errors per sae,
 * but valid conditions such as EOF or EOC (End of Chunk).
 */
#define	IFFERR_EOF		-1L	/*  Reached logical end of file	*/
#define IFFERR_EOC		-2L	/*  About to leave context	*/
#define	IFFERR_NOSCOPE		-3L	/*  No valid scope for property	*/
#define	IFFERR_NOMEM		-4L	/*  Internal memory alloc failed*/
#define	IFFERR_READ		-5L	/*  Stream read error		*/
#define	IFFERR_WRITE		-6L	/*  Stream write error		*/
#define	IFFERR_SEEK		-7L	/*  Stream seek error		*/
#define	IFFERR_MANGLED		-8L	/*  Data in file is corrupt	*/
#define	IFFERR_SYNTAX		-9L	/*  IFF syntax error		*/
#define	IFFERR_NOTIFF		-10L	/*  Not an IFF file		*/
#define	IFFERR_NOHOOK		-11L	/*  No call-back hook provided	*/
#define IFF_RETURN2CLIENT	-12L	/*  Client handler normal return*/

#define	MAKE_ID(a,b,c,d)	((a<<24L) | (b<<16L) | (c<<8L) | d)

/*
 * Universal IFF identifiers.
 */
#define	ID_FORM			MAKE_ID('F','O','R','M')
#define	ID_LIST			MAKE_ID('L','I','S','T')
#define	ID_CAT			MAKE_ID('C','A','T',' ')
#define	ID_PROP			MAKE_ID('P','R','O','P')
#define	ID_NULL			MAKE_ID(' ',' ',' ',' ')

/*
 * Ident codes for universally recognized local context items.
 */
#define IFFLCI_PROP		MAKE_ID('p','r','o','p')
#define IFFLCI_COLLECTION	MAKE_ID('c','o','l','l')
#define IFFLCI_ENTRYHANDLER	MAKE_ID('e','n','h','d')
#define IFFLCI_EXITHANDLER	MAKE_ID('e','x','h','d')

/*
 * Control modes for ParseIFF() function.
 */
#define IFFPARSE_SCAN		0L
#define IFFPARSE_STEP		1L
#define IFFPARSE_RAWSTEP	2L

/*
 * Control modes for StoreLocalItem().
 */
#define IFFSLI_ROOT		1L	/*  Store in default context	   */
#define IFFSLI_TOP		2L	/*  Store in current context	   */
#define IFFSLI_PROP		3L	/*  Store in topmost FORM or LIST  */

/*
 * "Flag" for writing functions.  If you pass this value in as a size
 * to PushChunk() when writing a file, the parser will figure out the
 * size of the chunk for you.  (Chunk sizes >= 2**31 are forbidden by the
 * IFF specification, so this works.)
 */
#define	IFFSIZE_UNKNOWN		-1L

/*
 * Possible call-back command values.
 */
enum IFFCmdCode {
	IFFCMD_INIT,		/*  Prepare your stream for a session	*/
	IFFCMD_CLEANUP,		/*  Terminate stream session		*/
	IFFCMD_READ,		/*  Read bytes from stream		*/
	IFFCMD_WRITE,		/*  Write bytes to stream		*/
	IFFCMD_SEEK,		/*  Seek on stream			*/
	IFFCMD_ENTRY,		/*  You just entered a new context	*/
	IFFCMD_EXIT,		/*  You're about to leave a context	*/
	IFFCMD_PURGELCI		/*  Purge a LocalContextItem		*/
};
/*  Backward compatibility.  Don't use these in new code.  */
#define	IFFSCC_INIT	IFFCMD_INIT
#define	IFFSCC_CLEANUP	IFFCMD_CLEANUP
#define	IFFSCC_READ	IFFCMD_READ
#define	IFFSCC_WRITE	IFFCMD_WRITE
#define	IFFSCC_SEEK	IFFCMD_SEEK

#endif
