// TSMorph - 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 TSMorph and TSMorph-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>
#include <proto/icon.h>
#include <proto/dos.h>
#include <proto/exec.h>
#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!!!!!
		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 TSMorph
 * they could be changed for another program
 */
#define PREFSDIR "ENV:TSMorph/"		// Directory where prefs may be held
#define PREFSFILE "TSMorph.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) {
	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
	/* 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,"SETTINGS",NULL);	// first from SETTINGS= on project
	if (settingsname) {
		settings = Open(settingsname,MODE_OLDFILE);					// try and open if present
	}
	if (!settings) {
		settingsname = ArgString(ArgArray,"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) {
		settings = Open(settingsname = "PROGDIR:"PREFSFILE,MODE_OLDFILE);	//	try and open again in program dir
	}
	// still not open so try ENV:
	if (!settings) {
		settings = Open(settingsname = PREFSDIR PREFSFILE,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
 */
LONG
MyArgInt(UBYTE *arg2, long arg3,BOOL reopen) {
	UBYTE *s;
	LONG ret;
	if (s = MyArgString(arg2,NULL,reopen)) {
		StrToLong(s,&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;
		}
	}
}
