/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by MXM
 *
 *	Name .....: PrintImage.c
 *	Created ..: Saturday 15-Sep-90 14:16
 *	Revision .: 1
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	15-Sep-90       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

	/* Remove this definition if you don't need it (see below). */

/*#define CITIZEN_SWIFT_24 1*/

	/* Prototypes for this module. */

VOID			CloseAll(BYTE ReturnCode);
VOID			OpenAll(VOID);
VOID			FreeImage(VOID);
BYTE			LoadImage(char *Name);
ULONG			FindChunk(ULONG ChunkName,FILE *FilePointer);
LONG			LoadHeader(char *FileName,BitMapHeader *BMHeader);
BYTE			LoadCMAP(char *FileName,BYTE Colours[32][3],LONG MaxCol,BitMapHeader *BMHeader);
BYTE			LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader);
VOID			main(VOID);

	/* Global and shared library identifiers. */

extern struct ExecBase	*SysBase;
struct IntuitionBase	*IntuitionBase;
struct GfxBase		*GfxBase;
struct ReqLib		*ReqBase;

	/* Window and process data. */

struct Window		*Window;
struct Process		*ThisProcess;

	/* Printer IO. */

struct MsgPort		*PrintPort;
struct IODRPReq		*PrintRequest;
struct IOStdReq		*PrintStdReq;

	/* File requester and associated data. */

struct FileRequester	 LoadFileReq;
char			 FileName[FCHARS],DirectoryName[DSIZE],Buffer[FCHARS + DSIZE + 2];

	/* Image data. */

struct BitMap		 ImageBitMap;
struct RastPort		 ImageRastPort;
struct ColorMap		*ImageColourMap;
BitMapHeader		 ImageBitMapHeader;
LONG			 ImageModes;
BYTE			 HasImage;

	/* Window data. */

struct IntuiMessage	*Massage;
ULONG			 Class;
USHORT			 Code;
BYTE			 GadgetID,i;

	/* The four gadgets. */

char *GadgetTexts[] =
{
	"Load new image",
	"Print current image",
	"Stop printing",
	"Exit program"
};

	/* Define the number of gadgets. */

#define NUMGADS	(sizeof(GadgetTexts) / sizeof(char *))

	/* Present a fitting number of gadget blocks. */

struct GadgetBlock GadgetBlocks[NUMGADS];

	/* A window definition. */

struct NewWindow NewWindow =
{
	0,0,
	0,0,
	0,1,
	CLOSEWINDOW | GADGETUP,
	WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | RMBTRAP | ACTIVATE,
	(struct Gadget *)NULL,
	(struct Image *)NULL,
	(STRPTR)"PrintImage",
	(struct Screen *)NULL,
	(struct BitMap *)NULL,
	~0,~0,
	~0,~0,
	WBENCHSCREEN
};

	/* A Zz... mouse pointer. */

USHORT ElecArtsWaitPointer[(22 + 2) * 2] =
{
	0x0000,0x0000,

	0x6700,0xC000,
	0xCFA0,0xC700,
	0xBFF0,0x0FA0,
	0x70F8,0x3FF0,
	0x7DFC,0x3FF8,
	0xFBFC,0x7FF8,
	0x70FC,0x3FF8,
	0x7FFE,0x3FFC,
	0x7F0E,0x3FFC,
	0x3FDF,0x1FFE,
	0x7FBE,0x3FFC,
	0x3F0E,0x1FFC,
	0x1FFC,0x07F8,
	0x07F8,0x01E0,
	0x01E0,0x0080,
	0x07C0,0x0340,
	0x0FE0,0x07C0,
	0x0740,0x0200,
	0x0000,0x0000,
	0x0070,0x0020,
	0x0078,0x0038,
	0x0038,0x0010,

	0x0000,0x0000
};

	/* A macro to attach the mouse pointer to a window. */

#define SetWait(Window) SetPointer(Window,ElecArtsWaitPointer,22,16,0,0)

	/* CloseAll():
	 *
	 *	Closes all resources and returns to the shell.
	 */

