/*
 * FoCo: Formatier-Kontroll-Programm
 *       (GadTools-Commodities-etc-Einführung)
 *       Autor: Michael Balzer
 * 
 * 03/91: Erste Version (primär für MacSoft Highlights-Serie)
 *        Version 1.0
 * 
 * 10/91: Änderung, Delay bevor Drivecheck durchgeführt wird
 *        (stand schon lange an...) und Quit-Frage bei CloseWindow
 *        Version 1.1
 * 
 */

#ifndef FOCO_HDR
# include "FoCo.h"
#endif

#include <dos/dosextens.h>

/*------------------------------------------------------------------------*/
void ende(int, STRPTR);
struct Gadget *CreateAllGadgets(struct Gadget **glistptr, 
	void *vi, UWORD topborder);
void ShowWindow( void );
void HideWindow( void );
int GetBADNum( void );

void ArgArrayDone( void );
UBYTE **ArgArrayInit( LONG arg1, UBYTE **arg2 );
LONG ArgInt( UBYTE **arg1, UBYTE *arg2, LONG arg3 );
UBYTE *ArgString( UBYTE **arg1, UBYTE *arg2, UBYTE *arg3 );
CxObj *HotKey( UBYTE *arg1, struct MsgPort *arg2, LONG arg3 );

LONG Printf( UBYTE *format, ... );
LONG CSystem( UBYTE *command, LONG tag1, ... );

/*------------------------------------------------------------------*/
/* GadgetIDs: */
#define GAD_DRIVE		1
#define GAD_NAME		2
#define GAD_FFS			3
#define GAD_NOICONS		4
#define GAD_QUICK		5
#define GAD_OK			6
#define GAD_CANCEL		7

/*------------------------------------------------------------------------*/
/*  Globale Variablen... */
struct IntuitionBase		*IntuitionBase = NULL;
struct GfxBase				*GfxBase = NULL;
struct Library				*GadToolsBase = NULL;
extern struct Library		*IconBase;

struct TextFont				*font = NULL;
struct Screen				*mysc = NULL;
struct Gadget				*glist = NULL;
struct Window				*mywin = NULL;

void						*vi = NULL;
struct RastPort				*rp;
int							Xwidth, WinWidth, WinHeight;
UWORD						topborder;
ULONG						windowsignal=0;

STRPTR DiskList[5] = { NULL,NULL,NULL,NULL,NULL };
STRPTR DiskName[4] = { "DF0:","DF1:","DF2:","DF3:" };

char *TextSpeicher = 0;
#define _COUNT_TXT 15
char *ProgrammText[ _COUNT_TXT ] =
{
	"Formatter",
	"You just inserted an unreadable disk\n"
	"in drive %s.\n"
	"Do you want it to be formatted?",
	" Yes |   NO!   ",
	"User-friendly disk formatter",
	"Pops up on disk insertion/hotkey",
	"Drive:",
	"Name:",
	"FFS",
	"NoIcons",
	"Quick",
	"Format!",
	"Cancel!",
	"Format Disk...",
	"CON:0/0/512/83/Formatting Disk...",
	"Quit FoCo?"
};
#define TXT(n) ProgrammText[n]

struct EasyStruct formatreq =
{
	sizeof( struct EasyStruct ), 0,
	0, 0, 0
	/*TXT(0), TXT(1), TXT(2)*/
};

struct EasyStruct quitreq =
{
	sizeof( struct EasyStruct ), 0,
	0, 0, 0
	/*TXT(0), TXT(14), TXT(2)*/
};

/*------------------------------------------------------------------------*/
/* Trackdisk-Variablen */

struct IOExtTD				*ioexttd[4]={ 0,0,0,0 };
int							changenum[4];
struct MsgPort				*tdport=0;

/*------------------------------------------------------------------------*/
/*  Adressen der Gadgets, Status-Variablen */

struct Gadget *drivegad, *namegad, *ffsgad, *noiconsgad, *quickgad;

int drive;
char name[33];
BOOL bffs=TRUE, bnoicons=TRUE, bquick=FALSE;

