/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by MXM
 *
 *	Name .....: FontConvert.c
 *	Created ..: Tuesday 25-Sep-90 20:43
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	25-Sep-90       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

	/* Global and shared library identifiers. */

extern struct ExecBase	*SysBase;
struct ReqLib		*ReqBase;
struct IntuitionBase	*IntuitionBase;
struct GfxBase		*GfxBase;
struct Library		*DiskfontBase;
struct Library		*LayersBase;

	/* Process and associated data. */

struct Process		*ThisProcess;
APTR			 SavePtr;

	/* Data associated with the font conversion. */

struct TextFont		*DiskFont;
struct BitMap		 RasterBitMap;
struct RastPort		 RasterPort;

struct BitMap		 TextBitMap;
struct Layer_Info	*TextLayerInfo;
struct Layer		*TextLayer;

	/* Global output file. */

BPTR			 GlobalOut;

	/* Window data. */

struct Window		*Window;
struct RastPort		*RPort;
struct IntuiMessage	*Massage;
ULONG			 Class,Code,GadgetID;

	/* The font requester. */

struct FileRequester	 FontFileReq;
char			 FontName[FCHARS],DirectoryName[DSIZE],Buffer[FCHARS + DSIZE + 2];

	/* Printer IO data. */

struct IOStdReq		*PrintRequest;
struct MsgPort		*PrintPort;

	/* Capture file requester. */

struct FileRequester	 CaptureFileReq;
char			 CaptureName[FCHARS],CaptureDirName[DSIZE],CaptureBuffer[FCHARS + DSIZE + 2];

	/* Seven select buttons. */

struct TwoImageGadget	 Buttons[7];

	/* At lease one of these bytes is set TRUE if the character
	 * is contained in the font set.
	 */

BYTE FontFlag[256];

	/* Which character belongs to a printer character (dreaded
	 * IBM font).
	 */

UBYTE CharTable[217] =
{
	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
	 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
	 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,  0,
	199,252,233,226,228,231,229,  0,234,235,232,239,238,236,196,197,
	201,230,198,244,246,242,251,249,255,214,220,162,163,165,  0,  0,
	225,237,243,250,241,209,170,186,191,  0,172,189,188,161,171,187,
	  0,127,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,223,  0,  0,  0,  0,181,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,176
};

	/* Select button image data. */

USHORT ButtonData[32] =
{
	0xFFFE,0xC006,0xC006,0xC006,0xC006,0xC006,0xFFFE,0x0000,
	0xFFFE,0xC006,0xC006,0xC006,0xC006,0xC006,0xFFFE,0x0000,

	0xFFFE,0xC006,0xCFE6,0xCFE6,0xCFE6,0xC006,0xFFFE,0x0000,
	0xFFFE,0xC006,0xCFE6,0xCFE6,0xCFE6,0xC006,0xFFFE,0x0000
};

	/* The texts for the seven buttons. */

char *ButtonText[7] =
{
	"Make the font underlined",
	"Make the font bold",
	"Make the font italicized",
	"Convert 256 characters",
	"Capture to file",
	"Send font to printer",
	"Start Conversion"
};

	/* An empty disk attribute. */

struct TextAttr DiskAttribute =
{
	(STRPTR)NULL,
	8,
	FS_NORMAL,
	FPF_DISKFONT
};

	/* Our window. */

struct NewWindow NewWindow =
{
	0,11,
	224,88,
	-1,-1,
	CLOSEWINDOW | GADGETUP | MOUSEBUTTONS,
	ACTIVATE | RMBTRAP | WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE,
	(struct Gadget *)NULL,
	(struct Image *)NULL,
	(STRPTR)"FontConvert 1.0",
	(struct Screen *)NULL,
	(struct BitMap *)NULL,
	~0,~0,
	~0,~0,
	WBENCHSCREEN
};

	/* The wait 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
};

	/* Use this macro to attach the sprite pointer to the
	 * window.
	 */

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

	/* Calculate the amount of bytes needed to represent a single
	 * display line.
	 */

#define byte(Width) (((Width + 15) >> 4) << 1)

	/* CloseAll():
	 *
	 *	Closes devices and libraries and locks the shop.
	 */

