/*
 *                          DiskSpeed v2.0
 *                                by
 *                           Michael Sinz
 *
 *             Copyright (c) 1989 by MKSoft Development
 *
 *
 * Yes, this is yet another disk speed testing program, but with a few
 * differences.  It was designed to give the most accurate results of the
 * true disk performance in the system.  For this reason many of
 * DiskSpeed's results may look either lower or higher than current disk
 * performance tests.
 *
 * This program was thrown together in a few hours because I needed more
 * accurate and consistent results for disk performance as seen from the
 * application's standpoint.  This program has now served its purpose and
 * I am now giving it to the rest of the Amiga world to play with as long
 * as all of the files remain together in unmodified form.  (That is, the
 * files DiskSpeed, DiskSpeed.info, DiskSpeed.c, DiskSpeedWindow.c,
 * DiskSpeedWindow.h, MakeBoxes.c, MakeBoxes.h, StandardGadgets.c,
 * StandardGadgets.h, RenderInfo.c, RenderInfo.h, DiskSpeed.doc, and
 * MakeFile)
 *
 * Version 2.0 of this program added a few features and cleaned up the
 * user interface.  I hope you like this...
 *
 ******************************************************************************
 *									      *
 *	Reading legal mush can turn your bain into guacamole!		      *
 *									      *
 *		So here is some of that legal mush:			      *
 *									      *
 * Permission is hereby granted to distribute this program's source	      *
 * executable, and documentation for non-commercial purposes, so long as the  *
 * copyright notices are not removed from the sources, executable or	      *
 * documentation.  This program may not be distributed for a profit without   *
 * the express written consent of the author Michael Sinz.		      *
 *									      *
 * This program is not in the public domain.				      *
 *									      *
 * Fred Fish is expressly granted permission to distribute this program's     *
 * source and executable as part of the "Fred Fish freely redistributable     *
 * Amiga software library."						      *
 *									      *
 * Permission is expressly granted for this program and it's source to be     *
 * distributed as part of the Amicus Amiga software disks, and the	      *
 * First Amiga User Group's Hot Mix disks.				      *
 *									      *
 ******************************************************************************
 *
 * This file contains the code needed to add standard gadgets to a
 * window.  These are the Close/Front/Back/Drag gadgets...
 *
 * Current limitations:  Gadgets are not rel-size/pos so they only
 * work on fixed sized windows...
 *
 * The drag gadget does not show window Active/Inactive...  :-( :-(
 */

#include	<exec/types.h>
#include	<exec/memory.h>
#include	<intuition/intuition.h>

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

#include	"RenderInfo.h"
#include	"MakeBoxes.h"
#include	"StandardGadgets.h"

static char fontnam[11]="topaz.font";
static struct TextAttr TOPAZ80={fontnam,TOPAZ_EIGHTY,0,0};

#define	CLOSE_WIDTH	24
#define	CLOSE_HEIGHT	12

static	SHORT	CloseBorderVectors1[8*2]=
{
	4,2,	4,9,	19,9,	19,2,	5,2,	5,9,	18,9,	18,3
};

static	SHORT	CloseBorderVectors2[4*2]=
{
	10,5,	13,5,	13,6,	10,6
};

struct CloseGadget
{
struct	Gadget	gad;
struct	Window	*win;
struct	Border	Borders[6];
	SHORT	BorderV1[5*2];
	SHORT	BorderV2[5*2];
};

struct Gadget *AddCloseGadget(struct Window *Window,struct RenderInfo *ri,SHORT x,SHORT y)
{
register	struct	CloseGadget	*gad;
register		SHORT		loop;

	if (gad=AllocMem(sizeof(struct CloseGadget),MEMF_PUBLIC|MEMF_CLEAR))
	{
		gad->win=Window;

		gad->gad.LeftEdge=x;
		gad->gad.TopEdge=y;
		gad->gad.Width=CLOSE_WIDTH;
		gad->gad.Height=CLOSE_HEIGHT;
		gad->gad.Flags=GADGHIMAGE;
		gad->gad.Activation=RELVERIFY;
		gad->gad.GadgetType=CLOSE|SYSGADGET;
		gad->gad.GadgetRender=(APTR)&(gad->Borders[0]);
		gad->gad.SelectRender=(APTR)&(gad->Borders[4]);

		/* Standard render path... */
		gad->Borders[0].NextBorder=&(gad->Borders[1]);
		gad->Borders[1].NextBorder=&(gad->Borders[2]);
		gad->Borders[2].NextBorder=&(gad->Borders[3]);

		/* These point back... */
		gad->Borders[4].NextBorder=&(gad->Borders[5]);
		gad->Borders[5].NextBorder=&(gad->Borders[2]);

		/* Border sizes... */
		gad->Borders[0].Count=5;
		gad->Borders[1].Count=5;
		gad->Borders[2].Count=8;
		gad->Borders[3].Count=4;
		gad->Borders[4].Count=5;
		gad->Borders[5].Count=5;

		for (loop=0;loop<6;loop++)
		{
			gad->Borders[loop].DrawMode=JAM1;
			gad->Borders[loop].FrontPen=ri->Highlight;
		}
		gad->Borders[1].FrontPen=ri->Shadow;
		gad->Borders[4].FrontPen=ri->Shadow;

		gad->Borders[4].XY=gad->Borders[0].XY=gad->BorderV1;
		gad->Borders[5].XY=gad->Borders[1].XY=gad->BorderV2;
		gad->Borders[2].XY=CloseBorderVectors1;
		gad->Borders[3].XY=CloseBorderVectors2;

		FillTopLeft_Border(&(gad->Borders[0]),CLOSE_WIDTH,CLOSE_HEIGHT);
		FillBottomRight_Border(&(gad->Borders[1]),CLOSE_WIDTH,CLOSE_HEIGHT);

		AddGadget(Window,&(gad->gad),NULL);
		RefreshGList(&(gad->gad),Window,NULL,1L);
	}
	return((struct Gadget *)gad);
}

