#include "DFC5.h"

char df0[] = "df0:" ;				  /* use only one copy of this name */
char df1[] = "df1:" ;				  /* ditto */
char df2[] = "df2:" ;				  /* ditto */
char df3[] = "df3:" ;				  /* ditto */
char *df[]={df0, df1, df2, df3};	  /* for easy access to drive names */

/*
 *	  Always use topaz 80, and let's define an intuition buffer for our
 *	  general string writing stuff.
 */

struct TextAttr Topaz8 = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 };
struct IntuiText IntuiText = {1, 0, JAM2, 0, 0, &Topaz8} ;

/*
 * This is to ``get that look''...
 */

SHORT XY1[6]={ 0,11,0,0,63,0 };
SHORT XY2[6]={ 1,11,63,11,63,0 };

/*
 * The copy progress bar 3D border.
 */

SHORT BXY1[6]={ 0,9,321,9,321,0 };
SHORT BXY2[6]={ 0,8,0,0,320,0 };

/*
 * The first two items are the gadget border, the other two ones the progress
 * bar border.
 */

struct Border Border[] = {
	{	0,0,2,0,JAM1,3,XY1,&Border[1]	},
	{	0,0,1,0,JAM1,3,XY2,NULL },
	{	0,0,2,0,JAM1,3,BXY1,&Border[3]	},
	{	0,0,1,0,JAM1,3,BXY2,NULL	}
};

/*
 * ITexts for gadgets.
 */

struct IntuiText IText[18] = {
	{	1,0,JAM1, 17,2, &Topaz8, df0, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df1, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df2, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df3, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df0, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df1, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df2, NULL	},
	{	1,0,JAM1, 17,2, &Topaz8, df3, NULL	},
	{	1,0,JAM1, 8,2, &Topaz8, "Verify", NULL },
	{	1,0,JAM1, 8,2, &Topaz8, "Buffer", NULL },
	{	1,0,JAM1, 16,2, &Topaz8, "Talk", NULL	},
	{	1,0,JAM1, 20,2, &Topaz8, "FFS", NULL	},
	{	1,0,JAM1, 16,2, &Topaz8, "Date", NULL	},
	{	1,0,JAM1, 16,2, &Topaz8, "Stop", NULL	},
	{	1,0,JAM1, 24,2, &Topaz8, "Go", NULL },
	{	1,0,JAM1, 8,2, &Topaz8, "Repeat", NULL },
	{	1,0,JAM1, 8,2, &Topaz8, "Format", NULL },
	{	1,0,JAM1, 16,2, &Topaz8, "Auto", NULL }
};

/*
 * The gadgets.
 */

struct Gadget Gadget[18] = {
	{	&Gadget[1], 80,20, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[0], NULL, NULL, '0', NULL
	},
	{	&Gadget[2], 148,20, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[1], NULL, NULL, '1', NULL
	},
	{	&Gadget[3], 216,20, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[2], NULL, NULL, '2', NULL
	},
	{	&Gadget[4], 284,20, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[3], NULL, NULL, '3', NULL
	},
	{	&Gadget[5], 80,50, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[4], NULL, NULL, '4', NULL
	},
	{	&Gadget[6], 148,50, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[5], NULL, NULL, '5', NULL
	},
	{	&Gadget[7], 216,50, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[6], NULL, NULL, '6', NULL
	},
	{	&Gadget[8], 284,50, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[7], NULL, NULL, '7', NULL
	},
	{	&Gadget[9], 12,65, 64,12,
		GADGHCOMP| SELECTED, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[8], NULL, NULL, 'V', NULL
	},
	{	&Gadget[10], 80,65, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[9], NULL, NULL, 'B', NULL
	},
	{	&Gadget[11], 148,65, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[10], NULL, NULL, 'T', NULL
	},
	{	&Gadget[12], 216,65, 64,12,
		GADGHCOMP, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[11], NULL, NULL, 'N', NULL
	},
	{	&Gadget[13], 284,65, 64,12,
		GADGHCOMP| SELECTED, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[12], NULL, NULL, 'D', NULL
	},
	{	&Gadget[14], 12,80, 64,12,
		GADGHCOMP, RELVERIFY, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[13], NULL, NULL, 'S', NULL
	},
	{	&Gadget[15], 80,80, 64,12,
		GADGHCOMP, RELVERIFY, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[14], NULL, NULL, 'G', NULL
	},
	{	&Gadget[16], 148,80, 64,12,
		GADGHCOMP, RELVERIFY, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[15], NULL, NULL, 'R', NULL
	},
	{	&Gadget[17], 216,80, 64,12,
		GADGHCOMP, RELVERIFY, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[16], NULL, NULL, 'F', NULL
	},
	{	NULL, 284,80, 64,12,
		GADGHCOMP | GADGDISABLED, GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET,
		(APTR)&Border[0], NULL, &IText[17], NULL, NULL, 'A', NULL
	}
};