VOID
CloseAll(BYTE ReturnCode)
{
	ThisProcess -> pr_WindowPtr = NULL;

	PurgeFiles(&LoadFileReq);

	FreeImage();

	if(Window)
		CloseWindow(Window);

	if(PrintRequest)
	{
		if(PrintRequest -> io_Device)
		{
			/* The following code puts the Citicen Swift 24
			 * printer back into Epson emulation mode.
			 */

#ifdef	CITIZEN_SWIFT_24

			PrintStdReq -> io_Command	= PRD_RAWWRITE;
			PrintStdReq -> io_Data		= (APTR)"\33~5\0";
			PrintStdReq -> io_Length	= 4;
	
			DoIO(PrintStdReq);

#endif	/* CITIZEN_SWIFT_24 */

			CloseDevice(PrintRequest);
		}

		DeleteExtIO(PrintRequest);
	}

	if(PrintPort)
		DeletePort(PrintPort);

	if(ReqBase)
		CloseLibrary(ReqBase);

	exit(ReturnCode);
}

	/* OpenAll():
	 *
	 *	Open all resources to start the program.
	 */

VOID
OpenAll()
{
	SHORT	MaxWidth = 0,TempWidth;
	BYTE	i;

	ThisProcess = (struct Process *)SysBase -> ThisTask;

	if(!(ReqBase = (struct ReqLib *)OpenLibrary("req.library",0)))
		CloseAll(RETURN_FAIL + 1);

	IntuitionBase	= ReqBase -> IntuiLib;
	GfxBase		= ReqBase -> GfxLib;

	if(!(PrintPort = (struct MsgPort *)CreatePort(NULL,0)))
		CloseAll(RETURN_FAIL + 2);

	if(!(PrintRequest = (struct IODRPReq *)CreateExtIO(PrintPort,sizeof(struct IODRPReq))))
		CloseAll(RETURN_FAIL + 3);

	PrintStdReq = (struct IOStdReq *)PrintRequest;

	if(OpenDevice("printer.device",0,PrintRequest,NULL))
		CloseAll(RETURN_FAIL + 4);

		/* The following lines will put the Citizen Swift 24
		 * printer into NEC P6+ emulation mode. Since the
		 * Workbench EpsonQ printer driver only permits
		 * to print with a maximum resolution of 360×180 dpi
		 * this provides a convenient way to work with the
		 * Nec_Pinwriter driver without having to reselect
		 * the emulation manually.
		 */

#ifdef	CITIZEN_SWIFT_24

	PrintStdReq -> io_Command	= PRD_RAWWRITE;
	PrintStdReq -> io_Data		= (APTR)"\33~5\2";
	PrintStdReq -> io_Length	= 4;

	if(DoIO(PrintStdReq))
		CloseAll(RETURN_FAIL + 4);

#endif	/* CITIZEN_SWIFT_24 */

		/* The following piece of code adapts the
		 * window to the number and the dimensions of
		 * the gadgets.
		 */

	for(i = 0 ; i < NUMGADS ; i++)
	{
		if((TempWidth = 8 * strlen(GadgetTexts[i]) + 4) > MaxWidth)
			MaxWidth = TempWidth;
	}

	NewWindow . Width = MaxWidth + 8;

	for(i = 0 ; i < NUMGADS ; i++)
	{
		LinkGadget(&GadgetBlocks[i],GadgetTexts[i],&NewWindow,((NewWindow . Width - (8 * strlen(GadgetTexts[i]) + 4)) >> 1) + 2,13 + (5 + 8) * i);

		GadgetBlocks[i] . Gadget . GadgetID = i;
	}

	NewWindow . Height = 11 + ((5 + 8) * NUMGADS + 1);

	Center(&NewWindow,GadgetBlocks[0] . Gadget . LeftEdge + (GadgetBlocks[0] . Gadget . Width >> 1),GadgetBlocks[0] . Gadget . TopEdge + (GadgetBlocks[0] . Gadget . Height >> 1));

	if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
		CloseAll(RETURN_FAIL + 5);

	for(i = 1 ; i < NUMGADS - 1 ; i++)
		OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);

	LoadFileReq . PathName		= Buffer;
	LoadFileReq . Title		= GadgetTexts[0];
	LoadFileReq . dirnamescolor	= 3;
	LoadFileReq . devicenamescolor	= 3;
	LoadFileReq . Window		= Window;

	LoadFileReq . Dir		= DirectoryName;
	LoadFileReq . File		= FileName;
	LoadFileReq . Flags		= FRQCACHINGM | FRQINFOGADGETM | FRQNOHALFCACHEM | FRQLOADINGM;
	LoadFileReq . blockcolor	= 1;

	ThisProcess -> pr_WindowPtr = (APTR)Window;
}

	/* FreeImage():
	 *
	 *	Free the data associated with the image in memory.
	 */

