//-------------------------------------------------------------------------------
//
//	File:
//		BidFormat.h
//
//	Copyright 1993-1997, Adobe Systems Incorporated.
//	All Rights Reserved.
//
//	Description:
//		This file contains the header prototypes and macros for the
//		File Format module BidFormat, 
//		which writes a flat file with merged document pixels.
//
//	Use:
//		Format modules are called from the Save, Save as,
//		and Save a copy dialogs.
//
//	Version history:
//		Version 1.0.0	1/1/1993	Created for Photoshop 3.0.
//			Written by Mark Hamburg
//
//		Version 2.0.0	5/27/1996	Updated for Photoshop 4.0.
//			Scripting added.
//
//		Version 2.1.0	6/28/1997	Updated for Photoshop 4.0.1.
//			Updated for new version of Photoshop and projects
//			moved to CodeWarrior Pro.
//
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
//	Includes -- Use precompiled headers if compiling with CodeWarrior.
//-------------------------------------------------------------------------------

#include "PIDefines.h"

#ifdef __PIMWCWMacPPC__
	#include "BidFormat-PPC.ch"
#elif defined(__PIMWCWMac68K__)
	#include "BidFormat-68k.ch"
	// We're using Metrowerks and they have an A4 library, so set that up:
	#include <SetupA4.h>
	#include <A4Stuff.h>
	
	#define UseA4 // We've now defined this for quick checks later.
#else
	#include "BidFormat.h"
#endif


//-------------------------------------------------------------------------------
//	Prototypes
//-------------------------------------------------------------------------------

static void DoReadPrepare (GPtr globals);
static void DoReadStart (GPtr globals);
static void DoReadContinue (GPtr globals);
static void DoReadFinish (GPtr globals);
static void DoOptionsPrepare (GPtr globals);
static void DoOptionsStart (GPtr globals);
static void DoOptionsContinue (GPtr globals);
static void DoOptionsFinish (GPtr globals);
static void DoEstimatePrepare (GPtr globals);
static void DoEstimateStart (GPtr globals);
static void DoEstimateContinue (GPtr globals);
static void DoEstimateFinish (GPtr globals);
static void DoWritePrepare (GPtr globals);
static void DoWriteStart (GPtr globals);
static void DoWriteContinue (GPtr globals);
static void DoWriteFinish (GPtr globals);
static void DoFilterFile (GPtr globals);

static void AddComment (GPtr globals);
static void GetHistory (GPtr globals, int16 index, Str255 s);

static Boolean CheckIdentifier (char identifier []);
static void SetIdentifier (char identifier []);
static Boolean CheckForServices (GPtr globals);
static int32 RowBytes (GPtr globals);
static Boolean AllocatePixelBuffer (GPtr globals);
static void DisposePixelBuffer (GPtr globals);

static void ReadSome (GPtr globals, int32 count, void *buffer);
static void WriteSome (GPtr globals, int32 count, void *buffer);
static void ReadRow (GPtr globals);
static void WriteRow (GPtr globals);
static void DisposeImageResources (GPtr globals);

//-------------------------------------------------------------------------------
//	Globals -- Define global variables for plug-in scope.
//-------------------------------------------------------------------------------

// Windows global for plug-in (considered a Dynamically Linked Library).
// Leave NULL for Macintosh; many cross-platform library utilities require
// something passed in for hDllInstance:
Handle hDllInstance = NULL;

//-------------------------------------------------------------------------------
//
//	ENTRYPOINT / main
//
//	All calls to the plug-in module come through this routine.
//	It must be placed first in the resource.  To achieve this,
//	most development systems require this be the first routine
//	in the source.
//
//	The entrypoint will be "pascal void" for Macintosh,
//	"void" for Windows.
//
//	Inputs:
//		const short selector						Host provides selector indicating
//													what command to do.
//
//		FormatRecord *formatParamBlock				Host provides pointer to parameter
//													block containing pertinent data
//													and callbacks from the host.
//													See PIFormat.h.
//
//	Outputs:
//		FormatRecord *formatParamBlock				Host provides pointer to parameter
//													block containing pertinent data
//													and callbacks from the host.
//													See PIFormat.h.
//
//		long *data									Use this to store a handle to our
//													global parameters structure, which
//													is maintained by the host between
//													calls to the plug-in.
//
//		short *result								Return error result or noErr.  Some
//													errors are handled by the host, some
//													are silent, and some you must handle.
//													See PIGeneral.h.
//
//-------------------------------------------------------------------------------