struct NewWindow NewWindow = {
	128,64, 360,100, 0,1,
	GADGETDOWN | GADGETUP | CLOSEWINDOW | VANILLAKEY,
	WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | ACTIVATE | NOCAREREFRESH,
	&Gadget[0], NULL, "DFC5--by T. Rokicki/S. Vigna", NULL, NULL, 360,100, -1,-1, WBENCHSCREEN
};

/*
 * This structures are for AutoRequest();
 */

struct IntuiText Req = {
	AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	20,20,
	&Topaz8,
};

struct IntuiText Cancel = {
  AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  AUTOLEFTEDGE, AUTOTOPEDGE,
	&Topaz8,
  NULL,
  AUTONEXTTEXT
};

struct IntuiText Retry = {
  AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  AUTOLEFTEDGE, AUTOTOPEDGE,
	&Topaz8,
  "Try Again",
  AUTONEXTTEXT
};


/*
 * Here we invert the border colors if we are under 1.3
 */

void ReverseBorderColors(void) {

	int i;
	for(i=0; i<4; i++) Border[i].FrontPen = i%2+1;
}


/*
 * This is for read errors, write errors etc.
 */

int ProblemsWithUnit(char *s, int Unit, int Track) {

	static char s2[100];

	sprintf(s2, "%s error on disk %ld, track %ld.", s, Unit, Track);
	Req.IText = s2;
	Say(s2);
	Cancel.IText = "So What?";
	return(AutoRequest(0, &Req, &Retry, &Cancel, 0, 0, 320, 72));
}

/*
 * This is only for saying something that's only a notification.
 */

void Acknowledge(char *s) {

	Req.IText = s;
	Say(s);
	Cancel.IText = "OK";
	AutoRequest(0, &Req, NULL, &Cancel, 0, 0, 320, 72);
}


/*
 *	  This routine draws a string into the window at
 *	  a specific X, Y location.
 */

void DrawText(struct Window *Window, char *String, int x, int y) {

	IntuiText.IText = (UBYTE *)String ;
	PrintIText(Window->RPort, &IntuiText, (long)x, (long)y) ;
}

/*
 *	  This set of routines draw the progress bar. They're fairly smart---
 *   first they update Bar, then they check for the layer we need being
 *   unlocked. If it's not the case, they set SomethingFailed go.
 *   As soon as the layer is free, the bar is redrawn basing on Bar.
 *   This allows for smooth copy operations even if someone uses menus
 *   (thus locking all layers). UpDateProgress forces the bar to be
 *   updated.
 */

static unsigned char SomethingFailed, Bar[20];

void PrintRectAt(struct Window *Window, int n, int color) {
	SetDrMd(Window->RPort, JAM1);
	SetAPen(Window->RPort, color);
	RectFill(Window->RPort, 21+n*4, 37, (21+3)+n*4, 44);
}