VOID RemCloseGadget(struct Gadget *TheGadget)
{
register	struct	CloseGadget	*gad;

	gad=(struct CloseGadget *)TheGadget;
	RemoveGadget(gad->win,&(gad->gad));
	FreeMem(gad,sizeof(struct CloseGadget));
}

#define	BACK_WIDTH	26
#define	BACK_HEIGHT	12

struct FrontBackGadget
{
struct	Gadget	Back_gad;
struct	Gadget	Front_gad;
struct	Window	*win;
struct	Border	Borders[12];
	SHORT	BorderV1[5*2];
	SHORT	BorderV2[5*2];
};

static	SHORT	FrontBackBorderVectors1[10*2]=
{
	6,3,  6,7,  7,7,  7,3,  17,3,  17,2,  4,2,  4,7,  5,7,  5,3
};

static	SHORT	FrontBackBorderVectors2[12*2]=
{
	8,4,  21,4,  21,9,  8,9,  8,5,  20,5,  20,8,  9,8,  9,6,  19,6,  19,7,  10,7
};

struct Gadget *AddFrontBackGadget(struct Window *Window,struct RenderInfo *ri,SHORT x,SHORT y)
{
register	struct	FrontBackGadget	*gad;
register		SHORT		loop;

	if (gad=AllocMem(sizeof(struct FrontBackGadget),MEMF_PUBLIC|MEMF_CLEAR))
	{
		gad->win=Window;

		gad->Back_gad.LeftEdge=x;
		gad->Back_gad.TopEdge=y;
		gad->Back_gad.Width=BACK_WIDTH;
		gad->Back_gad.Height=BACK_HEIGHT;
		gad->Back_gad.Flags=GADGHIMAGE;
		gad->Back_gad.Activation=RELVERIFY;
		gad->Back_gad.GadgetType=WDOWNBACK|SYSGADGET;
		gad->Back_gad.GadgetRender=(APTR)&(gad->Borders[0]);
		gad->Back_gad.SelectRender=(APTR)&(gad->Borders[4]);

		/* Standard render path... */
		gad->Borders[0].NextBorder=&(gad->Borders[1]);
		gad->Borders[1].NextBorder=&(gad->Borders[2]);
		gad->Borders[2].NextBorder=&(gad->Borders[3]);

		/* These point back... */
		gad->Borders[4].NextBorder=&(gad->Borders[5]);
		gad->Borders[5].NextBorder=&(gad->Borders[2]);

		gad->Front_gad.LeftEdge=x+BACK_WIDTH;
		gad->Front_gad.TopEdge=y;
		gad->Front_gad.Width=BACK_WIDTH;
		gad->Front_gad.Height=BACK_HEIGHT;
		gad->Front_gad.Flags=GADGHIMAGE;
		gad->Front_gad.Activation=RELVERIFY;
		gad->Front_gad.GadgetType=WUPFRONT|SYSGADGET;
		gad->Front_gad.GadgetRender=(APTR)&(gad->Borders[0+6]);
		gad->Front_gad.SelectRender=(APTR)&(gad->Borders[4+6]);

		/* Standard render path... */
		gad->Borders[0+6].NextBorder=&(gad->Borders[1+6]);
		gad->Borders[1+6].NextBorder=&(gad->Borders[2+6]);
		gad->Borders[2+6].NextBorder=&(gad->Borders[3+6]);

		/* These point back... */
		gad->Borders[4+6].NextBorder=&(gad->Borders[5+6]);
		gad->Borders[5+6].NextBorder=&(gad->Borders[2+6]);

		/* Border sizes... */
		for (loop=0;loop<12;loop++) gad->Borders[loop].Count=5;
		gad->Borders[2+6].Count=gad->Borders[2].Count=10;
		gad->Borders[3+6].Count=gad->Borders[3].Count=12;

		/* Pen colours... */
		for (loop=0;loop<12;loop++)
		{
			gad->Borders[loop].DrawMode=JAM1;
			gad->Borders[loop].FrontPen=ri->Highlight;
		}
		gad->Borders[1].FrontPen=ri->Shadow;
		gad->Borders[2].FrontPen=ri->Shadow;
		gad->Borders[4].FrontPen=ri->Shadow;
		gad->Borders[1+6].FrontPen=ri->Shadow;
		gad->Borders[3+6].FrontPen=ri->Shadow;
		gad->Borders[4+6].FrontPen=ri->Shadow;

		gad->Borders[4+6].XY=gad->Borders[0+6].XY=gad->Borders[4].XY=gad->Borders[0].XY=gad->BorderV1;
		gad->Borders[5+6].XY=gad->Borders[1+6].XY=gad->Borders[5].XY=gad->Borders[1].XY=gad->BorderV2;
		gad->Borders[2+6].XY=gad->Borders[2].XY=FrontBackBorderVectors1;
		gad->Borders[3+6].XY=gad->Borders[3].XY=FrontBackBorderVectors2;
		FillTopLeft_Border(&(gad->Borders[0]),BACK_WIDTH,BACK_HEIGHT);
		FillBottomRight_Border(&(gad->Borders[1]),BACK_WIDTH,BACK_HEIGHT);

		AddGadget(Window,&(gad->Back_gad),NULL);
		RefreshGList(&(gad->Back_gad),Window,NULL,1L);

		AddGadget(Window,&(gad->Front_gad),NULL);
		RefreshGList(&(gad->Front_gad),Window,NULL,1L);
	}
	return((struct Gadget *)gad);
}

