/*
 * Example 2 - Based on the UI code for FontMover 2.0 by Michael Sinz
 *
 * Copyright (c) 1989,90 - MKSoft Development
 *
 ************************************************************************
 *                                                                      *
 *                            DISCLAIMER                                *
 *                                                                      *
 *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
 *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
 *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
 *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
 *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
 *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
 *                                                                      *
 ************************************************************************
 */

#include	<exec/types.h>
#include	<exec/lists.h>
#include	<exec/nodes.h>
#include	<exec/memory.h>
#include	<exec/alerts.h>
#include	<graphics/text.h>
#include	<graphics/rastport.h>
#include	<libraries/dos.h>
#include	<intuition/intuition.h>

#include	<proto/intuition.h>
#include	<proto/exec.h>
#include	<proto/graphics.h>
#include	<proto/layers.h>

#include	<string.h>
#include	<ctype.h>

#include	"RenderInfo.h"
#include	"Example2Strings.h"

struct	Library	*LayersBase;

/*
 * Some code to fill in border arrays for boxes...
 */

/*
 * This function makes a top-left border array based on the
 * x/y size of the box...
 */
VOID	FillTopLeft_Border(struct Border *bd,SHORT xSize,SHORT ySize)
{
register	SHORT	*xy;

	xy=bd->XY;
	xy[0]=xSize-2;		xy[1]=0;
	xy[2]=0;		xy[3]=0;
	xy[4]=0;		xy[5]=ySize-1;
	xy[6]=1;		xy[7]=ySize-2;
	xy[8]=1;		xy[9]=1;
}

/*
 * This function makes a bottom-right border array based on the
 * x/y size of the box...
 */
VOID	FillBottomRight_Border(struct Border *bd,SHORT xSize,SHORT ySize)
{
register	SHORT	*xy;

	xy=bd->XY;
	xy[0]=1;		xy[1]=ySize-1;
	xy[2]=xSize-1;		xy[3]=ySize-1;
	xy[4]=xSize-1;		xy[5]=0;
	xy[6]=xSize-2;		xy[7]=1;
	xy[8]=xSize-2;		xy[9]=ySize-2;
}

/*
 * These are just STUB routines for a more complex gadget
 * this is not part of the example but is used in the
 * interface...
 */
struct DisplayList
{
struct	Gadget		Gadget;
struct	Border		Borders[2*2];
	SHORT		Vectors[2*5*2];
};

/*
 * This routine deallocates the DisplayList allocated below...
 * It does not do any unlinking...
 */
void FreeListGadget(struct DisplayList *list)
{
	if (list) FreeMem(list,sizeof(struct DisplayList));
}

/*
 * This routine allocates and initializes a DisplayList gadget...
 * It will link the gadgets into the gadget list given...
 *
 * Arguments:  **Gadget,Highlight,Shadow,Left,Top,Width,Height
 */
struct DisplayList *InitListGadget(struct Gadget **gad,UBYTE Highlight,UBYTE Shadow,SHORT Left,SHORT Top,SHORT Width,SHORT Height)
{
struct	DisplayList	*list;

	if (list=AllocMem(sizeof(struct DisplayList),MEMF_PUBLIC|MEMF_CLEAR))
	{
		/*
		 * Set up borders for the gadget
		 */
		list->Borders[0].FrontPen=Highlight;
		list->Borders[0].DrawMode=JAM1;
		list->Borders[0].Count=5;
		list->Borders[0].XY=&(list->Vectors[0*5*2]);
		list->Borders[0].NextBorder=&(list->Borders[1]);

		list->Borders[1].FrontPen=Shadow;
		list->Borders[1].DrawMode=JAM1;
		list->Borders[1].Count=5;
		list->Borders[1].XY=&(list->Vectors[1*5*2]);
		list->Borders[1].NextBorder=NULL;

		list->Borders[2]=list->Borders[0];
		list->Borders[2].FrontPen=Shadow;
		list->Borders[2].NextBorder=&(list->Borders[3]);

		list->Borders[3]=list->Borders[1];
		list->Borders[3].FrontPen=Highlight;

		FillTopLeft_Border(&(list->Borders[0]),Width,Height);
		FillBottomRight_Border(&(list->Borders[1]),Width,Height);

		/*
		 * Set up the gadget
		 */
		list->Gadget.NextGadget=*gad;	*gad=&(list->Gadget);
		list->Gadget.LeftEdge=Left;
		list->Gadget.TopEdge=Top;
		list->Gadget.Width=Width;
		list->Gadget.Height=Height;
		list->Gadget.Flags=((Shadow==Highlight) ? GADGHCOMP : GADGHIMAGE);
		list->Gadget.Activation=RELVERIFY;
		list->Gadget.GadgetType=BOOLGADGET;
		list->Gadget.GadgetRender=(APTR)&(list->Borders[0]);
		list->Gadget.SelectRender=(APTR)&(list->Borders[2]);
	}
	return(list);
}