VOID
FreeImage()
{
	if(ImageColourMap)
		FreeColorMap(ImageColourMap);

	if(ImageBitMap . Planes[0])
		FreeMem(ImageBitMap . Planes[0],ImageBitMap . Depth * ImageBitMap . BytesPerRow * ImageBitMap . Rows);

	HasImage = FALSE;
}

	/* PrintImage():
	 *
	 *	Print the image in memory according to the current
	 *	Preferences settings.
	 */

VOID
PrintImage()
{
	ULONG	SignalSet;
	SHORT	i;

		/* Standard system hardcopy. */

	PrintRequest -> io_Command	= PRD_DUMPRPORT;
	PrintRequest -> io_RastPort	= &ImageRastPort;
	PrintRequest -> io_ColorMap	= ImageColourMap;
	PrintRequest -> io_Modes	= ImageModes;
	PrintRequest -> io_SrcWidth	= ImageBitMapHeader . w;
	PrintRequest -> io_SrcHeight	= ImageBitMapHeader . h;
	PrintRequest -> io_SrcX		= 0;
	PrintRequest -> io_SrcY		= 0;
	PrintRequest -> io_DestCols	= ImageBitMapHeader . w;
	PrintRequest -> io_DestRows	= ImageBitMapHeader . h;
	PrintRequest -> io_Special	= SPECIAL_ASPECT | SPECIAL_TRUSTME;

		/* Block all gadgets save one. */

	for(i = 0 ; i < NUMGADS ; i++)
	{
		if(i != 2)
			OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
		else
			OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
	}

		/* Sleep... */

	SetWait(Window);

		/* ...and fire off the printer dump. */

	BeginIO(PrintRequest);

	FOREVER
	{
			/* Wait for 'stop' or printer to finish. */

		SignalSet = Wait((1 << PrintPort -> mp_SigBit) | (1 << Window -> UserPort -> mp_SigBit));

		if(SignalSet & (1 << PrintPort -> mp_SigBit))
		{
			while(GetMsg(PrintPort));

			break;
		}

		if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
		{
			while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
			{
				Class		= Massage -> Class;
				Code		= Massage -> Code;
				GadgetID	= ((struct Gadget *)Massage -> IAddress) -> GadgetID;

				ReplyMsg((struct Message *)Massage);

				if(Class == GADGETUP && GadgetID == 2)
				{
					AbortIO(PrintRequest);
					WaitIO(PrintRequest);

					goto Quit;
				}
			}
		}
	}

Quit:	ClearPointer(Window);

	for(i = 0 ; i < NUMGADS ; i++)
	{
		if(i != 2)
			OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
		else
			OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
	}
}

	/* LoadImage():
	 *
	 *	Loads an IFF-ILBM file and prepares it for the graphic
	 *	dump.
	 */

