/* RndPat.c
 *
 * Random Workbench background picture selector.
 *
 * Public domain in 1996-97 by Magnus Holmgren.
 */

#include "RndPat.h"


/* ----- Useful macros ---------------------------------------------------- */


#define MIN(a,b)	( ( a ) < ( b ) ? ( a ) : ( b ) )

/* Hm.. Not the best macro perhaps, but... ;) */
#define IFF(x)	if( ( rc = x ) < 0 ) { return( rc ); }


/* ----- Global variables ------------------------------------------------- */


struct Library		*IFFParseBase;

TEXT	ProgramName[] = "RndPat";


/* ----- Version string --------------------------------------------------- */


const STATIC TEXT Version[] = "$VER: RndPat 1.2 (14.12.97)";


/* ----- WBPattern prefs stuff -------------------------------------------- */


#define IFFERR_NOFILE	IFF_RETURN2CLIENT


/* Return error string based on input IFF error code. Assumes code to be
 * different from zero, and within range.
 */
STATIC const STRPTR
IffError( const LONG code )
{
	const STATIC STRPTR
	ErrorStrings[] =
	{
		"End of file",
		"End of chunk",
		"No valid scope for property",
		"Not enough memory",
		"Read error",
		"Write error",
		"Seek error",
		"Mangled file",
		"Syntax error",
		"Not an IFF file",
		"No hook provided",
		"Couldn't open file"
	}; /* ErrorStrings */

	return( ErrorStrings[ ~code ] );
} /* IffError */




/* Write the actual prefs data. Returns IFF error code */
STATIC LONG
WriteWBPatternPrefs( struct IFFHandle *iff, STRPTR *patterns, const BOOL remap )
{
	struct PrefHeader	header;
	struct WBPatternPrefs	prefs;
	LONG	rc, i;

	/* Clear prefs structs */
	memset( &header, 0, sizeof( header ) );
	memset( &prefs, 0, sizeof( prefs ) );

	if( remap )
	{
		prefs.wbp_Flags = WBPF_NOREMAP;
	} /* if */

	IFF( PushChunk( iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN ) );
	IFF( PushChunk( iff, ID_PREF, ID_PRHD, sizeof( header ) ) );
	IFF( WriteChunkBytes( iff, &header, sizeof( header ) ) );
	IFF( PopChunk( iff ) );

	for( i = WBP_ROOT; i <= WBP_SCREEN; ++i, ++patterns )
	{
		if( *patterns )
		{
			prefs.wbp_Which = i;
			prefs.wbp_DataLength = strlen( *patterns ) + 1;

			IFF( PushChunk( iff, ID_PREF, ID_PTRN, ( LONG ) ( sizeof( prefs ) + prefs.wbp_DataLength ) ) );
			IFF( WriteChunkBytes( iff, &prefs, sizeof( prefs ) ) );
			IFF( WriteChunkBytes( iff, *patterns, ( LONG ) prefs.wbp_DataLength ) );
			IFF( PopChunk( iff ) );
		} /* if */
	} /* for */

	return( PopChunk( iff ) );
} /* WriteWBPatternPrefs */


STATIC LONG
WritePrefs( const STRPTR file, const STRPTR *patterns, const BOOL remap )
{
	struct IFFHandle	*iff;
	LONG	rc = IFFERR_NOMEM;

	if( iff = AllocIFF() )
	{
		if( iff->iff_Stream = Open( file, MODE_NEWFILE ) )
		{
			InitIFFasDOS( iff );

			if( !( rc = OpenIFF( iff, IFFF_WRITE ) ) )
			{
				rc = WriteWBPatternPrefs( iff, patterns, remap );
				CloseIFF( iff );
			} /* if */

			if( !Close( iff->iff_Stream ) )
			{
				rc = IFFERR_WRITE;
			} /* if */
		}
		else
		{
			rc = IFFERR_NOFILE;
		} /* if */

		FreeIFF( iff );
	} /* if */

	return( rc );
} /* WritePrefs */


