/**************************************************************************
 *			MAND8.C - Read Dragon (Get Picture)
 *	     	      Mandelbrot Self-Squared Dragon Generator
 *			     For the Commodore Amiga
 *				  Version 2.05
 *
 *		       Copyright (C) 1986, Scott D. Ballantyne
 *			      Placed in the Public Domain
 *
 *	This program may be distributed free of charge as long as the above
 *	notice is retained.  You may extract any or all information contained
 *	in this file for use in your own programs
 *
 **************************************************************************/

#include "mand.h"

extern struct GfxBase		*GfxBase;
extern struct IntuitionBase 	*IntuitionBase;

extern struct RastPort		*rp;
extern struct ViewPort		*vp;

extern struct Window		*w, *ColorWindow;
extern struct Screen		*screen;
extern struct IntuiMessage	*message;

extern SHORT			last_color;
extern BOOL			SettingCenter, SettingBoxSize;

extern FLOAT	start_r, end_r, start_i, end_i;
extern int	max_x, max_y;
extern int	max_count, color_inc, color_offset;
extern int	color_set, color_mode, color_div;
extern int	color_inset, func_num;
extern UWORD	*color_table;
extern FILE	*console, *redir_fp;

extern SHORT			ZoomCenterX, ZoomCenterY, ZoomBoxSizeX, ZoomBoxSizeY;
extern SHORT			ZoomBoxStartX, ZoomBoxStartY;
extern BOOL			Resume;
extern SHORT			y_coord;
extern struct NewScreen		ns;
extern struct NewWindow 	nw;

extern LONG			*PictModes, *PictBody, *MandelHeader;
extern struct PaintingHeader	PaintingHeader;
extern struct Menu		MainMenu[MENU_COUNT];
extern struct MenuItem		OptionsItems[OPTIONS_COUNT];

BOOL ReadPicture(filename)
char *filename;
{
	REGISTER SHORT		i;
	REGISTER ULONG		length, file, bytes_read;
	ULONG			junk;
	UBYTE			*p, component[3];
	USHORT			rgb[32];
	BOOL			read = FALSE;
	BOOL			ReadBody(), ReadSpecialInfo();

	Resume = FALSE;

	if ( !(file = Open(filename, MODE_OLDFILE)) )
		goto ERROR;
	length = sizeof(struct PaintingHeader);
	
	if (Read(file, &PaintingHeader, length) != length)
		goto READ_ERROR;
	bytes_read = length - 8;

	/* I am really only interested in files generated by this program,
	 * or by earlier versions of this program. 
	 * So that is all I check for. This comment is posted as a warning
	 * to any innocent traveler that might wish to use this portion
	 * as an example of a generalized FORM ILBM reader.
	 * Please don't.
	 */
	if (	IFF_ID  != FORM || ILBM_ID != ILBM ||
		BMHD_ID != BMHD || CMAP_ID != CMAP )
	 		goto READ_ERROR;

	/* Check for valid compression type */
	if ( COMPRESSION != 0 && COMPRESSION != 1)
	  	goto READ_ERROR;	/* Unknown Compression Type */

	nw.Width = ns.Width = PAGE_WIDTH;
	nw.Height = ns.Height = PAGE_HEIGHT;
	ns.Depth = N_PLANES;

	/* Now read in some data - first the color map */

	length = ( 1 << N_PLANES);
	if (length > 32)	/* Clip to 32 colors */
		length = 32;

	for (i = 0; i < length; i++) /* Get the colormap */
	{
		if (Read(file, &component[0], 3L) != 3)
			goto READ_ERROR;
		bytes_read += 3;
		rgb[i] = ( component[0] << 4
			 | component[1] 
			 | component[2] >> 4 );
	}

	while (bytes_read < FILE_LENGTH)
	{

		if (Read(file, &junk, 4L) != 4)
			goto READ_ERROR;
		bytes_read += 4;
		switch (junk)
		{
			case CAMG:
				if (Seek(file, 4L, OFFSET_CURRENT) < 0)
					goto READ_ERROR;
				if (Read(file, &junk, 4L) != 4)
					goto READ_ERROR;
				ns.ViewModes = junk;
				bytes_read += 8;
				break;
			case BODY:
/* The nicest way to do this is to read the planes into a separate bitmap,
 * and then blast it into the rastport with the blitter.
 * Unfortunately, there isn't really enough room for that on even a 512k
 * box (640x400 mode takes a *lot* of memory), so we open the window, send
 * it to the back, read in the map, and then bring it to the front.
 * "Yesterday is a memory"
 * "Tomorrow is a dream"
 * "Today's a bitch"
 */
				if (!(screen = OpenScreen(&ns)) )
					goto READ_ERROR;
				ShowTitle(screen, 0L);
				nw.Screen = screen;
				if (!(w = OpenWindow(&nw)) )
					goto READ_ERROR;
				vp = &screen->ViewPort;
				rp = w->RPort;
				ScreenToBack(screen);
				LoadRGB4(vp, rgb, (LONG)i);
				if (Read(file, &junk, 4L) != 4)
					goto READ_ERROR;
				bytes_read += 4;
				if (!ReadBody(file, &screen->BitMap))
					goto READ_ERROR;
				bytes_read += junk;
				break;
			case MNDL:
				if (Read(file, &junk, 4L) != 4)
					goto READ_ERROR;
				junk += 4;
				bytes_read += junk;
				if (!ReadSpecialInfo(file))
					goto READ_ERROR;
				break;
			default:
				goto READ_ERROR;
		}

	}
	/* Restore the menu links, just in case.... */
	MainMenu[MENU_OPTIONS].NextMenu = &MainMenu[MENU_ZOOM];
	MainMenu[MENU_OPTIONS].FirstItem = &OptionsItems[0];
	SetMenuStrip(w, &MainMenu[0]);
	ScreenToFront(screen);
	read = TRUE;
READ_ERROR:
	Close(file);
ERROR:
	if (NOT read)
	{
		if (w)
		{
			CloseWindow(w);
			w = NULL;
		}
		if (screen)
		{
			CloseScreen(screen);
			screen = NULL;
		}
		fprintf(console, "***Could not read your file!***\n");
		DisplayBeep(NULL);
	}
	return(read);
}