/*
 * Gadgets in the window and standard requesters...
 */
#define	GADGET_COPY	1
#define	GADGET_REMOVE	2
#define	GADGET_SHOW	3
#define	GADGET_HELP	4
#define	GADGET_ABOUT	5
#define	FONT_DIR_ONE	6
#define	FONT_DIR_TWO	7
#define	OPEN_DIR_ONE	8
#define	OPEN_DIR_TWO	9

/*
 * These are the "stipped-down" structures needed for this
 * example.
 */
struct FontList
{
struct	DisplayList	*Font_List;
struct	DisplayList	*Size_List;
	char		FontDirNameBuffer[256];
};

struct TextGadget
{
struct	Gadget		Gadget;
struct	IntuiText	IText;
};

struct MyWindow
{
/*
 * Pointer to the window all of this is in
 */
struct	Window		*Window;

/*
 * The two "FontList" structures that will contain
 * the font directory string gadgets and other such info...
 */
struct	FontList	Fonts[2];

/*
 * This gives the active font side...  When the user selects
 * an item on from one of the font or size lists, that side is
 * made active.
 */
	SHORT		ActiveFont;

/*
 * String gadgets and the borders and Info
 */
struct	Gadget		StringGadgets[2];
struct	Border		StringBorders[2*2];
	SHORT		StringVectors[4*5*2];
struct	StringInfo	StringInfo[2];

/*
 * The five action gadgets and the borders
 */
struct	TextGadget	ActionGadgets[5];
struct	Border		ActionBorders[2*2];
	SHORT		ActionVectors[2*5*2];

/*
 * The two OPEN DIRECTORY gadget
 */
struct	TextGadget	OpenGadgets[2];
struct	Border		OpenBorders[2*2];
	SHORT		OpenVectors[2*5*2];
struct	IntuiText	OpenText;	/* For the SELECT word */

/*
 * For global details such as the dimple border
 * and the display text we just have this simple
 * gadget...
 */
struct	Gadget		DetailGadget;
struct	Border		DetailBorders[3*2];
	SHORT		DetailVectors[3*2*5*2];

/*
 * The "RenderInfo" stuff is "stuffed" in here...
 */
struct	RenderInfo	*RenderInfo;

/*
 * This is the TextAttr that was finally used
 * for the window...  (In case of Fall-Back)
 */
struct	TextAttr	*RealTextAttr;

/*
 * Global Undo buffer for string gadgets
 */
	char		UndoBuffer[256];
};

/*
 * The "default" font we might need for "FallBack"
 */
static char fontnam[11]="topaz.font";
static struct TextAttr TOPAZ80={fontnam,8,0,FPF_ROMFONT};

#define	IN_BOX	1
#define	OUT_BOX	2

/*
 * This is the number of lines between the action gadgets...
 */
#define	LINES_BETWEEN	2

struct Detail_Defs
{
	SHORT	x,y,w,h;	/* Size and position */
	SHORT	type;		/* IN_BOX or OUT_BOX */
};

static struct Detail_Defs DetailStuff[3]=
{
	{  0, 34,398, 38,			IN_BOX},	/* Font Preview area	*/
	{190,  8, 18, 10+LINES_BETWEEN*2,	IN_BOX},	/* Dimple in...		*/
	{192,  9, 14,  8+LINES_BETWEEN*2,	OUT_BOX}	/* Dimple out...	*/
};

struct Action_Defs
{
	SHORT	y;		/* y position (x pos and size is fixed...) */
	USHORT	GadgetID;	/* ID for this gadget */
	short	Text;
};

static short CopyNames[3]=
{
	TXT_CopyRightString,
	TXT_CopyLeftString,
	TXT_CopyGadgetString
};

