/*
 *	ParM.c - Copyright © 1990 by S.R. & P.C.
 *
 *	Created:	01 Jul 1990
 *	Modified:	01 Jul 1990
 *
 *	Make>> make
 */

/*
#define DO_ARP_COPIES
#include <exec/memory.h>
#include <libraries/arpbase.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <functions.h>
#include <arp_pragmas.h>
*/

#include <dos_functions.h>
#include <arpdos_pragmas.h>
#include <arp_ports.h>
#include "ParM.h"

#define THE_END		0
#define NO_ARP		1
#define NO_ICON		2
#define NO_WIN		3
#define NO_REQ		4
#define NO_PORT		5

#define OWN_MENU	0

#define OPEN_ITEM		0
#define UPDATE_ITEM		1
#define COMMAND_ITEM	2
#define CHDIR_ITEM		3
#define QUIT_ITEM		4

const char *COPYRIGHT =  "ParM V1.1 Copyright © 1990 by S.R. & P.C.";

extern void Command(void);
extern BOOL ParseMenus( void );
extern void FreeMenus( void );
extern void DoExtMenu( USHORT );
extern void WBFree( struct WBStartup * );

/*****				global functions					*****/

void Warn( const char * );

/*****				global variables					*****/

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct ArpBase *ArpBase;
extern struct IconBase *IconBase;	/* already defined in manx startup */
extern struct WBStartup *WBenchMsg;	/* defined in manx startup */
extern struct Process *MyProcess;
extern struct Window *Win;
extern struct Menu Menu1;
extern UBYTE menu_pen;
extern char CurCfg[];
extern char CmdWindow[];
extern struct MsgPort *WBReplyPort;
extern short WBCnt;
extern int Enable_Abort;	/* manx startup variable */


/*****				 local variables					*****/

static struct FileRequester *FileReq;
static BOOL Own_Window = FALSE;
static BOOL quit = FALSE;
static BYTE ParMenuColor = -1;


struct ToolTypesArg {
	char *tta_Name;
	char tta_cli_equ;
};

static struct ToolTypesArg TTA_List[] = {
	{ "LEFTEDGE"	, 'x' },
	{ "TOPEDGE"		, 'y' },
	{ "DETAILPEN"	, 'd' },
	{ "BLOCKPEN"	, 'b' },
	{ "MENUCOLOR"	, 'c' },
	{ "CONFIGFILE"	, 'f' }
};

#define TTANUM	6	/* Number of ToolTypesArg in List */


static char *ErrorTab[] = {
	NULL,
	"You need arp.library V39+",
	"No icon.library !",
	"Can't Open Window",
	"Not enough memory",
};

static struct NewWindow NWS = {
	0,0,	/* window XY origin relative to TopLeft of screen */
	90,10,	/* window width and height */
	3,2,	/* detail and block pens */
	MENUPICK,	/* IDCMP flags */
	WINDOWDRAG+WINDOWDEPTH+SIMPLE_REFRESH+NOCAREREFRESH,	/* other window flags */
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	(UBYTE *)PRG_NAME,	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	-1,-1,	/* maximum width and height */
	WBENCHSCREEN	/* destination screen type */
};

/**************************************************/
/************   Warn Requester Data   *************/
/**************************************************/

static struct IntuiText BodyText = {
	2,1,JAM1,	/* front and back text pens, drawmode and fill byte */
	14,8,		/* XY origin relative to container TopLeft */
	NULL,		/* font pointer or NULL for default */
	NULL,		/* pointer to text */
	NULL		/* next IntuiText structure */
};


static struct IntuiText OkText = {
	2,1,JAM1,
	6,3,
	NULL,
	(UBYTE *)"Ok",
	NULL
};


static struct IntuiText CancelText = {
	2,1,JAM1,	/* front and back text pens, drawmode and fill byte */
	6,3,		/* XY origin relative to container TopLeft */
	NULL,		/* font pointer or NULL for default */
	(UBYTE *)"Cancel",	/* pointer to text */
	NULL		/* next IntuiText structure */
};


void Warn( const char *text )
{
	static char buf[60];

	SPrintf( buf , "%s: %s" , PRG_NAME , text );
	BodyText.IText = (UBYTE *)buf;
	AutoRequest(NULL,&BodyText,NULL,&CancelText,NULL,NULL,60+IntuiTextLength(&BodyText),54);
}

static BOOL Confirm( const char *text )
{
	BodyText.IText = (UBYTE *)text;
	return AutoRequest(NULL,&BodyText,&OkText,&CancelText,NULL,NULL,60+IntuiTextLength(&BodyText),54);
}

/***** get CLI window ptr *****/

static struct Window *GetWindow( void )
{
	struct InfoData *infodata;
	struct Window *win;
	long args[8];