BYTE
LoadImage(char *Name)
{
	BYTE	Colours[32][3];
	ULONG	PageSize;
	BYTE	i,MaxCol;

		/* Load the view modes. */

	if((ImageModes = LoadHeader(Name,&ImageBitMapHeader)) != -1)
	{
			/* Load the colour table. */

		if(MaxCol = LoadCMAP(Name,Colours,32,&ImageBitMapHeader))
		{
				/* Initialize the bitmap. */

			InitBitMap(&ImageBitMap,ImageBitMapHeader . nPlanes,ImageBitMapHeader . w,ImageBitMapHeader . h);

				/* Don't forget the rastport. */

			InitRastPort(&ImageRastPort);

				/* Put the bitmap into the rastport. */

			ImageRastPort . BitMap = &ImageBitMap;

				/* Calculate the size of a single bitplane. */

			PageSize = ImageBitMap . BytesPerRow * ImageBitMap . Rows;

				/* Allocate space for the bitmap. */

			if(ImageBitMap . Planes[0] = AllocMem(PageSize * ImageBitMap . Depth,MEMF_CHIP | MEMF_CLEAR))
			{
					/* Set the bitplane pointers accordingly. */

				for(i = 1 ; i < ImageBitMapHeader . nPlanes ; i++)
					ImageBitMap . Planes[i] = (PLANEPTR)((ULONG)ImageBitMap . Planes[0] + PageSize * i);

					/* Allocate a colour map. */

				if(ImageColourMap = (struct ColorMap *)GetColorMap(MaxCol))
				{
						/* Set the image colours. */

					for(i = 0 ; i < MaxCol ; i++)
						SetRGB4CM(ImageColourMap,i,Colours[i][0],Colours[i][1],Colours[i][2]);

						/* Finally, load the bitmap itself. */

					if(LoadRaster(Name,ImageBitMap . Planes,&ImageBitMapHeader))
					{
						HasImage = TRUE;

						return(TRUE);
					}
				}
			}
		}
	}

	FreeImage();

	return(FALSE);
}

	/* FindChunk():
	 *
	 *	Find a chunk in a file and return its length.
	 */

ULONG
FindChunk(ULONG ChunkName,FILE *FilePointer)
{
	ULONG		OldPosition,FormType;
	IFF_Chunk	Chunk;

		/* Remember the initial file position. */

	OldPosition = ftell(FilePointer);

		/* Reset the form type. */

	FormType = 0;

	for(;;)
	{
			/* Try to read the chunk. */

		if(fread(&Chunk,sizeof(Chunk),1,FilePointer) != 1)
		{
				/* If it went wrong, reset the
				 * file position.
				 */

			fseek(FilePointer,OldPosition,0);
			return(0);
		}

			/* If this is supposed to be a FORM chunk,
			 * try to figure out the form type.
			 */

		if(OldPosition == 0 && FormType == 0 && Chunk . IFF_Type == 'FORM')
		{
			fread(&FormType,sizeof(LONG),1,FilePointer);

				/* Is it the type we want? */

			if(FormType == ChunkName)
				return(Chunk . IFF_Length);

			continue;
		}

			/* Is this what we want? */

		if(Chunk . IFF_Type == ChunkName)
			return(Chunk . IFF_Length);

			/* Else, skip the length information. */

		fseek(FilePointer,Chunk . IFF_Length,1);
	}
}

	/* LoadHeader():
	 *
	 *	Try to load a BitMapHeader from a file and return
	 *	the proper ViewModes.
	 */

LONG
LoadHeader(char *FileName,BitMapHeader *BMHeader)
{
	LONG	 ViewModes = -1;
	FILE	*ImageFile;

		/* No such file? */

	if(ImageFile = fopen(FileName,"rb"))
	{
			/* No BMHD-Chunk? */

		if(FindChunk('BMHD',ImageFile))
		{
				/* Read the header. */

			if(fread(BMHeader,sizeof(BitMapHeader),1,ImageFile))
			{

				/* Strange values, probably not a picture but a
				 * "mistake", or even a CMAP.
				 */

				if(BMHeader -> nPlanes && BMHeader -> nPlanes <= 8)
				{
					ViewModes = NULL;

					/* If we don't find a CAMG chunk in the file
					 * we will have to guess the right
					 * ViewModes. This line takes care of the
					 * interlaced display mode.
					 */

					if(BMHeader -> pageHeight > GfxBase -> NormalDisplayRows)
						ViewModes |= LACE;

					/* Could it be HIRES? */

					if(BMHeader -> pageWidth >= 640)
						ViewModes |= HIRES;

					/* It is still much more likely to encounter a
					 * HAM picture than an EHB picture. If we are
					 * wrong with this assumption, the CAMG chunk
					 * will tell us (hope so).
					 */

					if(BMHeader -> nPlanes == 6)
						ViewModes |= HAM;

					/* Hello out there, got any CAMG chunk? */

					if(FindChunk('CAMG',ImageFile))
					{
						/* Read it then. */

						if(fread(&ViewModes,sizeof(LONG),1,ImageFile) == 1)
						{
							/* Mask out all unwanted bits (thanks, Carolyn!). */

							ViewModes &= (~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO) | 0xFFFF);
						}
						else
							ViewModes = -1;
					}
				}
			}
		}

		fclose(ImageFile);
	}

		/* Finish it. */

	return(ViewModes);
}

	/* LoadCMAP():
	 *
	 *	Load a colour table from a file and return the number
	 *	of colours.
	 */