static struct Action_Defs AGadgetDef[5]=
{
	{13,			GADGET_COPY,	TXT_CopyGadgetString},
	{13+LINES_BETWEEN,	GADGET_REMOVE,	TXT_RemoveGadgetString},
	{13+LINES_BETWEEN*2,	GADGET_SHOW,	TXT_ShowGadgetString},
	{32-LINES_BETWEEN,	GADGET_HELP,	TXT_HelpGadgetString},
	{32,			GADGET_ABOUT,	TXT_AboutGadgetString}
};

/*
 * This routine centers a IntuiText string in the gadget.
 *
 * NOTE:  You *MUST* have the ITextFont set to a valid TextAttr
 *        or else you *CRASH*
 */
void CenterTextInGadget(struct TextGadget *gad)
{
	gad->IText.LeftEdge=(((gad->Gadget.Width)-IntuiTextLength(&(gad->IText))) >> 1);
	gad->IText.TopEdge=(((gad->Gadget.Height)-(gad->IText.ITextFont->ta_YSize)) >> 1);
}

/*
 * This routine is my simple, one-line user Alert plus a "Press to continue"
 *
 * Note that the text given should be 50 characters or less...
 *
 * Note also that this is using the "new" rule that text in
 * alerts is TOPAZ80...
 */
void AlertUser(short TextID)
{
register	UBYTE	*c;
register	char	*text;
		char	RealBuffer[128];

	text=Get_String(TextID);

	c=RealBuffer;
	*((USHORT *)c)=(80-strlen(text)) << 2;
	c++;
	c++;
	*c++=14;
	while (*text) *c++=*text++;
	*c++=0;
	*c++=1;
	text=Get_String(TXT_PressButtonToContinue);
	*((USHORT *)c)=(80-strlen(text)) << 2;
	c++;
	c++;
	*c++=26;
	while (*text) *c++=*text++;
	*c++=0;
	*c++=0;
	DisplayAlert(RECOVERY_ALERT,RealBuffer,36);
}

/*
 * Example of a gadget that has more that one possible text string
 * and how to "UpDate" the display
 */

/*
 * This routine changes the COPY gadget to point in the direction asked for.
 *
 * Direction Values are:  0 == Copy from left
 *			  1 == Copy from right
 *			  2 == No copy
 */
void ModifyCopy(struct MyWindow *my)
{
register	struct	TextGadget	*copyGad;
register		char		*NewString;

	copyGad=&(my->ActionGadgets[0]);
	if ((my->ActiveFont<0)||(my->ActiveFont>2)) my->ActiveFont=2;
	NewString=Get_String(CopyNames[my->ActiveFont]);
	if (copyGad->IText.IText!=NewString)
	{
		RemoveGadget(my->Window,&(copyGad->Gadget));
		copyGad->IText.IText=NewString;
		CenterTextInGadget(copyGad);
		SetDrMd(my->Window->RPort,JAM1);
		SetAPen(my->Window->RPort,0);
		RectFill(my->Window->RPort,copyGad->Gadget.LeftEdge+2,copyGad->Gadget.TopEdge+1,copyGad->Gadget.LeftEdge+copyGad->Gadget.Width-5,copyGad->Gadget.TopEdge+copyGad->Gadget.Height-3);
		AddGadget(my->Window,&(copyGad->Gadget),0);
		RefreshGList(&(copyGad->Gadget),my->Window,NULL,1);
	}
}

/*
 * This routine correctly frees any part of the MyWindow structure
 * that is allocated.  This includes the Window, if it was open.
 */
void MyCloseWindow(struct MyWindow *my)
{
	if (my)
	{
		if (my->Window) CloseWindow(my->Window);
		if (my->Fonts[0].Font_List) FreeListGadget(my->Fonts[0].Font_List);
		if (my->Fonts[0].Size_List) FreeListGadget(my->Fonts[0].Size_List);
		if (my->Fonts[1].Font_List) FreeListGadget(my->Fonts[1].Font_List);
		if (my->Fonts[1].Size_List) FreeListGadget(my->Fonts[1].Size_List);
		if (my->RenderInfo) CleanUp_RenderInfo(my->RenderInfo);
		FreeMem(my,sizeof(struct MyWindow));
	}
}

/*
 * Defines for the FALL_BACK flag...
 */
#define	NO_FALL_BACK	0
#define	TRY_FALL_BACK	1
#define	FALL_BACK_DONE	2