/*------------------------------------------------------------------------*/
/* Commodities-Variablen */

struct Library			*CxBase		= NULL;
extern struct Library	*IconBase;

char					**ttypes = NULL, *hotstr;

struct MsgPort			*cxport = 0;
ULONG					cxsigflag = 0;		/* signal for above */

CxObj					*broker = NULL;		/* Our broker */

#define POP_KEY_ID (86L)					/* pop up identifier */

struct NewBroker mynb = {
	NB_VERSION,						/* Library needs to know version */
	0 /*TXT(0)*/,					/* broker internal name			 */
	0 /*TXT(3)*/,					/* commodity title				 */
	0 /*TXT(4)*/,					/* description				 */
	NBU_NOTIFY | NBU_UNIQUE,		/* We want to be the only broker */
									/* with this name and we want to */
									/* be notified of any attempts	 */
									/* to add a commodity with the	 */
									/* same name					 */
	COF_SHOW_HIDE,					/* flags						 */
	0,								/* default priority				 */
	NULL,							/* port, will fill in			 */
	0								/* channel (reserved)			 */
};

/* Eine "input expression" die auf DISK_INSERTED paßt */

IX diskix = {
	IX_VERSION,				/* required */
	IECLASS_DISKINSERTED,
	0,						/* Code   */
	~0,						/* CodeMask   */
	
	0,                      /* qualifier I am interested in  */
	0,
	0                       /* synonyms irrelevant           */
};

#define CX_DISK_ID (87L)

/*-------------------------------------------------------------------------*/
/* Trackdisk-Support-Funktion(en) */

int GetChangeNum( int unit )
{
	if( !ioexttd[unit] ) return( 0 );
	
	ioexttd[unit]->iotd_Req.io_Command = TD_CHANGENUM;
	DoIO( ioexttd[unit] );
	return( ioexttd[unit]->iotd_Req.io_Actual );
}

int GetBADNum( void )
{
	int result=-1, i, cn;
	struct InfoData *infoData;
	struct MsgPort *port;
	
	if( !(infoData = AllocMem(sizeof(struct InfoData),MEMF_PUBLIC)) )
		return -1;
	
	/* ermitteln, WO eine Disk eingelegt wurde */
	for( i=0; i<=3; i++ )
	{
		if( cn = GetChangeNum(i) )
		{
			if( (cn>changenum[i]) && (port=DeviceProc(DiskName[i])) )
			{
				/* und ob die 'BAD' oder 'NDOS' ist */
				if( DoPkt( port, ACTION_DISK_INFO, MKBADDR(infoData), 0,0,0 ) )
				{
					if( infoData->id_DiskType == ID_UNREADABLE_DISK 
					 || infoData->id_DiskType == ID_NOT_REALLY_DOS )
						result=i;
				}
			}
			
			changenum[i] = cn;
		}
	}
	
	FreeMem( infoData, sizeof(struct InfoData) );
	return( result );
}

/*-------------------------------------------------------------------------*/

void LiesProgrammTexte( char *filename )
{
	BPTR file;
	long size, i;
	char *ts;
	
	if( file=Open(filename,MODE_OLDFILE) )
	{
		size = Seek( file, Seek(file,0,OFFSET_END), OFFSET_BEGINNING );
		if( TextSpeicher=AllocMem(size+4,MEMF_PUBLIC) )
		{
			*((long *)TextSpeicher) = size+4;
			Read( file, TextSpeicher+4, size );
			for( i=0, ts=TextSpeicher+4; i < _COUNT_TXT; i++, ts+=strlen(ts)+1 )
				ProgrammText[i] = ts;
		}
		Close( file );
	}
}