	infodata=AllocMem((long)sizeof(struct InfoData),MEMF_CLEAR | MEMF_PUBLIC);
	args[0]=(long)infodata >> 2;
	SendPacket(ACTION_DISK_INFO,args,(struct MsgPort *)MyProcess->pr_ConsoleTask);
	win=(struct Window *)infodata->id_VolumeNode;
	FreeMem(infodata,(long)sizeof(struct InfoData));
	return win;
}


/*	Configuration managing functions  */

static void InstallMenus( void )
{
	if( ! ParseMenus() ) FreeMenus();
	SetMenuStrip( Win , &Menu1 );
	return;
}

static void UpDateMenus( void )
{
	ClearMenuStrip( Win );
	FreeMenus();
	InstallMenus();
}

static void OpenMenus( void )
{
	char *yuck;

	FileReq->fr_Hail = "Open";
	strcpy( FileReq->fr_Dir , CurCfg );
	strcpy( FileReq->fr_File , yuck=BaseName(FileReq->fr_Dir) );
	*yuck = '\0';	/* cut off filename from fr_Dir */
	if( ! FileRequest(FileReq) ) return;	/* quit if Open canceled */
	strcpy( CurCfg , FileReq->fr_Dir );
	TackOn( CurCfg , FileReq->fr_File );
	UpDateMenus();
}

static void SetMenFgCol( UBYTE color ) /* set other Front Pen when attached to CLI */
{
	struct MenuItem *mi;
	struct IntuiText *it;

	menu_pen = color;
	for( mi=Menu1.FirstItem ; mi ; mi=mi->NextItem )
		for( it=(struct IntuiText *)mi->ItemFill ; it ; it=it->NextText )
			it->FrontPen = color;
}


/*	Print busy message in place of window title  */

static void Busy( BOOL status )
{
	char *Msg;

	if( status ) 
		Msg = "Busy";
	else
		Msg = PRG_NAME;
	SetWindowTitles( Win , Msg , COPYRIGHT );
}


static void Usage( void )
{
	Printf("%s\n",COPYRIGHT);
	Printf("Usage: %s [-w] [-x#] [-y#] [-d#] [-b#] [-c#] [-fConfigFile]\n",PRG_NAME);
	CloseLibrary( IconBase );
	CloseLibrary( ArpBase );
	exit(0);
}


/*	Atcho, bonsoir...  */

static void Bye(short err)
{
	switch( err ) {
	case THE_END :
		ClearMenuStrip( Win );
		FreeMenus();
		DeletePort( WBReplyPort );
	case NO_PORT :
		if( Own_Window == TRUE )
			CloseWindowSafely(Win,NULL);
		else
			ModifyIDCMP( Win , Win->IDCMPFlags & ~MENUPICK );
	case NO_WIN :
	case NO_REQ :
		CloseLibrary( IconBase );
	case NO_ICON :
		CloseLibrary( ArpBase );
	case NO_ARP :
		;
	}
	if(err) Warn( ErrorTab[(err>3)?4:err] );
	exit(err);
}


/*	handle workbench replies  */

static void DoWBMsg( void )
{
	WBCnt--;
	WBFree( (struct WBStartup *)GetMsg(WBReplyPort) );
}


/*	handle IntuiMessages  */

static void DoIntuiMsg( void )
{
	struct IntuiMessage *Message;
	ULONG Class;
	USHORT Code;
	BPTR NewLock,OldLock;
	BOOL DoNextSelect;

	while( Message = (struct IntuiMessage *) GetMsg(Win->UserPort) ) {
		Class = Message->Class;
		Code = Message->Code;
		ReplyMsg( (struct Message *)Message );
		switch( Class ) {
		case MENUPICK :
			DoNextSelect = TRUE;
			if( Code != MENUNULL ) do {
				switch( MENUNUM( Code ) ) { 	
				case OWN_MENU :
					switch( ITEMNUM( Code ) ) {
					case OPEN_ITEM :
						OpenMenus();
						DoNextSelect = FALSE;
						break;
					case UPDATE_ITEM :
						UpDateMenus();
						DoNextSelect = FALSE;
						break;
					case COMMAND_ITEM :
						Command();
						break;
					case CHDIR_ITEM :
						FileReq->fr_Dir[0] = '\0';	/* futur plans: build path string */
						FileReq->fr_File[0] = '\0';
						FileReq->fr_Hail = "Enter New Dir...";
						if( FileRequest(FileReq) ) {
							NewLock = Lock( FileReq->fr_Dir , ACCESS_READ );
	  						if( NewLock != NULL ) {
								OldLock = CurrentDir((struct FileLock *)NewLock);
								if( OldLock != NULL ) UnLock(OldLock);
							}
						}
						break;
					case QUIT_ITEM :
						if( WBCnt == 0 ) {
							if( Confirm("Really Quit ParM ?") ) {
								quit = TRUE;
								DoNextSelect = FALSE;
							}
						} else
							Warn("WorkBench Processes Still Active");
						break;
					}
					break;
				default :	/* custom menus */
					DoExtMenu( Code );
				}
			} while( DoNextSelect && (Code=ItemAddress(&Menu1,Code)->NextSelect) != MENUNULL );
			break;
		default :
			;	/* we only manage MENUPICK events */
		}
	}
}