MACPASCAL void ENTRYPOINT (const short selector,
						   FormatRecord *formatParamBlock,
						   long *data,
						   short *result)
{
	//---------------------------------------------------------------------------
	//	(1) Enter code resource if Mac 68k.
	//---------------------------------------------------------------------------
	
	#ifdef UseA4				// Are we in 68k Mac MW?
		EnterCodeResource(); 	// A4-globals
	#endif
	
	//---------------------------------------------------------------------------
	//	(2) Check for about box request.
	//
	// 	The about box is a special request; the parameter block is not filled
	// 	out, none of the callbacks or standard data is available.  Instead,
	// 	the parameter block points to an AboutRecord, which is used
	// 	on Windows.
	//---------------------------------------------------------------------------

	if (selector == formatSelectorAbout)
	{
		DoAbout((AboutRecordPtr)formatParamBlock);
	}
	else
	{ // do the rest of the process as normal:

		//-----------------------------------------------------------------------
		//	(3) Initialize function and global pointers.
		//
		// 	Initialize function pointer routine dispatcher. We use this to jump
		// 	to the different routines, instead of a long obnoxious switch
		// 	statement.  All routines are expected to have the same prototype
		// 	of "void RoutineName (globals)".  Returns any errors in gResult.
		//
		// 	WARNING: These better be in the order of the selector AND there
		// 	better be a routine for every selector call.
		//-----------------------------------------------------------------------
		
	 	static const FProc routineForSelector [] =
		{
			/* formatSelectorAbout  				DoAbout, */
			
			/* formatSelectorReadPrepare */		(FProc)DoReadPrepare,
			/* formatSelectorReadStart */		(FProc)	DoReadStart,
			/* formatSelectorReadContinue */	(FProc)	DoReadContinue,
			/* formatSelectorReadFinish */		(FProc)	DoReadFinish,
			
			/* formatSelectorOptionsPrepare */	(FProc)	DoOptionsPrepare,
			/* formatSelectorOptionsStart */	(FProc)	DoOptionsStart,
			/* formatSelectorOptionsContinue */	(FProc)	DoOptionsContinue,
			/* formatSelectorOptionsFinish */	(FProc)	DoOptionsFinish,
			
			/* formatSelectorEstimatePrepare */	(FProc)	DoEstimatePrepare,
			/* formatSelectorEstimateStart */	(FProc)	DoEstimateStart,
			/* formatSelectorEstimateContinue */(FProc)	DoEstimateContinue,
			/* formatSelectorEstimateFinish */	(FProc)	DoEstimateFinish,
			
			/* formatSelectorWritePrepare */	(FProc)	DoWritePrepare,
			/* formatSelectorWriteStart */		(FProc)	DoWriteStart,
			/* formatSelectorWriteContinue */	(FProc)	DoWriteContinue,
			/* formatSelectorWriteFinish */		(FProc)	DoWriteFinish,
			
			/* formatSelectorFilterFile */		(FProc)	DoFilterFile
		};
		
		Ptr globalPtr = NULL;		// Pointer for global structure
		GPtr globals = NULL; 		// actual globals

		//-----------------------------------------------------------------------
		//	(4) Allocate and initalize globals.
		//
		// 	AllocateGlobals requires the pointer to result, the pointer to the
		// 	parameter block, a pointer to the handle procs, the size of our local
		// 	"Globals" structure, a pointer to the long *data, a Function
		// 	Proc (FProc) to the InitGlobals routine.  It automatically sets-up,
		// 	initializes the globals (if necessary), results result to 0, and
		// 	returns with a valid pointer to the locked globals handle or NULL.
		//-----------------------------------------------------------------------
		
		globalPtr = AllocateGlobals ((uint32)result,
									 (uint32)formatParamBlock,
									 formatParamBlock->handleProcs,
									 sizeof(Globals),
						 			 data,
						 			 InitGlobals);
		
		if (globalPtr == NULL)
		{ // Something bad happened if we couldn't allocate our pointer.
		  // Fortunately, everything's already been cleaned up,
		  // so all we have to do is report an error.
		  
		  *result = memFullErr;
		  return;
		}
		
		// Get our "globals" variable assigned as a Global Pointer struct with the
		// data we've returned:
		globals = (GPtr)globalPtr;

		//-----------------------------------------------------------------------
		//	(5) Dispatch selector.
		//-----------------------------------------------------------------------

		if (selector > formatSelectorAbout && selector <= formatSelectorFilterFile)
			(routineForSelector[selector-1])(globals); // dispatch using jump table
		else
			gResult = formatBadParameters;
			
		//-----------------------------------------------------------------------
		//	(6) Unlock data, and exit resource.
		//
		//	Result is automatically returned in *result, which is
		//	pointed to by gResult.
		//-----------------------------------------------------------------------	
		
		// unlock handle pointing to parameter block and data so it can move
		// if memory gets shuffled:
		if ((Handle)*data != NULL)
			PIUnlockHandle((Handle)*data);
	
	} // about selector special		
	
	#ifdef UseA4			// Are we in 68k Mac MW?
		ExitCodeResource(); // A4-globals
	#endif
	
} // end ENTRYPOINT