VOID
CloseAll(BYTE ReturnCode)
{
	if(PrintRequest)
	{
		if(PrintRequest -> io_Device)
			CloseDevice(PrintRequest);

		DeleteStdIO(PrintRequest);
	}

	if(PrintPort)
		DeletePort(PrintPort);

	if(RasterBitMap . Planes[0])
		FreeMem(RasterBitMap . Planes[0],byte(24) * 36);

	if(DiskFont)
		CloseFont(DiskFont);

	if(Window)
	{
		ThisProcess -> pr_WindowPtr = SavePtr;

		CloseWindow(Window);
	}

	if(DiskfontBase)
		CloseLibrary(DiskfontBase);

	if(LayersBase)
		CloseLibrary(LayersBase);

	if(ReqBase)
	{
		PurgeFiles(&FontFileReq);
		PurgeFiles(&CaptureFileReq);

		CloseLibrary(ReqBase);
	}

	exit(ReturnCode);
}

	/* OpenAll():
	 *
	 *	Opens libraries, devices, the window, the tin can,
	 *	the door and various assorted items.
	 */

VOID
OpenAll()
{
	SHORT i;

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

	if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",0)))
	{
		SimpleRequest("Couldn't open \"layers.library\"!");
		CloseAll(RETURN_FAIL + 1);
	}

	if(!(DiskfontBase = (struct Library *)OpenLibrary("diskfont.library",34)))
	{
		SimpleRequest("Couldn't open \"diskfont.library\" (at least 1.3 required)!");
		CloseAll(RETURN_FAIL + 2);
	}

	IntuitionBase	= (struct IntuitionBase *)ReqBase -> IntuiLib;
	GfxBase		= (struct GfxBase *)ReqBase -> GfxLib;

	Center(&NewWindow,NewWindow . Width >> 1,NewWindow . Height >> 1);

	if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
	{
		SimpleRequest("Couldn't open window!");
		CloseAll(RETURN_FAIL + 3);
	}

	RPort = Window -> RPort;

	SetAPen(RPort,3);
	SetDrMd(RPort,JAM2);

	DrawBox(RPort,4,11,NewWindow . Width - 5,11 + 10);

	SetAPen(RPort,1);

		/* Dynamically create the gadget interface. */

	for(i = 0 ; i < 7 ; i++)
	{
		MakeButton(&Buttons[i],&ButtonData[0],&ButtonData[16],16,8,12);

		Buttons[i] . Gadget . LeftEdge	= 4;
		Buttons[i] . Gadget . TopEdge	= 12 + 11 + 8 * i;

		if(i != 6)
			Buttons[i] . Gadget . Activation |= TOGGLESELECT;

		if(i > 3)
			Buttons[i] . Gadget . TopEdge += 8;

		AddGadget(Window,&Buttons[i] . Gadget,-1);

		Move(RPort,Buttons[i] . Gadget . LeftEdge + 24,Buttons[i] . Gadget . TopEdge + 6);
		Text(RPort,ButtonText[i],strlen(ButtonText[i]));

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

	Buttons[5] . Gadget . Flags |= SELECTED;

	RefreshGadgets(Window -> FirstGadget,Window,NULL);

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

	SavePtr = ThisProcess -> pr_WindowPtr;

	ThisProcess -> pr_WindowPtr = (APTR)Window;


	InitRastPort(&RasterPort);

	RasterPort . BitMap = &RasterBitMap;

	InitBitMap(&RasterBitMap,1,24,36);

	if(!(RasterBitMap . Planes[0] = (PLANEPTR)AllocMem(byte(24) * 36,MEMF_CHIP)))
	{
		SimpleRequest("Not enough memory for character matrix!");
		CloseAll(RETURN_FAIL + 4);
	}

	if(!(PrintPort = (struct MsgPort *)CreatePort(NULL,0)))
	{
		SimpleRequest("Printer I/O failure!");
		CloseAll(RETURN_FAIL + 5);
	}

	if(!(PrintRequest = (struct IOStdReq *)CreateStdIO(PrintPort)))
	{
		SimpleRequest("Printer I/O failure!");
		CloseAll(RETURN_FAIL + 6);
	}

	if(OpenDevice("printer.device",0,PrintRequest,0))
	{
		SimpleRequest("Couldn't open \"printer.device\"\n(printer already in use?)!");
		CloseAll(RETURN_FAIL + 7);
	}

	FontFileReq . PathName			= Buffer;
	FontFileReq . Title			= "Load a disk font";
	FontFileReq . fontnamescolor		= 3;
	FontFileReq . fontsizescolor		= 3;
	FontFileReq . Window			= Window;
	FontFileReq . Dir			= DirectoryName;
	FontFileReq . File			= FontName;
	FontFileReq . Flags			= FRQCACHINGM | FRQINFOGADGETM | FRQNOHALFCACHEM | FRQGETFONTSM;
	FontFileReq . blockcolor		= 1;

	CaptureFileReq . PathName		= CaptureBuffer;
	CaptureFileReq . Title			= "Select font capture file";
	CaptureFileReq . Window			= Window;
	CaptureFileReq . dirnamescolor		= 3;
	CaptureFileReq . devicenamescolor	= 3;
	CaptureFileReq . Dir			= CaptureDirName;
	CaptureFileReq . File			= CaptureName;
	CaptureFileReq . Flags			= FRQCACHINGM | FRQINFOGADGETM | FRQNOHALFCACHEM | FRQSAVINGM | FRQCACHEPURGEM;
	CaptureFileReq . blockcolor		= 3;

	strcpy(DirectoryName,"FONTS:");

	DiskAttribute . ta_Name	= (UBYTE *)Buffer;

	SetAPen(&RasterPort,1);
	SetBPen(&RasterPort,0);
	SetDrMd(&RasterPort,JAM1);
}

	/* PrintWrite():
	 *
	 *	Send a string to the printer, do the necessary data
	 *	conversion on the way.
	 */

VOID
PrintWrite(char *String)
{
	PrintRequest -> io_Command	= CMD_WRITE;
	PrintRequest -> io_Data		= String;
	PrintRequest -> io_Length	= -1;

	DoIO(PrintRequest);
}

	/* PrintRawWrite():
	 *
	 *	Send a string to the printer, don't convert
	 *	anything!
	 */

VOID
PrintRawWrite(APTR String,SHORT Length)
{
		/* Are we to send the string to the capture file? */

	if(Buttons[4] . Gadget . Flags & SELECTED)
	{
		if(GlobalOut)
		{
			if(Write(GlobalOut,String,Length) != Length)
			{
				SimpleRequest("Error writing to capture file!");

				Close(GlobalOut);

				GlobalOut = NULL;

				DeleteFile(CaptureBuffer);
			}
		}
	}

	if(Buttons[5] . Gadget . Flags & SELECTED)
	{
		PrintRequest -> io_Command	= PRD_RAWWRITE;
		PrintRequest -> io_Data		= String;
		PrintRequest -> io_Length	= Length;

		DoIO(PrintRequest);
	}
}

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

	/* main():
	 *
	 *	This follows one of the largest main routines ever!
	 */

void
main()
{
	SHORT	 ReadX,ReadY,WriteX,WriteY,AspectRatio,MaxWidth,i;
	char	 TempString[20];
	UBYTE	 Shuttle[2];
	UBYTE	*Bits,Data[3];

	OpenAll();

		/* Some more setups. */

	Shuttle[1] = 0;

	Move(RPort,(Window -> Width >> 1) - 8 * (3),11 + 2 + 6);
	Text(RPort,"Ready.",6);

	FOREVER
	{
		WaitPort(Window -> UserPort);

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

			ReplyMsg(Massage);

				/* User made the mistake to press the
				 * right mouse button!
				 */

			if(Class == MOUSEBUTTONS && Code == MENUUP)
			{
				SimpleRequest("            FontConvert 1.0\n\n\
       (c) Copyright 1990 by MXM,\n\
          all rights reserved.\n\n\
This program is SHARE-WARE.  If you like\n\
and  use  it  frequently,  please send a\n\
contribution  of  at  least 10$ US or DM\n\
15,- to:\n\n\
           Olaf Barthel, MXM\n\
           Brabeckstrasse 35\n\
           D-3000 Hannover 71\n\n\
      Federal Republic of Germany\n");

				continue;
			}

				/* Close the window and terminate the
				 * program?
				 */

			if(Class == CLOSEWINDOW)
			{
				if(TwoGadRequest("Really quit FontConvert 1.0?"))
				{
					ClearPointer(Window);
					CloseAll(RETURN_OK);
				}
			}

				/* One of those gadgets has been
				 * selected.
				 */

			if(Class == GADGETUP)
			{
					/* Capture the printer data
					 * to a disk file?
					 */

				if(GadgetID == 4)
				{
					if(Buttons[4] . Gadget . Flags & SELECTED)
					{
						if(FileRequester(&CaptureFileReq))
							continue;
					}

					Buttons[4] . Gadget . Flags &= ~SELECTED;

					RefreshGadgets(&Buttons[4] . Gadget,Window,NULL);
				}

					/* Start the font conversion? */

				if(GadgetID == 6)
				{
					if(!(Buttons[4] . Gadget . Flags & SELECTED) && !(Buttons[5] . Gadget . Flags & SELECTED))
					{
						SimpleRequest("Font must be sent to a file or\nto the printer!");
						continue;
					}

						/* Turn the window off. */

					SetWait(Window);

					for(i = 0 ; i < 7 ; i++)
						OffGadget(&Buttons[i] . Gadget,Window,NULL);

						/* Did we get a font? */

					if(FileRequester(&FontFileReq))
					{
							/* Fill in name and size. */

						DiskAttribute . ta_YSize = FontFileReq . FontYSize;
						DiskAttribute . ta_Style = FontFileReq . FontStyle;

							/* Open the font. */

						if(!(DiskFont = (struct TextFont *)OpenDiskFont(&DiskAttribute)))
							SimpleRequest("Couldn't load font \"%s/%ld\"!",DiskAttribute . ta_Name,DiskAttribute . ta_YSize);
						else
						{
							SHORT i,j,CharSpace,Style = 0;

								/* Erase the message window. */

							SetAPen(RPort,0);
							RectFill(RPort,4 + 1,11 + 1,NewWindow . Width - 5 - 1,11 + 10 - 1);
							SetAPen(RPort,1);

								/* Open the capture file? */

							if(Buttons[4] . Gadget . Flags & SELECTED)
							{
								if(!(GlobalOut = Open(CaptureBuffer,MODE_NEWFILE)))
								{
									if(!TwoGadRequest("Couldn't open capture file! Do you want\nto continue?"))
										continue;
								}
							}

								/* Clear the font flags. */

							for(i = 0 ; i < 256 ; i++)
								FontFlag[i] = FALSE;

								/* Clear the printer font raster. */

							SetFont(&RasterPort,DiskFont);

								/* Set the approriate style bits. */

							if(Buttons[0] . Gadget . Flags & SELECTED)
								Style |= FSF_UNDERLINED;

							if(Buttons[1] . Gadget . Flags & SELECTED)
								Style |= FSF_BOLD;

							if(Buttons[2] . Gadget . Flags & SELECTED)
								Style |= FSF_ITALIC;

							SetSoftStyle(&RasterPort,Style,~0);

								/* Fill in the font flags and determine the
								 * width of each character.
								 */

							for(i = DiskFont -> tf_LoChar, MaxWidth = 0 ; i <= DiskFont -> tf_HiChar ; i++)
							{
								Shuttle[0] = i;

								if((CharSpace = TextLength(&RasterPort,(char *)Shuttle,1)) > MaxWidth)
									MaxWidth = CharSpace;

								if(CharSpace > 0)
									FontFlag[i] = TRUE;
							}

								/* Rescale the font height until it fits into
								 * the raster.
								 */

							AspectRatio = 24;

							while((AspectRatio * MaxWidth) / DiskFont -> tf_YSize > 36)
								AspectRatio--;

								/* Initialize the dummy raster port. */

							InitBitMap(&TextBitMap,1,MaxWidth,DiskFont -> tf_YSize);

							if(TextBitMap . Planes[0] = AllocMem(byte(MaxWidth) * DiskFont -> tf_YSize,MEMF_CHIP | MEMF_PUBLIC))
							{
								if(TextLayerInfo = (struct Layer_Info *)NewLayerInfo())
								{
									if(TextLayer = (struct Layer *)CreateBehindLayer(TextLayerInfo,&TextBitMap,0,0,MaxWidth - 1,DiskFont -> tf_YSize - 1,LAYERSIMPLE,NULL))
									{
										SHORT LastChar;

											/* Setup the necessary things to
											 * convert the font.
											 */

										SetAPen(TextLayer -> rp,1);
										SetBPen(TextLayer -> rp,0);
										SetDrMd(TextLayer -> rp,JAM2);

										SetFont(TextLayer -> rp,DiskFont);

										SetSoftStyle(TextLayer -> rp,Style,~0);

											/* Are we to convert the whole graphics
											 * character set?
											 */

										if(Buttons[3] . Gadget . Flags & SELECTED)
										{
											LastChar = 217;
											PrintRawWrite("\33@\33!\2\33:\0\0\0\33&\0\40\331",15);
										}
										else
										{
											LastChar = 95;
											PrintRawWrite("\33@\33!\2\33:\0\0\0\33&\0\40\176",15);
										}

											/* Go into conversion loop... */

										for(i = 0 ; i < LastChar ; i++)
										{
												/* Empy character? Send a row of blanks. */

											if(!CharTable[i] || !FontFlag[CharTable[i]])
											{
												PrintRawWrite("\0\1\0\0\0\0",6);
												continue;
											}

												/* Right mouse button pressed? */

											if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
											{
												Class	= Massage -> Class;
												Code	= Massage -> Code;

												ReplyMsg((struct Message *)Massage);

												if(Class == MOUSEBUTTONS && Code == MENUUP)
												{
													if(TwoGadRequest("Really stop font conversion?"))
													{
															/* Send blanks for the following
															 * characters and reset the printer.
															 */

														for(j = i ; j < LastChar ; j++)
															PrintRawWrite("\0\1\0\0\0\0",6);

														PrintRawWrite("\33@",2);
														break;
													}
												}
											}

											Shuttle[0] = CharTable[i];

											CharSpace = TextLength(TextLayer -> rp,(char *)Shuttle,1);

												/* Clear the font raster port and
												 * draw the character.
												 */

											SetRast(TextLayer -> rp,0);
											Move(TextLayer -> rp,0,DiskFont -> tf_Baseline);
											Text(TextLayer -> rp,(char *)Shuttle,1);

												/* Say where we are... */

											Format(TempString,"%03ld '%lc' %2ld × %2ld",Shuttle[0],Shuttle[0],(AspectRatio * CharSpace) / DiskFont -> tf_YSize,AspectRatio);

											Move(RPort,(Window -> Width >> 1) - 8 * (7) + 4,11 + 2 + 6);
											Text(RPort,TempString,15);

											SetRast(&RasterPort,0);

												/* Scan the character line by line including
												 * rescaling.
												 */

											for(ReadY = WriteY = 0 ; ReadY < DiskFont -> tf_YSize ; ReadY = ((++WriteY) * DiskFont -> tf_YSize) / AspectRatio)
											{
												for(ReadX = WriteX = 0 ; ReadX < CharSpace ; ReadX = ((++WriteX) * DiskFont -> tf_YSize) / AspectRatio)
												{
													if(ReadPixel(TextLayer -> rp,ReadX,ReadY))
														WritePixel(&RasterPort,WriteY,WriteX);
												}
											}

												/* Say how wide the character is. */

											Data[0] = Data[2] = 0;
											Data[1] = (AspectRatio * CharSpace) / DiskFont -> tf_YSize;

											PrintRawWrite(Data,3);

												/* Send the character bits. */

											for(j = 0 ; j < Data[1] ; j++)
											{
												Bits = (UBYTE *)((ULONG)RasterBitMap . Planes[0] + RasterBitMap . BytesPerRow * j);

												PrintRawWrite(Bits,3);
											}
										}

											/* Turn on the use font. */

										PrintRawWrite("\33%1",3);

											/* Say that we are done. */

										Move(RPort,(Window -> Width >> 1) - 8 * (12),11 + 2 + 6);
										Text(RPort,"Font conversion finished",24);

											/* Test the printer font? */

										if(Buttons[5] . Gadget . Flags & SELECTED)
										{
											if(TwoGadRequest("Font conversion completed.\nTest new printer font?"))
											{
												PrintWrite("\nFont \"");
												PrintWrite(Buffer);
												PrintWrite("\":\n");

												PrintWrite("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\n");
											}
										}

											/* Clean up the font stuff... */

										DeleteLayer(TextLayerInfo,TextLayer);
									}
									else
										SimpleRequest("Not enough memory for font work area!");

									DisposeLayerInfo(TextLayerInfo);
								}
								else
									SimpleRequest("Not enough memory for font work area!");

								FreeMem(TextBitMap . Planes[0],byte(MaxWidth) * DiskFont -> tf_YSize);
							}
							else
								SimpleRequest("Not enough memory for font work area!");

							CloseFont(DiskFont);
							DiskFont = NULL;

								/* Dump file still open? */

							if(GlobalOut)
							{
								Close(GlobalOut);

								GlobalOut = NULL;
							}
						}
					}

						/* Reenable the window? */

					for(i = 0 ; i < 7 ; i++)
						OnGadget(&Buttons[i] . Gadget,Window,NULL);

					ClearPointer(Window);
				}
			}
		}
	}
}