void UpdateProgress(struct Window *Window) {

	register int i;

	if (SomethingFailed) {
		for(i=0; i<80; i++) PrintRectAt(Window, i, (Bar[i/4]>>(2*(i%4))) & 3);
		SomethingFailed = 0;
	}
}

void DrawProgress(struct Window *Window, int n, int color) {

	Bar[n/4] &= ~(3<<(2*(n%4)));
	Bar[n/4] |= color<<(2*(n%4));

	if (Window->WScreen->LayerInfo.Lock.ss_NestCount == 0) {
		UpdateProgress(Window);
		PrintRectAt(Window, n, color);
	}
	else SomethingFailed = 1;
}

/*
 *	  This routine wipes the progress bar.
 */

void WipeProgress(struct Window *Window, int start) {

	register int i;

	for(i=start; i<80; i++) DrawProgress(Window, i, 0);
}


/*
 * This sets up the window.
 */

struct Window *SetUpWindow(void) {

	register struct Window *Window;

	if (Window = OpenWindow(&NewWindow)) {

		DrawText(Window, "Source", 20, 22);
		DrawText(Window, "Dest", 28, 52);
		DrawBorder(Window->RPort, &Border[2], 20, 36);
	}
	return(Window);
}

/*
 * Here we wipe completely a gadget
 */

void WipeGadget(struct Window *Window, struct Gadget *G) {

	SetAPen(Window->RPort, 0);
	SetDrMd(Window->RPort, JAM1);
	RectFill(Window->RPort, G->LeftEdge, G->TopEdge, G->LeftEdge+G->Width-1, G->TopEdge+G->Height-1);
}

/*
 * This routines selects or delects a gadget.
 */

void SelectGadget(struct Window *Window, struct Gadget *G, int Bool) {

	register int pos;

	if ((Bool && (G->Flags & SELECTED)) || (!Bool && !(G->Flags & SELECTED))) return;
	pos = RemoveGadget(Window, G);

	if (Bool) G->Flags |= SELECTED;
		else G->Flags &= ~SELECTED;

	AddGadget(Window, G, pos);
	WipeGadget(Window, G);
	RefreshGList(G, Window, NULL, 1);
}

/*
 * This routines toggles a gadget.
 */

void ToggleGadget(struct Window *Window, struct Gadget *G) {

	if (G->Flags & SELECTED)
		SelectGadget(Window, G, FALSE);
	else SelectGadget(Window, G, TRUE);
}

/*
 * This routine returns the address of a gadget. *MUCH* better than global data.
 * If the gadget is disabled, returns NULL.
 */

struct Gadget *GAddr(int GadgetNumber) {
	return(Gadget[GadgetNumber].Flags & GADGDISABLED ? NULL : &Gadget[GadgetNumber]);
}

/*
 * EnableGadgets takes a mask of sizeof(Gadget)/sizeof(struct Gadget) bits and sets
 * all of the gadgets accordingly. Notice that if all it's already OK, we don't
 * do anything.
 */

void EnableGadgets(struct Window *Window, int Mask) {

	register int i, pos=0;

	for(i=0; i<sizeof(Gadget)/sizeof(struct Gadget); i++)
		pos |= ( (((1<<i) & Mask)!=0) != !(Gadget[i].Flags & GADGDISABLED) );
	if (!pos) return;

	for(i=0; i<sizeof(Gadget)/sizeof(struct Gadget); i++) {
		pos = RemoveGadget(Window, &Gadget[i]);

		if ((1<<i) & Mask) Gadget[i].Flags &= ~GADGDISABLED;
		else Gadget[i].Flags |= GADGDISABLED;

		WipeGadget(Window, &Gadget[i]);
		AddGadget(Window, &Gadget[i], pos);
	}

	RefreshGList(Gadget, Window, NULL, sizeof(Gadget)/sizeof(struct Gadget));
}