//-------------------------------------------------------------------------------
//
//	InitGlobals
//	
//	Initalize any global values here.  Called only once when global
//	space is reserved for the first time.
//
//	Inputs:
//		Ptr globalPtr		Standard pointer to a global structure.
//
//	Outputs:
//		Initializes any global values with their defaults.
//
//-------------------------------------------------------------------------------

void InitGlobals (Ptr globalPtr)
{	
	// create "globals" as a our struct global pointer so that any
	// macros work:
	GPtr globals = (GPtr)globalPtr;
	
	// Initialize global variables:
	gQueryForParameters = true;
	ValidateParameters (globals);
	
} // end InitGlobals

//-------------------------------------------------------------------------------
//
//	ValidateParameters
//
//	Initialize parameters to default values.
//
//	Inputs:
//		GPtr globals		Pointer to global structure.
//
//	Outputs:
//		gWhatShape			Default: iShapeTriangle.
//
//		gCreate				Default: iCreateSelection.
//
//		gIdleAmount			Default: 2.0 seconds.
//
//-------------------------------------------------------------------------------

void ValidateParameters (GPtr globals)
{
	gPixelBuffer = NULL;
	gPixelData = NULL;
	
	gRowBytes = 0;
	
	gFooRead = false;
	gBarWrite = true;
	
	PIResetString(gHistory);

} // end ValidateParameters


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

static Boolean CheckIdentifier (char identifier [])
	{
	
	return identifier[0] == 'o' &&
		   identifier[1] == 'n' &&
		   identifier[2] == 'e' &&
		   identifier[3] == 'b' &&
		   identifier[4] == 'r' &&
		   identifier[5] == 'a' &&
		   identifier[6] == 'i' &&
		   identifier[7] == 'n';
	
	}

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

static void SetIdentifier (char identifier [])
	{
	
	identifier[0] = 'o';
    identifier[1] = 'n';
    identifier[2] = 'e';
    identifier[3] = 'b';
    identifier[4] = 'r';
    identifier[5] = 'a';
    identifier[6] = 'i';
    identifier[7] = 'n';
	
	}

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

static Boolean CheckForServices (GPtr globals)
	{
	
	return WarnBufferProcsAvailable () &&
		   WarnAdvanceStateAvailable () &&
		   WarnHandleProcsAvailable ();
	
	}

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

static int32 RowBytes (GPtr globals)
	{
	
	return (gStuff->imageSize.h * (int32) gStuff->depth + 7) >> 3;
	
	}

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