static BOOL PortNotEmpty( struct MsgPort *P )
{
	return ( P->mp_MsgList.lh_Head->ln_Succ ) ? TRUE : FALSE;
}


static void parse_arg( char opt , char *args )
{
	long argl;

	argl = Atol( args );
	switch( opt ) {
	case 'w' :
		Own_Window = TRUE;
		break;
	case 'x' :
		NWS.LeftEdge = argl;
		Own_Window = TRUE;
		break;
	case 'y' :
		NWS.TopEdge = argl;
		Own_Window = TRUE;
		break;
	case 'd' :
		NWS.DetailPen = argl;
		Own_Window = TRUE;
		break;
	case 'b' :
		NWS.BlockPen = argl;
		Own_Window = TRUE;
		break;
	case 'c' :
		ParMenuColor = argl;
		break;
	case 'f' :
		strcpy( CurCfg , args );
		break;
	case 'h' :	/* those can only happen on CLI invocation */
	default :
		Usage();
	}
}


int main(int argc, char *argv[])
{
	ULONG Mask,WBRPMask,WinMask;
	struct DiskObject *dop;
	char *arg;
	SHORT i;

	Enable_Abort = 0;	/* disable ^C break */
	if( !(ArpBase = (struct ArpBase *)OpenLibrary("arp.library",39L)) ) Bye(NO_ARP);
	IntuitionBase = (struct IntuitionBase *)ArpBase->IntuiBase;
	GfxBase = (struct GfxBase *)ArpBase->GfxBase;
	if( !(IconBase = (struct IconBase *)OpenLibrary("icon.library",0L)) ) Bye(NO_ICON);
	if( !(FileReq = ArpAllocFreq()) ) Bye(NO_REQ);
	MyProcess = (struct Process *)FindTask(0L);
	strcpy(CurCfg, DEFAULT_CONFIG_FILE);
	strcpy(CmdWindow ,DEFAULT_CMD_WINDOW);

	if( argc == 0 ) {	/* Tool Types parsing */
		Own_Window = TRUE;
		if( dop = GetDiskObject(WBenchMsg->sm_ArgList->wa_Name) ) {
			for( i=0 ; i<TTANUM ; i++ ) {		
				if( arg = FindToolType( dop->do_ToolTypes, TTA_List[i].tta_Name) )
					parse_arg( TTA_List[i].tta_cli_equ , arg );
			}
			FreeDiskObject(dop);
		}
	} else {	/* CLI parsing */
		for( i=1 ; i<argc ; i++ ) {
			if( argv[i][0] != '-' || strlen(argv[i]) < 2 ) Usage();
			parse_arg( argv[i][1] , &argv[i][2] );
		}
	}
	if( Own_Window == TRUE ) {
		if( !(Win = OpenWindow(&NWS)) ) Bye(NO_WIN);
		Busy( FALSE );
	} else {
		Win = GetWindow();
		if( Win->IDCMPFlags & MENUPICK ) {
			Warn("This window already have menus!");
			CloseLibrary( IconBase );
			CloseLibrary( ArpBase );
			exit(0);
		} else
			ModifyIDCMP( Win , Win->IDCMPFlags | MENUPICK );
	}
	if( ParMenuColor < 0 )
		SetMenFgCol( Win->DetailPen ); /* default FgPen for main menu */
	else
		SetMenFgCol( ParMenuColor );
	FileReq->fr_Window = Win;
	if( !(WBReplyPort = CreatePort(NULL,NULL)) ) Bye(NO_PORT);
	WBRPMask = 1L << WBReplyPort->mp_SigBit;
	WinMask = 1L << Win->UserPort->mp_SigBit;
	InstallMenus();

	/* Monitor Menu Events */

	while( !quit ) {
		/* Wait only if no messages are queued up at any port */
		while( PortNotEmpty(WBReplyPort) || PortNotEmpty(Win->UserPort) ) {
			if( PortNotEmpty(WBReplyPort) )
				DoWBMsg();
			else
				DoIntuiMsg();
		}
		if( Own_Window ) Busy( FALSE );
		Mask = Wait( WinMask | WBRPMask );
		if( Own_Window ) Busy( TRUE );
		if( Mask == WBRPMask )
			DoWBMsg();
		else
			DoIntuiMsg();
	}
	Bye(THE_END);
}