BOOL ReadBody(file, bitmap)
ULONG file;
struct BitMap *bitmap;
{
	REGISTER WORD	i, j;
	WORD		offset = 0;
	REGISTER BYTE	*dest;
	BYTE		value;
	REGISTER LONG	count = 0;
	REGISTER WORD	bytes;
	ULONG		bytes_read = 0;

	switch(COMPRESSION)
	{
	    case 0:
		for (j = 0; j < ROWS; j++)
		{
		    for (i = 0; i < DEPTH; i++)
		    {
			if (Read(file, Plane(i) + offset, (LONG)BPR) != BPR)
				return(FALSE);
		    }
		    offset += BPR;
		}
		return(TRUE);
	    case 1:
		
		for (j = 0; j < ROWS; j++)
		{
			for (i = 0; i < DEPTH; i++)
			{
				bytes = BPR;
				dest = (BYTE *)(Plane( i ) + offset);
				while (bytes > 0)
				{
					if (Read(file, &value, 1L) != 1)
						return(FALSE);
					bytes_read++;
					if (value == 128)
						continue;
					if (value > 0)
					{
						count = value + 1;
						bytes -= count;
						if (Read(file, dest, count) != count)
							return(FALSE);
						dest += count;
						bytes_read += count;
					}
					else
					{
						count = -value + 1;
						bytes -= count;
						if (Read(file, &value, 1L) != 1)
							return(FALSE);
						bytes_read++;
						while (--count >= 0)
						{
							*dest++ = value;
						}
					}
				}
				if (bytes != 0)
					return(FALSE);
			}
			offset += BPR;
		}
		/* if bytes_read is odd, then gobble the pad byte */
		if ( bytes_read & 1)
			if (Read(file, &value, 1L) != 1)
				return(FALSE);
		return(TRUE);
	    default:
	    	return(FALSE);
	}
}


BOOL ReadSpecialInfo(file)
ULONG file;
{
	struct MandelInfo	mi;
	ULONG			length;

	length = sizeof(struct MandelInfo);

	if (Read(file, &mi, length) != length)
		return(FALSE);

	start_r	= mi.mi_start_r;
	end_r	= mi.mi_end_r;
	start_i	= mi.mi_start_i;
	end_i	= mi.mi_end_i;
	max_x	= mi.mi_max_x;
	max_y	= mi.mi_max_y;
	max_count = mi.mi_max_count;
	color_inc = mi.mi_color_inc;
	color_offset = mi.mi_color_offset;
	color_set = mi.mi_color_set;
	color_mode = mi.mi_color_mode;
	color_div = mi.mi_color_div;
	color_inset = mi.mi_color_inset;
	func_num = mi.mi_func_num;
	y_coord = mi.mi_starty;
	Resume = TRUE;
	return (TRUE);
}