static Boolean AllocatePixelBuffer (GPtr globals)
	{
	
	BufferID buffer;
	
	if (gResult != noErr) return FALSE;

	/* We will want a buffer that is one line wide. */
	
	gPixelBuffer = 0;
	
	gRowBytes = RowBytes (globals);
	
	if (!TSR (AllocateBuffer (gRowBytes, &buffer))) return FALSE;
	
	gPixelBuffer = buffer;
	
	gPixelData = LockBuffer (gPixelBuffer, FALSE);
	
	return TRUE;
	
	}

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

static void DisposePixelBuffer (GPtr globals)
	{
	
	if (gPixelBuffer != 0)
		{
		
		FreeBuffer (gPixelBuffer);
		
		gPixelBuffer = 0;
		gPixelData = 0;
		
		}
	
	}

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

static void DoReadPrepare (GPtr globals)
	{
	
	gStuff->maxData = 0;
	
	}

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

static void ReadSome (GPtr globals, int32 count, void *buffer)
	{
	
	int32 readCount = count;
	
	if (gResult != noErr)
		return;
	
	gResult = FSRead (gStuff->dataFork, &readCount, buffer);
	
	if (gResult == noErr && readCount != count)
		gResult = eofErr;
	
	}

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

static void WriteSome (GPtr globals, int32 count, void *buffer)
	{
	
	int32 writeCount = count;
	
	if (gResult != noErr)
		return;
	
	gResult = FSWrite (gStuff->dataFork, &writeCount, buffer);
	
	if (gResult == noErr && writeCount != count)
		gResult = dskFulErr;
	
	}

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

static void ReadRow (GPtr globals)
	{
	
	ReadSome (globals, gRowBytes, gPixelData);
	
	}

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

static void WriteRow (GPtr globals)
	{

int32 i,r,g,b,a,pixs;
uint16 tbuf;
pixs=gStuff->imageSize.h;

switch(gStuff->planes)
{
case 3:
	{
/*
	r=((uint8 *)gPixelData)[0];
	g=((uint8 *)gPixelData)[1];
	b=((uint8 *)gPixelData)[2];
	tbuf=(uint16)(((r&0xF8)<<(10-3))|((g&0xF8)<<(5-3))|(b>>3));
	WriteSome (globals, 2, &tbuf);
*/
	for(i=0;i<pixs;i++)
	{
	r=((uint8 *)gPixelData)[i*3+0];
	g=((uint8 *)gPixelData)[i*3+1];
	b=((uint8 *)gPixelData)[i*3+2];
	tbuf=(uint16)(((r&0xF8)<<(10-3))|((g&0xF8)<<(5-3))|(b>>3));
	WriteSome (globals, 2, &tbuf);
	}

//	WriteSome (globals, 2, &tbuf);
	}
	break;
case 4:
	{
/*
	r=((uint8 *)gPixelData)[0];
	g=((uint8 *)gPixelData)[1];
	b=((uint8 *)gPixelData)[2];
	a=((uint8 *)gPixelData)[3];
	tbuf=(uint16)(((r&0xF0)<<(12-4))|((r&0xF0)<<(8-4))|(b&0xF0)|(a>>4));
	WriteSome (globals, 2, &tbuf);
*/
		
	for(i=0;i<pixs;i++)
	{
	r=((uint8 *)gPixelData)[i*4+0];
	g=((uint8 *)gPixelData)[i*4+1];
	b=((uint8 *)gPixelData)[i*4+2];
	a=((uint8 *)gPixelData)[i*4+3];
	tbuf=(uint16)(((r&0xF0)<<(12-4))|((r&0xF0)<<(8-4))|(b&0xF0)|(a>>4));
	WriteSome (globals, 2, &tbuf);
	}

//	WriteSome (globals, 2, &tbuf);
	}
	break;
default:
	{
//	WriteSome (globals, 1, gPixelData);
	
	WriteSome (globals, gRowBytes, gPixelData);
//	WriteSome (globals, 1, ((uint8 *)gPixelData)+(gStuff->imageSize.h-1));
	}
	break;

}
	
	
	}

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

