/* MPMorph - Amiga Morphing program */
/* Copyright (C) © 1993  Topicsave Limited */

/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* any later version. */

/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
/* GNU General Public License for more details. */

/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* mpaddock@cix.compulink.co.uk */

/* This object is included in both MPMorph and MPMorph-render
 * it includes all the stuff for determing arguments
 * including settings file stuff
 */

/* include headers since does not include precompiled headers */
#include <workbench/workbench.h>
#include <workbench/startup.h>
#ifdef __GNUC__
#include <inline/icon.h>
#include <inline/dos.h>
#include <inline/exec.h>
#else
#include <proto/icon.h>
#include <proto/dos.h>
#define __USE_SYSBASE 1
#include <proto/exec.h>
#endif
#include <exec/memory.h>
#include <stddef.h>
#include <string.h>

/* The program icon for settings */
struct DiskObject *program_icon = NULL;

/* My version of ArgArrayDone
 * does not use cx_lib version as would have to open commodities.library
 * frees everything allocated by argArrayInit
 */
void
argArrayDone( void ) {
	if (program_icon) {
		FreeDiskObject(program_icon);
	}
}

/* my version for ArgArrayInit
 * returns   : pointer to the parameters or program tool types
 * parameters: argc
 *             argv - standard main() arguments
 */
char **
argArrayInit( LONG argc, char **argv ) {
	if (argc) {				/* from the shell */
/*		argv[argc] = 0;	// HACK!!!!!	- not required for SASC 6.5+ */
		return argv;		/* The above is required to prevent the following code */
	}							/* falling off the end. Not sure how safe this is!!! */
	else {
		struct WBStartup *wbs = (struct WBStartup *) argv;								/* from the Workbench */
		if (program_icon = GetDiskObject((char *) wbs->sm_ArgList->wa_Name)) {	/* get the program icon */
			return ((char **) program_icon->do_ToolTypes);								/* return tooltypes */
		}
	}
	return NULL;
}

/* My version of ArgString
 * returns   : string result
 * parameters: arg1 - parameter array
 *             arg2 - parameter name
 *             arg3 - default value
 */
UBYTE *
ArgString( UBYTE **arg1, UBYTE *arg2, UBYTE *arg3 ) {
	UBYTE *s;
	if (arg1) {
		if (s = FindToolType(arg1,arg2)) {
			return s;
		}
	}
	return arg3;
}

/* The following defines are what make this code specific to MPMorph
 * they could be changed for another program
 */
/*#define PREFSDIR "ENV:MPMorph/"		// Directory where prefs may be held */
/*#define PREFSFILE "Morph.prefs"	// Name of prefs file */
/*#define PREFSFILE "Render.prefs"	// Name of prefs file */

struct DiskObject	*project_icon 			= NULL;	/* The project Icon */
char					**project_settings	= NULL;	/* Parameters on project Icon */
extern char			**ArgArray;							/* Program Parameter/ToolTypes */
extern char			**ArgArraySettings;				/* Parameters from settings file */

BOOL					FromWB;								/* Are we shell or Workbench */

/* Similar to ArgArrayInit but knows
 * how to handle settings files
 * does not return a value - it is held in this file
 */
