#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <inline/stubs.h>
#ifdef __OPTIMIZE__
#include <inline/exec.h>
#include <inline/dos.h>
#include <inline/intuition.h>
#else
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#endif

int	 atexit(void (*)(void));

/* build_argc_argv will build the argv array pointer and store
   the number of arguements in argc. The length of the provided
   commandline or the number of arguements should not be limited too much.
   I think 100 (MAX_TEMPLATE_ITEMS) arguements should be enough

	We also have to parse workbench startups !
*/

/* things for commandline-parsing */

static struct RDArgs	*rda = NULL;	/* for CLI-startup */

static LONG **arguement_array=NULL;

static char *arguement_string=NULL;

static UBYTE	**ToolTypes=NULL; 	/* for WB-startup */


static char *MyGetProgramName(void);

UBYTE *__default_wb_window=NULL;

void destroy_argc_argv(void)
{
	/* Free all the space that was occupied by build_argc_argv */

	if(arguement_string)
		FreeVec(arguement_string);

	if(arguement_array)
	{
			/* Free Programm-name */

		if(arguement_array[0])
			FreeVec(arguement_array[0]);

		FreeVec(arguement_array);
	}

		/* free WB-arguments */

	if( ToolTypes )
	{
		ArgArrayDone();
	}


		/* Free arguments passed by commandline allocated by ReadArgs() */

	if( rda )
	{
		FreeArgs( rda );
		FreeDosObject( DOS_RDARGS, rda );
	}

}

BOOL build_argc_argv(int orig_d0, char *orig_a0, int *argc, char **argv[])
{
	/* We will store the name of our program in argv[0] */

	*argc=0;
    *argv=NULL;

	if(orig_d0)
	{
		/* start from CLI */
		/* parse arguements */

			/* copy the arguement string for security reasons */
    		/* first: get len, arguement string can be terminated by zero or return (0x0a) */

		char *s=orig_a0;
		int arguement_len=0;

		if(orig_a0)
		{
			while( (*s) && (*s !='\n'))
			{
				s++;
				arguement_len++;
			}

			if(arguement_len)
			{
					/* we need a zero-terminated buffer */

				if( (arguement_string=AllocVec(arguement_len+2,MEMF_CLEAR)) )
				{
					int x;

						/* copy commandline */

					for(x=0;x<arguement_len;x++)
						arguement_string[x]=orig_a0[x];


						/* terminate buffer with return for ReadArgs */

					arguement_string[x] = '\n';
					arguement_string[x+1] = 0;


				}
				else
				{
					/* out of memory error */
					return FALSE;
				}
			}
			else
			{
				/* the string is empty */
			}
		}
		else
		{
			/* we have a NULL-pointer, we can do nothing */
		}



		/* here we have a return-terminated string in arguement_string,
           or nothing */

		if(arguement_string)
		{
			/* Get memory for the arguement array */

			if( (arguement_array = AllocVec(sizeof(long)*110+100, MEMF_CLEAR)))
			{
					/* We have the memory */

					/* Set up arguement template */

				int x;
				UBYTE *template=(UBYTE *)&arguement_array[110];
				UBYTE *s=template;

				for(x=0;x<99;x++) *s++=',';

            		/* Set the program name */

				arguement_array[0] = (LONG *)MyGetProgramName();

					/* Do ReadArgs */

				if( (rda = (struct RDArgs *)AllocDosObject( DOS_RDARGS, NULL )))
				{
						/* Setup CSource */

                    rda->RDA_Source.CS_Buffer = arguement_string;
                    rda->RDA_Source.CS_Length = strlen(arguement_string);

					if(ReadArgs( template, (LONG *) &arguement_array[1], rda ) )
					{
						/* Args erfolgreich gelesen */

						/* Count args to store them in argc */

						int x=1;

						while( arguement_array[x] )
							x++;

						*argc=x;
						*argv=(char **)arguement_array;

					}
					else
					{
						/* ReadArgs error: give it to stdout */

						PrintFault(IoErr(), "");
						return FALSE;
					}
				}
				else
				{
					/* panic, we don't have the memory for RDArgs */
					return FALSE;
				}
			}
			else
			{
				/* panic, we don't have the memory for an arguement array */
				return FALSE;
			}
		}
		else
		{
			/* we have only to initialize argv[0]/[1] */

			if( (arguement_array = (LONG **)AllocVec(sizeof(long)*2, MEMF_CLEAR)))
			{
				arguement_array[0] = (LONG *)MyGetProgramName();
				*argc    = 1;
				*argv    = (char **)arguement_array;
			}
			else
			{
				/* panic, we don't have enough memory ! */
				return FALSE;
			}

		}
	}
	else
	{
		/* Workbench-Start, needs icon.library to be open !! */

		ToolTypes = (UBYTE **)ArgArrayInit((LONG)orig_d0,(UBYTE **)orig_a0);

		if(ToolTypes)
		{
			/* As we want to have our program name in argv[0], we have
				to copy the array

				first get the number of arguements : */

			int x=0;
			while(ToolTypes[x])
			{
				x++;
			}

			x++;	/* Add one entry for our argv[0] */
			x++;	/* Add one entry for argv[x]=NULL */

			if( (arguement_array = AllocVec(sizeof(long)*x, MEMF_CLEAR)))
			{
					/* We have the memory */

            		/* Set the program name */

				arguement_array[0] = (LONG *)MyGetProgramName();
							 *argc = x-1;


					/* copy arguements */

				x=0;
				while(ToolTypes[x])
				{
					arguement_array[x+1]=(LONG *)ToolTypes[x];
					x++;
				}

					/* now look at an entry that starts with "WINDOW=",
						we will cancel that entry */

				{
					int cancel_entry=0;
					x=1;

					while(arguement_array[x])
					{
						if(strncmp(arguement_array[x],"WINDOW=",7)==0)
						{
							cancel_entry=x;
							break;
						}
						x++;
					}

						/* remove the WINDOW-Entry */

					if(cancel_entry)
					{
						__default_wb_window = (UBYTE *)(arguement_array[cancel_entry]) + 7;
						*argc-=1;
						x=cancel_entry;
						while(arguement_array[x])
						{
							arguement_array[x]=arguement_array[x+1];
							x++;
						}
					}
				}

				*argv= (char **)arguement_array;
			}
			else
				return FALSE;
		}
	}


	return TRUE;
}



	/*
	 * MyGetProgramName()
	 *
	 * Returns a pointer to the name of the program. The User is responsible
	 * to free the pointer with FreeVec()!
	 *
	 * a maximum of 100 characters (incl. zero) are returned
     *
     * from WB there is no name, so you get a ZERO pointer!
	 */

static char *MyGetProgramName(void)
{
	UBYTE Buffer[100];

	if(GetProgramName(Buffer, 100))
	{
		char *mem=(char *)AllocVec(100, 0);
		if(mem)
			strcpy(mem, Buffer);

		return mem;
	}
	else
		return NULL;
}