STATIC LONG
ShowWBPatternPrefs( struct IFFHandle *iff )
{
	struct CollectionItem	*ci = NULL;
	LONG	rc;

	/* Load and store all PTRN chunks */
	IFF( CollectionChunk( iff, ID_PREF, ID_PTRN ) );

	/* Stop before leaving PREF chunk, so we can process the stored PTRN chunks. */
	IFF( StopOnExit( iff, ID_PREF, ID_FORM ) );

	/* Read the stuff */
	rc = ParseIFF( iff, IFFPARSE_SCAN );

	if( rc == IFFERR_EOC )
	{
		/* Get the last loaded chunk */
		ci = FindCollection( iff, ID_PREF, ID_PTRN );
		rc = 0;
	} /* if */

	/* Process all chunks */
	while( ci )
	{
		const STATIC STRPTR
		Types[] =
		{
			"Workbench", "Window   ", "Screen   "
		}; /* Types[] */
		struct WBPatternPrefs	*chunk;
		STRPTR	type;

		chunk = ( struct WBPatternPrefs * ) ci->ci_Data;
		type = Types[ chunk->wbp_Which ];

		if( ci->ci_Size < sizeof( struct WBPatternPrefs ) )
		{
			Printf( "%s pattern chunk is too small (%ld bytes)\n", type, ci->ci_Size );
		}
		else if( chunk->wbp_Flags & WBPF_PATTERN )
		{
			Printf( "%s pattern is not a picture\n", type );
		}
		else if( !chunk->wbp_DataLength )
		{
			Printf( "%s picture: Empty name\n", type );
		}
		else
		{
			LONG	len;

			/* Make sure we only print the string... */
			len = strlen( ( STRPTR ) ( chunk + 1 ) );
			len = MIN( len, chunk->wbp_DataLength );

			/* Name data is stored after the WBPatternPrefs structure */
			Printf( "%s picture: ", type );
			FWrite( Output(), chunk + 1, len, 1 );
			PutStr( "\n" );
		} /* if */

		ci = ci->ci_Next;
	} /* while */

	return( rc );
} /* ShowWBPatternPrefs */


STATIC LONG
ShowPrefs( const STRPTR file )
{
	struct IFFHandle	*iff;
	LONG	rc = IFFERR_NOMEM;

	if( iff = AllocIFF() )
	{
		if( iff->iff_Stream = Open( file, MODE_OLDFILE ) )
		{
			InitIFFasDOS( iff );

			if( !( rc = OpenIFF( iff, IFFF_READ ) ) )
			{
				rc = ShowWBPatternPrefs( iff );
				CloseIFF( iff );
			} /* if */

			Close( iff->iff_Stream );
		}
		else
		{
			rc = IFFERR_NOFILE;
		} /* if */

		FreeIFF( iff );
	} /* if */

	return( rc );
} /* ShowPrefs */


/* ----- Main ------------------------------------------------------------- */


struct Args
{
	STRPTR	Workbench;
	STRPTR	Window;
	STRPTR	Screen;
	STRPTR	File;
	LONG	NoRemap;
	LONG	Show;
}; /* struct Args */

#define TEMPLATE	"WORKBENCH,WINDOW,SCREEN,FILE/K,NOREMAP/S,SHOW/S"


LONG
Main( VOID )
{
	struct RDArgs	*rda;
	struct Args	args;
	LONG	rc = RETURN_ERROR, err;

	memset( &args, 0, sizeof( args ) );
	args.File = "Env:sys/wbpattern.prefs";

	if( IFFParseBase = OpenLib( "iffparse.library", 39 ) )
	{
		if( rda = ReadArgs( TEMPLATE, ( LONG * ) &args, NULL ) )
		{
			if( args.Show )
			{
				if( err = ShowPrefs( args.File ) )
				{
					Printf( "%s: Couldn't show \"%s\":\n%s\n", ProgramName, args.File, IffError( err ) );
				}
				else
				{
					rc = RETURN_OK;
				} /* if */
			}
			else
			{
				InitSeed();
				SetIoErr( 0 );

				if( args.Screen || args.Workbench || args.Window )
				{
					STRPTR	patterns[ 3 ];

					patterns[ 0 ] = GetPattern( args.Workbench );
					patterns[ 1 ] = GetPattern( args.Window    );
					patterns[ 2 ] = GetPattern( args.Screen    );

					if( !IoErr() )
					{
						if( err = WritePrefs( args.File, patterns, ( BOOL ) args.NoRemap ) )
						{
							Printf( "%s: Couldn't create \"%s\":\n%s\n", ProgramName, args.File, IffError( err ) );
						}
						else
						{
							rc = RETURN_OK;
						} /* if */
					} /* if */

					FreeVec( patterns[ 0 ] );
					FreeVec( patterns[ 1 ] );
					FreeVec( patterns[ 2 ] );
				}
				else
				{
					Printf( "%s: No pattern(s) specified\n", ProgramName );
					rc = RETURN_WARN;
				} /* if */
			} /* if */

			FreeArgs( rda );
		}
		else
		{
			PrintfFault( IoErr(), "%s: Argument error", ProgramName );
		} /* if */

		CloseLib( IFFParseBase );
	} /* if */

	return( rc );
} /* Main */