VOID RemFrontBackGadget(struct Gadget *TheGadget)
{
register	struct	FrontBackGadget	*gad;

	gad=(struct FrontBackGadget *)TheGadget;
	RemoveGadget(gad->win,&(gad->Back_gad));
	RemoveGadget(gad->win,&(gad->Front_gad));
	FreeMem(gad,sizeof(struct FrontBackGadget));
}

#define	DRAG_HEIGHT	12

struct DragGadget
{
struct	Gadget		gad;
struct	Window		*win;
struct	IntuiText	iText;
struct	Border		Borders[2];
	SHORT		BorderV1[5*2];
	SHORT		BorderV2[5*2];
};

struct Gadget *AddDragGadget(struct Window *Window,struct RenderInfo *ri,char *text,SHORT x,SHORT y,SHORT xSize)
{
register	struct	DragGadget	*gad;

	if (gad=AllocMem(sizeof(struct DragGadget),MEMF_PUBLIC|MEMF_CLEAR))
	{
		gad->win=Window;

		gad->gad.LeftEdge=x;
		gad->gad.TopEdge=y;
		gad->gad.Width=xSize;
		gad->gad.Height=CLOSE_HEIGHT;
		gad->gad.Flags=GADGHNONE;
		gad->gad.GadgetType=WDRAGGING|SYSGADGET;
		gad->gad.GadgetRender=(APTR)&(gad->Borders[0]);
		gad->gad.GadgetText=&(gad->iText);

		gad->iText.FrontPen=ri->TextPen;
		gad->iText.DrawMode=JAM1;
		gad->iText.TopEdge=2;
		gad->iText.ITextFont=&TOPAZ80;
		gad->iText.IText=text;
		gad->iText.LeftEdge=(xSize-IntuiTextLength(&(gad->iText))) >> 1;

		/* Standard render path... */
		gad->Borders[0].NextBorder=&(gad->Borders[1]);

		/* Border sizes... */
		gad->Borders[0].Count=gad->Borders[1].Count=5;

		gad->Borders[0].DrawMode=gad->Borders[1].DrawMode=JAM1;
		gad->Borders[0].FrontPen=ri->Shadow;
		gad->Borders[1].FrontPen=ri->Highlight;

		gad->Borders[0].XY=gad->BorderV1;
		gad->Borders[1].XY=gad->BorderV2;
		FillTopLeft_Border(&(gad->Borders[0]),xSize,DRAG_HEIGHT);
		FillBottomRight_Border(&(gad->Borders[1]),xSize,DRAG_HEIGHT);

		AddGadget(Window,&(gad->gad),NULL);
		RefreshGList(&(gad->gad),Window,NULL,1L);
	}
	return((struct Gadget *)gad);
}

VOID RemDragGadget(struct Gadget *TheGadget)
{
register	struct	DragGadget	*gad;

	gad=(struct DragGadget *)TheGadget;
	RemoveGadget(gad->win,&(gad->gad));
	FreeMem(gad,sizeof(struct DragGadget));
}