/*
 * This routine allocates a MyWindow structure and puts together a window
 * description plus gadgets for the FontMover.  It will also open this
 * window if possible.  If it returns with a NULL, the open failed for some
 * reason.  (Either not enough memory or too large a screen font)
 */
struct MyWindow *MyOpenWindow(ULONG Initial_IDCMP)
{
register		SHORT		loop;
register		SHORT		y_plus;
register		USHORT		highlight=GADGHIMAGE;
register		short		TextGadget_X;
register		short		TextGadget_Y;
register		short		X_Extra;
register		short		FallBack=NO_FALL_BACK;
register	struct	TextAttr	*TextGadget_Attr;
register	struct	MyWindow	*my;
register	struct	Gadget		**gad;
register	struct	RenderInfo	*ri;
		struct	NewWindow	nw;

	while (FallBack<FALL_BACK_DONE) if (my=AllocMem(sizeof(struct MyWindow),MEMF_PUBLIC|MEMF_CLEAR))
	{
		/*
		 * Clear out the NewWindow structure and get ready to
		 * build the window we need...
		 */
		memset((char *)&nw,0,sizeof(struct NewWindow));
		gad=&(nw.FirstGadget);

		/*
		 * Get the rendering information...
		 */
		if (my->RenderInfo=(ri=Get_RenderInfo(NULL)))
		{
			y_plus=ri->WindowTitle+ri->WindowTop;

			/*
			 * Check if we are in Fall-Back mode...
			 */
			my->RealTextAttr=TextGadget_Attr=(FallBack ? &TOPAZ80 : &(ri->TextAttr));

			/*
			 * Quick, determine the text gadget sizes...
			 */
			TextGadget_X=10+Max_Gadget_Length(TextGadget_Attr);
			TextGadget_Y=4+(TextGadget_Attr->ta_YSize);

			/*
			 * Check if we need to used GADGHCOMP for those with single bit planes...
			 */
			if (ri->Shadow==ri->Highlight) highlight=GADGHCOMP;

			/*
			 * Set up the COPY gadget state and the active font state.  (All in one ;-)
			 */
			my->ActiveFont=2;

			/*
			 * Now, set up the two gadgets that let the user open
			 * the Directory Requester
			 */
			my->OpenGadgets[0].IText.FrontPen=1;
			my->OpenGadgets[0].IText.DrawMode=JAM1;
			my->OpenGadgets[0].IText.ITextFont=TextGadget_Attr;
			my->OpenGadgets[0].IText.IText="<";

			my->OpenGadgets[0].Gadget.NextGadget=*gad;	*gad=&(my->OpenGadgets[0].Gadget);
			my->OpenGadgets[0].Gadget.TopEdge=1+y_plus+(((ri->FontSize)+4-TextGadget_Y) >> 1);
			my->OpenGadgets[0].Gadget.Height=TextGadget_Y;
			my->OpenGadgets[0].Gadget.Flags=highlight;
			my->OpenGadgets[0].Gadget.Activation=RELVERIFY;
			my->OpenGadgets[0].Gadget.GadgetType=BOOLGADGET;
			my->OpenGadgets[0].Gadget.GadgetRender=(APTR)&(my->OpenBorders[0]);
			my->OpenGadgets[0].Gadget.SelectRender=(APTR)&(my->OpenBorders[2]);
			my->OpenGadgets[0].Gadget.GadgetText=&(my->OpenGadgets[0].IText);
			my->OpenGadgets[0].Gadget.GadgetID=OPEN_DIR_ONE;
			my->OpenGadgets[0].Gadget.UserData=(APTR)&(my->Fonts[0]);

			my->OpenGadgets[1]=my->OpenGadgets[0];
			my->OpenGadgets[1].IText.IText=">";

			my->OpenGadgets[1].Gadget.NextGadget=*gad;	*gad=&(my->OpenGadgets[1].Gadget);
			my->OpenGadgets[1].Gadget.GadgetText=&(my->OpenGadgets[1].IText);
			my->OpenGadgets[1].Gadget.GadgetID=OPEN_DIR_TWO;
			my->OpenGadgets[1].Gadget.UserData=(APTR)&(my->Fonts[1]);

			/*
			 * Find the widest of the two...
			 */
			my->OpenGadgets[0].Gadget.Width=IntuiTextLength(&(my->OpenGadgets[0].IText))+6;
			my->OpenGadgets[1].Gadget.Width=IntuiTextLength(&(my->OpenGadgets[1].IText))+6;

			if ((my->OpenGadgets[0].Gadget.Width) > (my->OpenGadgets[1].Gadget.Width))
			{
				my->OpenGadgets[1].Gadget.Width=my->OpenGadgets[0].Gadget.Width;
			}
			else
			{
				my->OpenGadgets[0].Gadget.Width=my->OpenGadgets[1].Gadget.Width;
			}

			/*
			 * Center the '<' and '>' in the gadgets
			 */
			CenterTextInGadget(&(my->OpenGadgets[0]));
			CenterTextInGadget(&(my->OpenGadgets[1]));

			/*
			 * Add in the text between the gadgets
			 */
			my->OpenText=my->OpenGadgets[0].IText;
			my->OpenGadgets[0].IText.NextText=&(my->OpenText);
			my->OpenText.IText=Get_String(TXT_DirSelectGadget);

			/*
			 * Make sure that the text will fit between the gadgets...
			 */
			TextGadget_X-=1;
			my->OpenText.LeftEdge=-100;	/* Make sure we do this atleast once */
			while (my->OpenText.LeftEdge < (my->OpenGadgets[0].Gadget.Width+2))
			{
				TextGadget_X+=1;

				/*
				 * Adjust the list gadget widths if we grow too large
				 * with the gadgets.
				 *
				 * NOTE:  85 is the LARGEST the adjustment value can be
				 *        otherwise some gadgets will run into each other.
				 *        Smaller values will cause more expansion.
				 */
				X_Extra=((TextGadget_X > 74) ? ((TextGadget_X-74) << 1) : 0);

				/*
				 * Calculate new values for X positions of the gadgets
				 * and the text between them...
				 */
				my->OpenText.LeftEdge=(my->OpenGadgets[0].Gadget.Width) +
				    (
					(
					    (my->OpenGadgets[1].Gadget.LeftEdge=212-(my->OpenGadgets[1].Gadget.Width)+TextGadget_X+((ri->WindowLeft)*2)+X_Extra) -
					    (my->OpenGadgets[0].Gadget.LeftEdge=186+((ri->WindowLeft)*2)+X_Extra) -
					    (my->OpenGadgets[0].Gadget.Width) -
					    IntuiTextLength(&(my->OpenText))
					) >> 1
				    );
			}

			/*
			 * Set up borders for the string gadgets (One set for both gadgets...)
			 */
			my->StringBorders[0].LeftEdge=-5;
			my->StringBorders[0].TopEdge=-3;
			my->StringBorders[0].FrontPen=ri->Highlight;
			my->StringBorders[0].DrawMode=JAM1;
			my->StringBorders[0].Count=5;
			my->StringBorders[0].XY=&(my->StringVectors[0*5*2]);
			my->StringBorders[0].NextBorder=&(my->StringBorders[1]);

			my->StringBorders[1]=my->StringBorders[0];
			my->StringBorders[1].FrontPen=ri->Shadow;
			my->StringBorders[1].XY=&(my->StringVectors[1*5*2]);
			my->StringBorders[1].NextBorder=&(my->StringBorders[2]);

			my->StringBorders[2].LeftEdge=-3;
			my->StringBorders[2].TopEdge=-2;
			my->StringBorders[2].FrontPen=ri->Shadow;
			my->StringBorders[2].DrawMode=JAM1;
			my->StringBorders[2].Count=5;
			my->StringBorders[2].XY=&(my->StringVectors[2*5*2]);
			my->StringBorders[2].NextBorder=&(my->StringBorders[3]);

			my->StringBorders[3]=my->StringBorders[2];
			my->StringBorders[3].FrontPen=ri->Highlight;
			my->StringBorders[3].XY=&(my->StringVectors[3*5*2]);
			my->StringBorders[3].NextBorder=NULL;

			FillTopLeft_Border(&(my->StringBorders[0]),182+X_Extra,6+ri->FontSize);
			FillBottomRight_Border(&(my->StringBorders[1]),182+X_Extra,6+ri->FontSize);
			FillTopLeft_Border(&(my->StringBorders[2]),178+X_Extra,4+ri->FontSize);
			FillBottomRight_Border(&(my->StringBorders[3]),178+X_Extra,4+ri->FontSize);

			/*
			 * Set up borders for the action gadgets (One set for all gadgets...)
			 */
			my->ActionBorders[0].FrontPen=ri->Highlight;
			my->ActionBorders[0].DrawMode=JAM1;
			my->ActionBorders[0].Count=5;
			my->ActionBorders[0].XY=&(my->ActionVectors[0*5*2]);
			my->ActionBorders[0].NextBorder=&(my->ActionBorders[1]);

			my->ActionBorders[1].FrontPen=ri->Shadow;
			my->ActionBorders[1].DrawMode=JAM1;
			my->ActionBorders[1].Count=5;
			my->ActionBorders[1].XY=&(my->ActionVectors[1*5*2]);
			my->ActionBorders[1].NextBorder=NULL;

			my->ActionBorders[2]=my->ActionBorders[0];
			my->ActionBorders[2].FrontPen=ri->Shadow;
			my->ActionBorders[2].NextBorder=&(my->ActionBorders[3]);

			my->ActionBorders[3]=my->ActionBorders[1];
			my->ActionBorders[3].FrontPen=ri->Highlight;

			FillTopLeft_Border(&(my->ActionBorders[0]),TextGadget_X,TextGadget_Y);
			FillBottomRight_Border(&(my->ActionBorders[1]),TextGadget_X,TextGadget_Y);

			/*
			 * Set up borders for the "open" gadgets (One set for all gadgets...)
			 */
			my->OpenBorders[0]=my->ActionBorders[0];
			my->OpenBorders[0].XY=&(my->OpenVectors[0*5*2]);
			my->OpenBorders[0].NextBorder=&(my->OpenBorders[1]);

			my->OpenBorders[1]=my->ActionBorders[1];
			my->OpenBorders[1].XY=&(my->OpenVectors[1*5*2]);

			my->OpenBorders[2]=my->OpenBorders[0];
			my->OpenBorders[2].FrontPen=ri->Shadow;
			my->OpenBorders[2].NextBorder=&(my->OpenBorders[3]);

			my->OpenBorders[3]=my->OpenBorders[1];
			my->OpenBorders[3].FrontPen=ri->Highlight;

			FillTopLeft_Border(&(my->OpenBorders[0]),my->OpenGadgets[0].Gadget.Width,TextGadget_Y);
			FillBottomRight_Border(&(my->OpenBorders[1]),my->OpenGadgets[0].Gadget.Width,TextGadget_Y);

			/*
			 * Set up borders for the display "details"
			 */
			{
			register	struct	Border	*tmp;

				tmp=&(my->DetailBorders[0]);

				for (loop=0;loop<3;loop++)
				{
					tmp->LeftEdge=DetailStuff[loop].x+(loop ? X_Extra : 0);
					tmp->TopEdge=DetailStuff[loop].y+(loop ? 0 : (5*TextGadget_Y));
					tmp->FrontPen=((DetailStuff[loop].type==OUT_BOX) ? ri->Highlight : ri->Shadow);
					tmp->DrawMode=JAM1;
					tmp->Count=5;
					tmp->XY=&(my->DetailVectors[loop*2*5*2]);
					tmp->NextBorder=&(tmp[1]);

					FillTopLeft_Border(tmp,DetailStuff[loop].w+TextGadget_X+(loop ? 0 : (2*X_Extra)),DetailStuff[loop].h+((loop ? 3 : 1)*TextGadget_Y));

					tmp=&(tmp[1]);

					tmp->LeftEdge=DetailStuff[loop].x+(loop ? X_Extra : 0);
					tmp->TopEdge=DetailStuff[loop].y+(loop ? 0 : (5*TextGadget_Y));
					tmp->FrontPen=((DetailStuff[loop].type==OUT_BOX) ? ri->Shadow : ri->Highlight);
					tmp->DrawMode=JAM1;
					tmp->Count=5;
					tmp->XY=&(my->DetailVectors[((loop*2)+1)*5*2]);
					tmp->NextBorder=&(tmp[1]);

					FillBottomRight_Border(tmp,DetailStuff[loop].w+TextGadget_X+(loop ? 0 : (2*X_Extra)),DetailStuff[loop].h+((loop ? 3 : 1)*TextGadget_Y));

					tmp=&(tmp[1]);
				}

				tmp[-1].NextBorder=NULL;
			}

			/*
			 * Now, set up the string gadgets...  We know what the title bar
			 * size is and what the font size will be for the gadgets.
			 */
			my->StringGadgets[0].NextGadget=*gad;	*gad=&(my->StringGadgets[0]);
			my->StringGadgets[0].LeftEdge=5+((ri->WindowLeft)*2);
			my->StringGadgets[0].TopEdge=3+y_plus;
			my->StringGadgets[0].Width=172+X_Extra;
			my->StringGadgets[0].Height=ri->FontSize;
			my->StringGadgets[0].Flags=GADGHCOMP;
			my->StringGadgets[0].Activation=RELVERIFY;
			my->StringGadgets[0].GadgetType=STRGADGET;
			my->StringGadgets[0].GadgetRender=(APTR)&(my->StringBorders[0]);
			my->StringGadgets[0].SpecialInfo=(APTR)&(my->StringInfo[0]);
			my->StringGadgets[0].GadgetID=FONT_DIR_ONE;

			my->StringGadgets[1]=my->StringGadgets[0];
			my->StringGadgets[1].NextGadget=*gad;	*gad=&(my->StringGadgets[1]);
			my->StringGadgets[1].LeftEdge=221+TextGadget_X+((ri->WindowLeft)*2)+X_Extra;
			my->StringGadgets[1].SpecialInfo=(APTR)&(my->StringInfo[1]);
			my->StringGadgets[1].GadgetID=FONT_DIR_TWO;

			my->StringInfo[0].Buffer=my->Fonts[0].FontDirNameBuffer;
			my->StringInfo[0].UndoBuffer=my->UndoBuffer;
			my->StringInfo[0].MaxChars=250;

			my->StringInfo[1].Buffer=my->Fonts[1].FontDirNameBuffer;
			my->StringInfo[1].UndoBuffer=my->UndoBuffer;
			my->StringInfo[1].MaxChars=250;

			y_plus+=ri->FontSize;

			/*
			 * Set up a fake gadget that will hold the
			 * display details such as the boxes and borders
			 */
			my->DetailGadget.NextGadget=*gad;	*gad=&(my->DetailGadget);
			my->DetailGadget.LeftEdge=((ri->WindowLeft)*2);
			my->DetailGadget.TopEdge=y_plus;
			my->DetailGadget.Flags=GADGHNONE;
			my->DetailGadget.GadgetType=BOOLGADGET;
			my->DetailGadget.GadgetRender=(APTR)&(my->DetailBorders[0]);

			/*
			 * Now do the action gadgets...
			 */
			for (loop=0;loop<5;loop++)
			{
				my->ActionGadgets[loop].Gadget.NextGadget=*gad;	*gad=&(my->ActionGadgets[loop].Gadget);
				my->ActionGadgets[loop].Gadget.LeftEdge=199+((ri->WindowLeft)*2)+X_Extra;
				my->ActionGadgets[loop].Gadget.TopEdge=AGadgetDef[loop].y+y_plus+loop*TextGadget_Y;
				my->ActionGadgets[loop].Gadget.Width=TextGadget_X;
				my->ActionGadgets[loop].Gadget.Height=TextGadget_Y;
				my->ActionGadgets[loop].Gadget.Flags=highlight;
				my->ActionGadgets[loop].Gadget.Activation=RELVERIFY;
				my->ActionGadgets[loop].Gadget.GadgetType=BOOLGADGET;
				my->ActionGadgets[loop].Gadget.GadgetRender=(APTR)&(my->ActionBorders[0]);
				my->ActionGadgets[loop].Gadget.SelectRender=(APTR)&(my->ActionBorders[2]);
				my->ActionGadgets[loop].Gadget.GadgetText=&(my->ActionGadgets[loop].IText);
				my->ActionGadgets[loop].Gadget.GadgetID=AGadgetDef[loop].GadgetID;

				my->ActionGadgets[loop].IText.FrontPen=1;
				my->ActionGadgets[loop].IText.BackPen=0;
				my->ActionGadgets[loop].IText.DrawMode=JAM1;
				my->ActionGadgets[loop].IText.ITextFont=TextGadget_Attr;
				my->ActionGadgets[loop].IText.IText=Get_String(AGadgetDef[loop].Text);
				CenterTextInGadget(&(my->ActionGadgets[loop]));
			}

			/*
			 * Get the four list gadgets set up...
			 */
			{
			register	short	tmpExtra;

				tmpExtra=(X_Extra >> 1);
				my->Fonts[0].Font_List=InitListGadget(gad,ri->Highlight,ri->Shadow,((ri->WindowLeft)*2),8+y_plus,130+tmpExtra,24+5*TextGadget_Y);
				my->Fonts[0].Size_List=InitListGadget(gad,ri->Highlight,ri->Shadow,134+((ri->WindowLeft)*2)+tmpExtra,8+y_plus,48+X_Extra-tmpExtra,24+5*TextGadget_Y);
				my->Fonts[1].Font_List=InitListGadget(gad,ri->Highlight,ri->Shadow,216+TextGadget_X+X_Extra+((ri->WindowLeft)*2),8+y_plus,130+tmpExtra,24+5*TextGadget_Y);
				my->Fonts[1].Size_List=InitListGadget(gad,ri->Highlight,ri->Shadow,350+TextGadget_X+X_Extra+((ri->WindowLeft)*2)+tmpExtra,8+y_plus,48+X_Extra-tmpExtra,24+5*TextGadget_Y);
			}

			/*
			 * Set up the NewWindow structure now that the gadgets are done...
			 */
			nw.LeftEdge=0;
			nw.TopEdge=0;
			nw.Width=398+((ri->WindowLeft+ri->WindowRight)*2)+TextGadget_X+(2*X_Extra);
			nw.Height=72+y_plus+((ri->WindowBottom)*2)+(6*TextGadget_Y);
			nw.DetailPen=-1;
			nw.BlockPen=-1;
			nw.IDCMPFlags=Initial_IDCMP;
			nw.Flags=WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SMART_REFRESH|NOCAREREFRESH|ACTIVATE;
			nw.Title=Get_String(TXT_Window_Title);
			nw.MinWidth=nw.Width;
			nw.MinHeight=nw.Height;
			nw.MaxWidth=nw.Width;
			nw.MaxHeight=nw.Height;
			nw.Type=WBENCHSCREEN;

			/*
			 * Now, check if all it a go for opening the window
			 */
			if (	(my->Fonts[0].Font_List)
			     &&	(my->Fonts[0].Size_List)
			     &&	(my->Fonts[1].Font_List)
			     &&	(my->Fonts[1].Size_List)	) my->Window=OpenWindow(&nw);
		}

		/*
		 * If we did not get a window, free everything and return NULL
		 */
		if (!(my->Window))
		{
			MyCloseWindow(my);
			my=NULL;
			FallBack+=1;
		}
		else FallBack=FALL_BACK_DONE;
	}
	else FallBack=FALL_BACK_DONE;