void
MyArgArrayInit(int argc,char **argv,char *prefsfile,char *prefsdir) {
	BPTR 	oldcurrentdir 	= NULL;	/* Remember the current dir */
	BPTR 	settings			= 0;		/* Settings file handle */
	UBYTE	string[65];					/*	buffer to read in (should not be limited size) */
	int 	kount				= 0,		/* number of settings strings in file */
			kount1			= 0;		/* index */
	UBYTE *settingsname;				/* file name of settings */
	BPTR	projectdir		= 0;		/* project directory */
	struct WBStartup	*argmsg;		/* Workbench message */
	struct WBArg 		*wb_arg;		/* Workbench argument */
	char filename[256];

	/* check if from workbench	*/
	if (!argc) {
		FromWB = TRUE;
  		argmsg = (struct WBStartup *)argv;
		if (argmsg->sm_NumArgs > 1) {
			wb_arg = argmsg->sm_ArgList;
	 		wb_arg++;
		 	projectdir = wb_arg->wa_Lock;					/* set up project dir for settings file */
			oldcurrentdir = CurrentDir(projectdir);	/* switch to project dir */
			if (project_icon = GetDiskObject((char *) wb_arg->wa_Name)) {
				project_settings = (char **) project_icon->do_ToolTypes;	/* and get project tool types if poss. */
			}
			CurrentDir(oldcurrentdir);						/* switch back to original dir */
			oldcurrentdir = NULL;
		}
	}
	else {
		FromWB = FALSE;
	}
	/* Do normal ArgArrayInit */
	ArgArray = argArrayInit(argc,argv);
	/* Get name of settings file */
	ArgArraySettings = NULL;
	settingsname = ArgString(project_settings,(char *)"SETTINGS",NULL);	/* first from SETTINGS= on project */
	if (settingsname) {
		settings = Open(settingsname,MODE_OLDFILE);					/* try and open if present */
	}
	if (!settings) {
		settingsname = ArgString(ArgArray,(char *)"SETTINGS",NULL);		/* if not open try Program parameters/tool types SETTINGS= */
	}
	/* try and open */
	if (settingsname && !settings) {
		settings = Open(settingsname,MODE_OLDFILE);					/* and try and open if present */
	}
	if (!settings) {
		/* if not open then if from WorkBench then change
		 * to the project dir, if from CLI try current dir
		 */
		if (projectdir) {
			oldcurrentdir = CurrentDir(projectdir);
		}
		if (!(settings = Open(settingsname = prefsfile,MODE_OLDFILE))) {	/* try and open again in "current" dir */
			/* change back if it did not open */
			if (projectdir) {
				CurrentDir(oldcurrentdir);
			}
		}
	}
	/* if still not open then try program directory */
	if (!settings) {
		strcpy(filename,"PROGDIR:");
		strcat(filename,prefsfile);
		settings = Open(settingsname = filename,MODE_OLDFILE);	/*	try and open again in program dir */
	}
	/* still not open so try ENV: */
	if (!settings) {
		strcpy(filename,prefsdir);
		strcat(filename,prefsfile);
		settings = Open(settingsname = filename,MODE_OLDFILE);	/* and again!!! in ENV:/xxx/ */
	}
	if (settings) {																		/* We have a settings file!!! */
		/* If we have found a file then count the relevant lines */
		while (FGets(settings,string,64)) {		/* read in each line */
			if ((string[0] != '\n') &&				/* ignore blank lines */
				 (string[0] != ';')) {				/* and commented out lines */
				++kount;									/* count the rest */
			}
		}
		Close(settings);								/* close the file */
		if (settings = Open(settingsname,MODE_OLDFILE)) {	/* reopen it (why not seek?) */
			/* Allocate memory for settings from file pointers (including zero at end */
			if (ArgArraySettings = AllocVec((kount+1) * sizeof(UBYTE *),MEMF_CLEAR)) {
				/* Read in all settings */
				while (FGets(settings,string,64) &&
						 (kount1 < kount)) {									/* Do not do too many */
					/* remove newline (from FGets) */
					string[strlen(string)-1] = '\0';
					/* ignore blank and comment lines */
					if (string[0] && (string[0]!=';')) {
						/* Clone settings in memory */
						ArgArraySettings[kount1] = strdup(string);	/* Note! */
						++kount1;												/* strdup() not AllocMem() etc. */
					}																/* so memory is only freed on quit */
				}
			}
			/* Close file and change directory back if required */
			Close(settings);
		}
		if (oldcurrentdir) {
			CurrentDir(oldcurrentdir);
		}
	}
}

/* Similar to ArgArrayDone but knows
 * how to handle settings files
 */
void
MyArgArrayDone(void) {
	/* Call argArrayDone */
	argArrayDone();
	/* and free settings file pointers */
	if (ArgArraySettings) {
		FreeVec(ArgArraySettings);
		ArgArraySettings = NULL;
	}
	/* and the project icon */
	if (project_icon) {
		FreeDiskObject(project_icon);
		project_icon = NULL;
	}
}

/* Similar to ArgString but knows
 * how to handle settings files
 * missing parameter: arg1   - is internal
 * extra parameter  : reopen - set if this is not the initial call but just a new project
 */
UBYTE *
MyArgString(UBYTE *arg2,UBYTE *arg3,BOOL reopen) {
	UBYTE *s;
	/* Look in project Parameters first */
	if (project_settings) {
		if (s = FindToolType(project_settings,arg2)) {
			return s;
		}
	}
	if (!reopen) {
		/* then look in parameters */
		if (ArgArray) {
			if (s = FindToolType(ArgArray,arg2)) {
				return s;
			}
		}
		/* then in settings file */
		if (ArgArraySettings) {
			if (s = FindToolType(ArgArraySettings,arg2)) {
				return s;
			}
		}
	}
	return arg3;
}

/* Similar to ArgInt but knows
 * how to handle settings files
 * See MyArgString() for different parameters
 */
ULONG
MyArgInt(UBYTE *arg2, ULONG arg3,BOOL reopen) {
	UBYTE *s;
	ULONG ret;
	if (s = MyArgString(arg2,NULL,reopen)) {
		StrToLong(s,(LONG *)&ret);
		return ret;
	}
	return arg3;
}

/* Similar to FindToolType but knows
 * how to handle settings files
 * See MyArgString() for different parameters
 */
BOOL MyFindToolType(UBYTE *arg2,BOOL reopen) {
	if (MyArgString(arg2,NULL,reopen)) {
		return TRUE;
	}
	return FALSE;
}	

/* Opens a new project parameters
 * Frees old Icon and opens new, if from Workbench
 * filename must be full file name
 */
void OpenNewArgs(UBYTE *filename) {
	if (FromWB) {
		if (project_icon) {
			FreeDiskObject(project_icon);
		}
		if (project_icon = GetDiskObject(filename)) {
			project_settings = (char **) project_icon->do_ToolTypes;
		}
		else {
			project_settings = NULL;
		}
	}
}