void InitAll( int argc, char **argv )
{
	char *str;
	CxObj *cxo;
	int i, dr=0;
	
			/*** Libraries öffnen... ***/
	
	if (!(GfxBase = (struct GfxBase *)
		OpenLibrary("graphics.library", 36L)))
		ende(20, "Requires V36 graphics.library");

	if (!(IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library", 36L)))
		ende(20, "Requires V36 intuition.library");

	if (!(GadToolsBase = OpenLibrary("gadtools.library", 36L)))
		ende(20, "Requires V36 gadtools.library");

	CxBase = OpenLibrary("commodities.library", 36);
	if(!CxBase) ende(20,"Requires V36 commodities.library");
	IconBase = OpenLibrary("icon.library", 36);
	if(!IconBase) ende(20,"Requires V36 icon.library");
	
			/*** ToolTypes (Argv) scannen ***/
	
	ttypes = ArgArrayInit( argc, argv );
	
	drive = ArgInt( ttypes, "DRIVE", 0 );
	strcpy( name, ArgString(ttypes, "NAME", "Empty Disk") );
	if( str=ArgString(ttypes,"FLAGS",NULL) )
	{
		bffs     = MatchToolValue( str, "FFS" );
		bnoicons = MatchToolValue( str, "NOICONS" );
		bquick   = MatchToolValue( str, "QUICK" );
	}
	
	/* Die Texte einlesen */
	LiesProgrammTexte( ArgString(ttypes,"LANGUAGEFILE","FoCo.txt") );
	
	/* und einsetzen */
	formatreq.es_Title = TXT(0);
	formatreq.es_TextFormat = TXT(1);
	formatreq.es_GadgetFormat = TXT(2);
	quitreq.es_Title = TXT(0);
	quitreq.es_TextFormat = TXT(14);
	quitreq.es_GadgetFormat = TXT(2);
	mynb.nb_Name = TXT(0);
	mynb.nb_Title = TXT(3);
	mynb.nb_Descr = TXT(4);
	
			/*** Trackdisk.device öffnen: ***/
	
	if( !(tdport = CreateMsgPort()) )
		ende(20,"Couldn't create TD MsgPort");
	
	/* alle 4 Units antesten */
	for( i=0; i<=3; i++ )
	{
		if( ioexttd[i] = CreateIORequest(tdport, sizeof(struct IOExtTD)) )
		{
			if( OpenDevice(TD_NAME, i, ioexttd[i], TDF_ALLOW_NON_3_5) )
			{
				DeleteIORequest( ioexttd[i] );
				ioexttd[i] = 0;
			}
			else
			{
				changenum[i] = GetChangeNum(i);
				/* in Liste für CycleGadget aufnehmen */
				DiskList[dr++] = DiskName[i];
			}
		}
	}
	
			/*** Hotkey installieren: ***/
	
	cxport = CreateMsgPort();
	if(!cxport) ende(20,"Couldn't create MsgPort");
	cxsigflag = 1L << cxport->mp_SigBit;	/* Signal Mask für Wait*/
	mynb.nb_Port = cxport;
	
	/* Versuchen, den Broker zu erzeugen */
	if ( !(broker = CxBroker(&mynb, NULL)) )
		ende(0,0);
	
	/* Hotkey installieren */
	AttachCxObj( broker,
		HotKey( hotstr=ArgString(ttypes,"HOTKEY","lcommand f"),
			cxport, POP_KEY_ID) );
	
	/* Disk-Insert-Filter installieren */
	if( cxo = CxFilter(NULL) )
	{
		SetFilterIX( cxo, &diskix );
		AttachCxObj( cxo, CxSender(cxport, CX_DISK_ID) );
		AttachCxObj( cxo, CxTranslate(NULL) );
		
		AttachCxObj( broker, cxo );
	}
	
	/* Auf summierten Fehler prüfen */
	if( CxObjError(broker) )
		ende(20,"Internal commodities error");
	
	/* Alles o.k., Broker aktivieren */
	ActivateCxObj(broker,1L);
	
	/* soll das Fenster gleich geöffnet werden? */
	if( str=ArgString(ttypes,"SHOWWINDOW",NULL) )
		if( MatchToolValue(str,"ON") )
			ShowWindow();
}

/*------------------------------------------------------------------------*/

struct Gadget *CreateAllGadgets(
	struct Gadget **glistptr, void *vi, UWORD topborder )
{
	struct NewGadget ng;
	struct Gadget *gad;
	long tl;				/* wg. cc-Fehler */

	/*  All the gadget creation calls accept a pointer to the previous
		gadget, and l