	if (!my) AlertUser(TXT_WindowOpenError);

	return(my);
}

/*
 * Code to "Make this work"
 */
void DoFontMover(struct MyWindow *mywin)
{
register		short		ExitFlag=FALSE;
register	struct	IntuiMessage	*msg;
register	struct	Gadget		*gad;

	while (!ExitFlag)
	{
		WaitPort(mywin->Window->UserPort);
		while (msg=(struct IntuiMessage *)GetMsg(mywin->Window->UserPort))
		{
			if (msg->Class==CLOSEWINDOW) ExitFlag=TRUE;
			else if (msg->Class==GADGETUP)
			{
				if (gad=(struct Gadget *)(msg->IAddress))
				{
					if (gad->GadgetID==GADGET_COPY)
					{
						mywin->ActiveFont-=1;
						ModifyCopy(mywin);
					}
				}
			}
			ReplyMsg((struct Message *)msg);
		}
	}
}

/*
 * Main...
 *
 * This just opens everything that will be needed...
 */
void main(void)
{
register	struct	MyWindow	*MyWindow;

	if (IntuitionBase=OpenLibrary("intuition.library",33L))
	{
		if (LayersBase=OpenLibrary("layers.library",33L))
		{
			if (GfxBase=OpenLibrary("graphics.library",33L))
			{
				if (MyWindow=MyOpenWindow(GADGETUP|CLOSEWINDOW))
				{
					DoFontMover(MyWindow);
					MyCloseWindow(MyWindow);
				}
				CloseLibrary(GfxBase);
			}
			else AlertUser(TXT_OpenGraphicsError);
			CloseLibrary(LayersBase);
		}
		else AlertUser(TXT_OpenLayersError);
		CloseLibrary(IntuitionBase);
	}
}