BYTE
LoadCMAP(char *FileName,BYTE Colours[32][3],LONG MaxCol,BitMapHeader *BMHeader)
{
	BYTE	 NumCols = 0;
	FILE	*ColFile;
	BYTE	 i;

		/* Are you there? */

	if(ColFile = fopen(FileName,"rb"))
	{
			/* Black 'n white or colour TV? */

		if(FindChunk('CMAP',ColFile))
		{
				/* Correct it before the reader believes it! */

			if(MaxCol < 2)
				MaxCol = 1 << BMHeader -> nPlanes;

				/* A bit too large, innit? */

			if(MaxCol > 32)
				MaxCol = 32;

				/* Read those colours. */

			if(fread(Colours,32 * 3,1,ColFile) == 1)
			{
				for(i = 0 ; i < MaxCol ; i++)
				{
					Colours[i][0] >>= 4;
					Colours[i][1] >>= 4;
					Colours[i][2] >>= 4;
				}

				NumCols = MaxCol;
			}
		}

			/* Finish it. */

		fclose(ColFile);
	}

	return(NumCols);
}

	/* LoadRaster():
	 *
	 *	Load the bitmap from a file and decompress it into the
	 *	supplied planes.
	 */

BYTE
LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader)
{
	UBYTE		 Value,SoFar,Compr,Depth;
	LONG		 Height,Width;
	PLANEPTR	 Planes[9];	/* 9 for possible bitmask. */
	FILE		*PicFile;
	BYTE		 ChkVal;
	LONG		 i,j,k;

	LONG		 AuxLength;
	BYTE		*AuxBuff2;
	BYTE		*AuxBuff;	/* Decompress in memory buffer. */

		/* Clear the planes. */

	for(i = 0 ; i < 9 ; i++)
		Planes[i] = NULL;

		/* Set up the working copies. */

	Width	= byte(BMHeader -> w);
	Height	= BMHeader -> h;
	Depth	= BMHeader -> nPlanes;
	Compr	= BMHeader -> compression;

		/* Is there something wrong in paradise? */

	if(Compr > 1 || !BitPlanes)
		return(FALSE);

		/* Can we read it, please? */

	if(!(PicFile = fopen(FileName,"rb")))
		return(FALSE);

		/* No BODY? What is this? */

	if(!(AuxLength = FindChunk('BODY',PicFile)))
	{
		fclose(PicFile);
		return(FALSE);
	}

		/* Copy the bitmap pointers since their
		 * contents will get changed.
		 */

	for(i = 0 ; i < Depth ; i++)
		Planes[i] = BitPlanes[i];

		/* Very well, nobody told me that DPaint and Aegis Images
		 * are allowed to save their own home-brewn BODY chunks
		 * if the transparent colour is nonzero or the
		 * stencil/behind function is used. In this case the
		 * interleaved plane data is immediately followed by
		 * a bitmask which is to clear all unwanted pixels
		 * after the image is drawn. To support this feature
		 * we increment the depth of the image to give the
		 * reader access to a blank pointer the bitmask will
		 * be sent to.
		 */

	if(BMHeader -> masking == 1)
		Depth++;

		/* If we can allocate the memory buffer, we will
		 * decompress the image in memory rather than
		 * while reading it from disk.
		 */

	if(AuxBuff = (BYTE *)AllocMem(AuxLength,MEMF_PUBLIC))
	{
			/* Read the data. */

		fread(AuxBuff,AuxLength,1,PicFile);

			/* Remember the buffer address. */

		AuxBuff2 = AuxBuff;

			/* No compression? */

		if(Compr == 0)
		{
			for(k = 0 ; k < Height ; k++)
			{
				for(j = 0 ; j < Depth ; j++)
				{
					if(Planes[j])
					{
						CopyMem(AuxBuff,Planes[j],Width);
						Planes[j] += Width;
					}

					AuxBuff += Width;
				}
			}
		}

			/* ByteRun compression? */

		if(Compr == 1)
		{
			for(k = 0 ; k < Height ; k++)
			{
				for(j = 0 ; j < Depth ; j++)
				{
					for(SoFar = 0 ; SoFar < Width ; )
					{
						ChkVal = *AuxBuff;
						AuxBuff++;

						if(ChkVal > 0)
						{
							if(Planes[j])
							{
								CopyMem(AuxBuff,Planes[j],ChkVal + 1);

								Planes[j] += ChkVal + 1;
							}

							AuxBuff += ChkVal + 1;

							SoFar += ChkVal + 1;
						}
						else
						{
							if(ChkVal != -128)
							{
								Value = *AuxBuff;
								AuxBuff++;

								for(i = 0 ; i <= -ChkVal ; i++)
								{
									if(Planes[j])
										*Planes[j]++ = Value;

									SoFar++;
								}
							}
						}
					}
				}
			}
		}

			/* Free the auxilary buffer. */

		FreeMem(AuxBuff2,AuxLength);

		goto Quit;
	}
		/* No compression, take the data as is. */

	if(Compr == 0)
	{
		for(k = 0 ; k < Height ; k++)
		{
			for(j = 0 ; j < Depth ; j++)
			{
				if(Planes[j])
				{
					fread(Planes[j],Width,1,PicFile);
					Planes[j] += Width;
				}
				else
					fseek(PicFile,Width,1);
			}
		}
	}

		/* ByteRun1 compression. */

	if(Compr == 1)
	{
		for(k = 0 ; k < Height ; k++)
		{
			for(j = 0 ; j < Depth ; j++)
			{
				for(SoFar = 0 ; SoFar < Width ; )
				{
					ChkVal = fgetc(PicFile);

						/* Read the next bytes. */

					if(ChkVal > 0)
					{
						if(Planes[j])
						{
							fread(Planes[j],ChkVal + 1,1,PicFile);

							Planes[j] += ChkVal + 1;
						}
						else
							fseek(PicFile,ChkVal + 1,1);

						SoFar += ChkVal + 1;
					}
					else
					{
							/* Set the memory to this
							 * value.
							 */

						if(ChkVal != -128)
						{
							Value = fgetc(PicFile);

							for(i = 0 ; i <= -ChkVal ; i++)
							{
								if(Planes[j])
									*Planes[j]++ = Value;

								SoFar++;
							}
						}
					}
				}
			}
		}
	}

		/* Finish it up. */

Quit:	fclose(PicFile);

	return(TRUE);
}

	/* Stub routines. */