static void DisposeImageResources (GPtr globals)
	{
	
	if (gStuff->imageRsrcData)
		{
		
		PIDisposeHandle (gStuff->imageRsrcData);
		
		gStuff->imageRsrcData = NULL;
		
		gStuff->imageRsrcSize = 0;
		
		}
	
	}

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

static void DoReadStart (GPtr globals)
	{
/*	
	FileHeader header;
	
	ReadScriptParamsOnRead (globals); // override params here
	
	// Exit if we have already encountered an error. 

    if (gResult != noErr) return;
		
	// Check for the needed services. 
	
	if (!TSC ((Boolean)(!CheckForServices (globals)))) return;

	//	 If we have not encountered an error, then we want to read the file header. 
	   
	if (!TSR (SetFPos (gStuff->dataFork, fsFromStart, 0))) return;
	
	ReadSome (globals, sizeof (FileHeader), &header);
	
	if (gResult != noErr) return;
	
	if (!CheckIdentifier (header.identifier))
		{
		gResult = formatCannotRead;
		return;
		}
	
	gStuff->imageMode = header.mode;
	gStuff->imageSize.v = header.rows;
	gStuff->imageSize.h = header.cols;
	gStuff->depth = header.depth;
	gStuff->planes = header.planes;
	
	// Next, we will try to read the image resources. 
	
	if (header.resourceLength > 0)
		{
		
		gStuff->imageRsrcData = PINewHandle (header.resourceLength);
		
		if (!gStuff->imageRsrcData)
			{
			gResult = memFullErr;
			return;
			}
			
		ReadSome (globals,
				  header.resourceLength,
				  PILockHandle (gStuff->imageRsrcData, FALSE));
		
		PIUnlockHandle (gStuff->imageRsrcData);
		
		if (gResult != noErr)
			goto CleanUp;
			
		gStuff->imageRsrcSize = header.resourceLength;
		
		}
		
	// Next, we will will read the lookup tables if in indexed color mode. 
	
	if (header.mode == plugInModeIndexedColor)
		{
		
		ReadSome (globals, 3 * sizeof (LookUpTable), &gStuff->redLUT);
		
		if (gResult != noErr)
			goto CleanUp;
		
		}
		
	return;
		
	// The following code does any clean-up work in the event of an error. 
	
	CleanUp:
	
	DisposeImageResources (globals);
*/        
	}

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

static void DoReadContinue (GPtr globals)
	{
/*	
	int32 done;
	int32 total;
	int16 plane;
	int16 row;
	
	// Dispose of the image resource data if it exists. 
	
	DisposeImageResources (globals);
	
	// Set up the progress variables. 
	
	done = 0;
	total = gStuff->imageSize.v * (long) gStuff->planes;
		
	// Next, we will allocate the pixel buffer. 
	
	AllocatePixelBuffer (globals);
	
	// Set up to start returning chunks of data. 
	
	gStuff->theRect.left = 0;
	gStuff->theRect.right = gStuff->imageSize.h;
	gStuff->colBytes = 1;
	gStuff->rowBytes = gRowBytes;
	gStuff->planeBytes = 0;
	gStuff->data = gPixelData;
	
	for (plane = 0; gResult == noErr && plane < gStuff->planes; ++plane)
		{
		
		gStuff->loPlane = gStuff->hiPlane = plane;
		
		for (row = 0; gResult == noErr && row < gStuff->imageSize.v; ++row)
			{
			
			gStuff->theRect.top = row;
			gStuff->theRect.bottom = row + 1;
			
			ReadRow (globals);
			
			if (gResult == noErr)
				gResult = AdvanceState ();
				
			UpdateProgress (++done, total);
			
			}
		
		}
		
	gStuff->data = NULL;
	
	DisposePixelBuffer (globals);
*/	
	}

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

static void DoReadFinish (GPtr globals)
	{
	/*
	// Dispose of the image resource data if it exists. 
	
	DisposeImageResources (globals);
	WriteScriptParamsOnRead (globals); // should be different for read/write
	AddComment (globals); // write a history comment
*/
	}

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

