/*
**	IFF.c
**
**	Interchange file format I/O support routines
**
**	Copyright © 1990-1997 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

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

	/* CloseIFFClip(struct IFFHandle *Handle):
	 *
	 *	Closes the clipboard opened by OpenIFFClip.
	 */

BOOL
CloseIFFClip(struct IFFHandle *Handle)
{
	if(Handle != NULL)
	{
		CloseIFF(Handle);
		CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);

		FreeIFF(Handle);
	}

	return(TRUE);
}

	/* OpenIFFClip(LONG Unit,LONG Mode):
	 *
	 *	Open the clipboard for reading or writing. This
	 *	routine handles all the initizalizations and
	 *	allocation and returns an IFFHandle ready
	 *	to be used.
	 */

struct IFFHandle *
OpenIFFClip(
	LONG Unit,
	LONG Mode)
{
	struct IFFHandle *Handle;
	LONG Error;

	ASSERT(Mode == MODE_NEWFILE || Mode == MODE_OLDFILE);

	Handle = AllocIFF();
	if(Handle != NULL)
	{
		Handle->iff_Stream = (ULONG)OpenClipboard(Unit);
		if(Handle->iff_Stream != NULL)
		{
			LONG type;

			InitIFFasClip(Handle);

			if(Mode == MODE_NEWFILE)
				type = IFFF_WRITE;
			else
				type = IFFF_READ;

			Error = OpenIFF(Handle,type);
			if(Error != OK)
				CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
		}
		else
		{
			Error = ERROR_NO_FREE_STORE;
		}

		if(Error != OK)
		{
			FreeIFF(Handle);
			Handle = NULL;
		}
	}
	else
	{
		Error = ERROR_NO_FREE_STORE;
	}

	if(Error != OK)
		SetIoErr(Error);

	return(Handle);
}

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

	/* CloseIFFStream(struct IFFHandle *Handle):
	 *
	 *	Closes an IFF file opened by OpenIFFStream.
	 */

BOOL
CloseIFFStream(struct IFFHandle *Handle)
{
	BOOL Result;

	if(Handle != NULL)
	{
		CloseIFF(Handle);
		Result = Close((BPTR)Handle->iff_Stream);

		FreeIFF(Handle);
	}
	else
	{
		Result = TRUE;
	}

	return(Result);
}

	/* OpenIFFStream(STRPTR Name,LONG Mode):
	 *
	 *	Open an IFF file for reading or writing. This
	 *	routine handles all the initizalizations and
	 *	allocation and returns an IFFHandle ready
	 *	to be used.
	 */

struct IFFHandle *
OpenIFFStream(
	const STRPTR	Name,
	LONG			Mode)
{
	struct IFFHandle *Handle;
	LONG Error;

	ASSERT(Name != NULL && (Mode == MODE_NEWFILE || Mode == MODE_OLDFILE));

	Handle = AllocIFF();
	if(Handle != NULL)
	{
		Handle->iff_Stream = (ULONG)Open((STRPTR)Name,Mode);
		if(Handle->iff_Stream != NULL)
		{
			LONG type;

			InitIFFasDOS(Handle);

			if(Mode == MODE_NEWFILE)
				type = IFFF_WRITE;
			else
				type = IFFF_READ;

			Error = OpenIFF(Handle,type);
			if(Error != OK)
			{
				Close((BPTR)Handle->iff_Stream);

				if(Mode == MODE_NEWFILE)
					DeleteFile((STRPTR)Name);
			}
		}
		else
		{
			Error = IoErr();
		}

		if(Error != OK)
		{
			FreeIFF(Handle);
			Handle = NULL;
		}
	}
	else
	{
		Error = ERROR_NO_FREE_STORE;
	}

	if(Error != OK)
		SetIoErr(Error);

	return(Handle);
}

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

BOOL
ReadIFFBytes(
	struct IFFHandle *	handle,
	APTR				buffer,
	LONG				numBytes)
{
	BOOL result;
	LONG total;

	ASSERT(handle != NULL && buffer != NULL && numBytes > 0);

	total = ReadChunkBytes(handle,buffer,numBytes);
	if(total < 0)
	{
		SetIoErr(total);
		result = FALSE;
	}
	else
	{
		result = TRUE;
	}

	return(result);
}

BOOL
ReadIFFRecords(
	struct IFFHandle *	handle,
	APTR				buffer,
	LONG				bytesPerRecord,
	LONG				numRecords)
{
	BOOL result;
	LONG total;

	ASSERT(handle != NULL && buffer != NULL && bytesPerRecord > 0 && numRecords > 0);

	total = ReadChunkRecords(handle,buffer,bytesPerRecord,numRecords);
	if(total < 0)
	{
		SetIoErr(total);
		result = FALSE;
	}
	else
	{
		result = TRUE;
	}

	return(result);
}

BOOL
WriteIFFBytes(
	struct IFFHandle *	handle,
	const APTR			buffer,
	LONG				numBytes)
{
	BOOL result;
	LONG total;

	ASSERT(handle != NULL && buffer != NULL && numBytes > 0);

	total = WriteChunkBytes(handle,(APTR)buffer,numBytes);
	if(total < 0)
	{
		SetIoErr(total);
		result = FALSE;
	}
	else
	{
		result = TRUE;
	}

	return(result);
}

BOOL
WriteIFFRecords(
	struct IFFHandle *	handle,
	const APTR			buffer,
	LONG				bytesPerRecord,
	LONG				numRecords)
{
	BOOL result;
	LONG total;

	ASSERT(handle != NULL && buffer != NULL && bytesPerRecord > 0 && numRecords > 0);

	total = WriteChunkRecords(handle,(APTR)buffer,bytesPerRecord,numRecords);
	if(total < 0)
	{
		SetIoErr(total);
		result = FALSE;
	}
	else
	{
		result = TRUE;
	}

	return(result);
}

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

LONG
AddIFFChunkBytes(
	struct IFFHandle *	handle,
	LONG				chunkID,
	const APTR			buffer,
	LONG				numBytes)
{
	LONG status;

	ASSERT(handle != NULL && buffer != NULL && numBytes > 0);

	status = PushChunk(handle,0,chunkID,numBytes);
	if(status == OK)
	{
		LONG total;

		total = WriteChunkBytes(handle,(APTR)buffer,numBytes);
		if(total < 0)
			status = total;
	}

	if(status == OK)
		status = PopChunk(handle);

	return(status);
}