VOID _cli_parse() {}
VOID _wb_parse() {}

	/* main():
	 *
	 *	The real main program.
	 */

VOID
main()
{
	BYTE i;

		/* Open all resources. */

	OpenAll();

		/* Go into neverending loop. */

	FOREVER
	{
		WaitPort(Window -> UserPort);

			/* Pick up all the messages. */

		while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
		{
			Class		= Massage -> Class;
			Code		= Massage -> Code;
			GadgetID	= ((struct Gadget *)Massage -> IAddress) -> GadgetID;

			ReplyMsg((struct Message *)Massage);

				/* Close the window? */

			if(Class == CLOSEWINDOW)
				CloseAll(RETURN_OK);

				/* Hit a gadget. */

			if(Class == GADGETUP)
			{
				switch(GadgetID)
				{
						/* Load a new image? */

					case 0:	if(HasImage)
							FreeImage();

						if(FileRequester(&LoadFileReq))
						{
							SetWait(Window);

							if(LoadImage(Buffer))
							{
								for(i = 1 ; i < NUMGADS - 1 ; i++)
								{
									if(i != 2)
										OnGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
									else
										OffGadget(&GadgetBlocks[i] . Gadget,Window,NULL);
								}
							}
							else
								SimpleRequest("Couldn't load file \"%s\"!",Buffer);

							ClearPointer(Window);
						}

						break;

						/* Print the image? */

					case 1:	if(HasImage)
							PrintImage();

						break;

						/* Stop printing (ignore)? */

					case 2:	break;

						/* Exit the program? */

					case 3:	CloseAll(RETURN_OK);
				}
			}
		}
	}
}