static void DoOptionsPrepare (GPtr globals)
	{

	gStuff->maxData = 0;

	}

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

static void DoOptionsStart (GPtr globals)
	{

	// Check for the needed services. 
	
	if (!TSC ((Boolean)(!CheckForServices (globals)))) return;

	gStuff->data = NULL;

	}

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

static void DoOptionsContinue (GPtr globals)
{
	#ifdef __PIMWCW__
		#pragma unused (globals) // remove this when you write this routine
	#endif
}

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

static void DoOptionsFinish (GPtr globals)
{
	#ifdef __PIMWCW__
		#pragma unused (globals) // remove this when you write this routine
	#endif
}

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

static void DoEstimatePrepare (GPtr globals)
{
	gStuff->maxData = 0;

}

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

static void DoEstimateStart (GPtr globals)
{
	
	int32 dataBytes;
	
	// Check for the needed services. 
	
	if (!TSC ((Boolean)(!CheckForServices (globals)))) return;

	if(gStuff->planes==3 || gStuff->planes==4)
	dataBytes = 2 * (gStuff->imageSize.v+2) * (gStuff->imageSize.h+2);
	else
	dataBytes =  (gStuff->imageSize.v+2) * (gStuff->imageSize.h+2);
/*					  
	if (gStuff->imageMode == plugInModeIndexedColor)
		dataBytes += 3 * sizeof (LookUpTable);
*/		
	gStuff->minDataBytes = dataBytes;
	gStuff->maxDataBytes = dataBytes;
	
	gStuff->data = NULL;

}

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

static void DoEstimateContinue (GPtr globals)
{
	#ifdef __PIMWCW__
		#pragma unused (globals) // remove this when you write this routine
	#endif
}

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

static void DoEstimateFinish (GPtr globals)
{
	#ifdef __PIMWCW__
		#pragma unused (globals) // remove this when you write this routine
	#endif
}

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

static void DoWritePrepare (GPtr globals)
{
	gStuff->maxData = 0;	
}

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

static void DoWriteStart (GPtr globals)
{

//	FileHeader header;
	int32 done;
	int32 total;
//	int16 plane;
	int16 row;
	
	ReadScriptParamsOnWrite (globals); // read script params here
	
    if (gResult != noErr) return;
		
	// Check for the needed services. 
	
	if (!TSC ((Boolean)(!CheckForServices (globals)))) return;

	// Write the header. 
	
	gResult = SetFPos (gStuff->dataFork, fsFromStart, 0);
	
//	SetIdentifier (header.identifier);
/*
	header.mode = gStuff->imageMode;
	header.rows = gStuff->imageSize.v;
	header.cols = gStuff->imageSize.h;
	header.depth = gStuff->depth;
	header.planes = gStuff->planes;
	if (gStuff->imageRsrcData)
		header.resourceLength = gStuff->imageRsrcSize;
	else
		header.resourceLength = 0;
		
//	WriteSome (globals, sizeof (FileHeader), &header);
	
	if (gResult != noErr) return;
*/	
	
	// Write the image resources if any. 
/*	
	if (header.resourceLength > 0)
		{
		
		WriteSome (globals,
				   header.resourceLength,
				   PILockHandle (gStuff->imageRsrcData, FALSE));
		
		PIUnlockHandle (gStuff->imageRsrcData);
		
		if (gResult != noErr) return;
		
		}
*/		
	// Write the lookup tables if appropriate. 
/*	
	if (header.mode == plugInModeIndexedColor)
		{
		
		WriteSome (globals, 3 * sizeof (LookUpTable), &gStuff->redLUT);
		
		if (gResult != noErr) return;
		
		}
*/		
	// Set up the progress variables. 
	
	done = 0;
//	total = header.rows * (long) header.planes;
	total = gStuff->imageSize.v;
		
	// Next, we will allocate the pixel buffer. 
	
	 	
	// Set up to start receiving chunks of data. 
	
		gStuff->theRect.left = 0;
		gStuff->theRect.right = gStuff->imageSize.h;
		gStuff->loPlane = 0;
		gStuff->hiPlane = gStuff->planes-1;
		gStuff->colBytes =gStuff->planes;
		gStuff->rowBytes = gStuff->imageSize.h*gStuff->planes;
		gStuff->planeBytes = 1;
		gStuff->data = gPixelData;

		AllocatePixelBuffer (globals);
/*		
			gStuff->theRect.top = 0;
			gStuff->theRect.bottom =1;

			if (gResult == noErr)
				gResult = AdvanceState ();
				
			WriteRow (globals);
			
			UpdateProgress (++done, total);
*/
		for (row = 0; gResult == noErr && row < gStuff->imageSize.v; ++row)
			{
			
			gStuff->theRect.top = row;
			gStuff->theRect.bottom = row + 1;
			
			if (gResult == noErr)
				gResult = AdvanceState ();
				
			WriteRow (globals);
			
			UpdateProgress (++done, total);
			
			}
	/*	
			gStuff->theRect.top = gStuff->imageSize.v-1;
			gStuff->theRect.bottom =gStuff->imageSize.v;

			if (gResult == noErr)
				gResult = AdvanceState ();
				
			WriteRow (globals);
			
			UpdateProgress (++done, total);
	*/	
		
	gStuff->data = NULL;
	
	DisposePixelBuffer (globals);
	
}

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

static void DoWriteContinue (GPtr globals)
{
	#ifdef __PIMWCW__
		#pragma unused (globals) // remove this when you write this routine
	#endif
}

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

static void DoWriteFinish (GPtr globals)
{
	WriteScriptParamsOnWrite (globals); // should be different for read/write
}

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

static void DoFilterFile (GPtr globals)
{
/*	 
	FileHeader header;
	
	// Exit if we have already encountered an error. 

    if (gResult != noErr) return;
		
	// Read the file header. 
	   
	if (!TSR (SetFPos (gStuff->dataFork, fsFromStart, 0))) return;
	
	ReadSome (globals, sizeof (FileHeader), &header);
	
	if (gResult != noErr) return;
	
	// Check the identifier. 
	
	if (!CheckIdentifier (header.identifier))
		{
		gResult = formatCannotRead;
		return;
		}
*/	
}

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

/* This routine adds a history entry to the file when incoming. */

static void AddComment (GPtr globals)
{
/*	
	// We will attempt to add a resource showing that we made this change. 
	
	Str255 s, s0;
	Handle h;
	
	if (!ResourceProcsAvailable (NULL))
		return;
		
	PIGetString(kHistoryEntry, s);
	// Pulls a pascal string from the resource tree.
	
	NumToString(gStuff->dataFork, s0);
	// Need some unique data for this entry
	
	PIParamText(s, s0, NULL, NULL);

	h = PIPString2Handle(s);
		
	if (h != NULL)
	{
		PILockHandle(h, FALSE);
		(void) AddPIResource (histResource, h);
		PIUnlockHandle(h);
		PIDisposeHandle(h);
		h = NULL;
	}
	
	if (gHistory[0] > 0)
	{ // we had an old history.  Write that back out, as well.
		h = PIPString2Handle(gHistory);
		
		if (h != NULL)
		{ // got our handle. Write it out.
			gHistory[ (gHistory[0]=0)+1 ] = 0; // clear string
			PILockHandle(h, FALSE);
			(void) AddPIResource (histResource, h);
			PIUnlockHandle(h);
			PIDisposeHandle(h);
			h = NULL;
		}
	} // no earlier history
*/
} // end AddComment

/**************************************************************************/
// Returns a history entry in a string

static void GetHistory (GPtr globals, int16 index, Str255 s)
{	
	int16 currentResources = CountPIResources(histResource);
	
	PIResetString(s);
	
	if (currentResources >= index)
	{
		Handle h = GetPIResource (histResource, index);	
		if (h != NULL) PIHandle2PString(h, s);
		// just a read-only reference.  Do NOT dispose.
	}
}

