
#include <dos/dos.h>
#include <dos/dostags.h>

#include <exec/types.h>
#include <intuition/classes.h>
#include <gadgets/textfield.h>

/* Libraries */
#include <libraries/mui.h>
#include <libraries/asl.h>

/* protos */
#include <clib/muimaster_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/asl_protos.h>

/*  Pragmas  */
#include <pragmas/muimaster_pragmas.h>
#include <pragmas/exec_pragmas.h>

/*  Ansi  */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>

/* MUIBuilder */
#include "MyEd.h"

#ifdef MUZAK
#include "LinkPlay.h"
static BOOL muzakon=FALSE;
#endif

/* Get rid of SAS breaks */
int CXBRK(void) { return(0); }
int _CXBRK(void) { return(0); }
void chkabort(void) {}

char MyExtHelp[] ="\nUsage : Geditor TEXT=FILENAME FONT=FONTNAME SIZE=FONTSIZE SCREEN=PUBLICSCREEN BASE=MUIBASE\n\n";

char *CMD_TEMPLATE = "TEXT/A,FONT/K,SIZE/N,SCREEN/K,BASE/K";

BOOL fontuse=FALSE;
BOOL baseuse=FALSE;
static struct TextAttr usefont = {NULL,0,0,0};
static char fontname[256];
static char pscreen[256];
static char base[256];

#define OPT_TEXT 0
#define OPT_FONT 1
#define OPT_SIZE 2
#define OPT_SCREEN 3
#define OPT_BASE 4
#define OPT_COUNT 5

BOOL show_bodytext = FALSE;
char *body_text = NULL;

char filename[1024];

struct Library * MUIMasterBase;
struct Library *AslBase;


#ifdef MUZAK
static __saveds __asm ULONG MuzakFunc(register __a0 struct Hook *hook,
									register __a2 Object *appl,
									register __a1 ULONG *arg)
{
#ifdef GLUEDEB
	printf("Muzak\n\n");
#endif
	if (muzakon)
	{
		muzakon=FALSE;
		stopmusic();
	}
	else
	{
		muzakon=TRUE;
		startmusic(0);
	}
	return(0L);
}

static struct Hook MuzakHook = {{NULL, NULL},(void *)MuzakFunc,NULL,NULL};

#endif

/*
 * ARexx hooks
 */

static struct Gadget *kludgegadget=NULL;
static struct Window *kludgewindow=NULL;

void DoIncludeText(char* incfile,struct Gadget *gadget,struct Window *window);

static __saveds __asm ULONG IncludeFunc(register __a0 struct Hook *hook,
									register __a2 Object *appl,
									register __a1 char** arg)
{
#ifdef GLUEDEB
	printf("ARexx include file: '%s'\n",arg[0]);
#endif
	DoIncludeText(arg[0],kludgegadget,kludgewindow);

	return(0L);
}

static __saveds __asm ULONG GotoFunc(register __a0 struct Hook *hook,
									register __a2 Object *appl,
									register __a1 char** arg)
{
	long charpos=0;
#ifdef GLUEDEB
	printf("Arexx goto: '%s'\n",arg[0]);
#endif
	if (!stricmp(arg[0],"FIRST"))
		charpos=0;
	else if (!stricmp(arg[0],"LAST"))
		charpos=0xffffffff;
	else if (stcd_l(arg[0],&charpos))
		;
	else
		return(5L);

#ifdef GLUEDEB
	printf("Arexx goto parsed: '%ld'\n",charpos);
#endif
	SetGadgetAttrs(kludgegadget, kludgewindow, NULL, TEXTFIELD_CursorPos, charpos, TAG_DONE);


	return(0L);
}

static struct Hook IncludeHook = {{NULL, NULL},(void *)IncludeFunc,NULL,NULL};

static struct Hook GotoHook = {{NULL, NULL},(void *)GotoFunc,NULL,NULL};

static struct MUI_Command Arexx_list[] =
{
	{"OK",			MC_TEMPLATE_ID,	OK,				NULL},
	{"CANCEL",		MC_TEMPLATE_ID,	Cancel,			NULL},
	{"INCLUDE",		"FILE/A",			1,					&IncludeHook},
	{"SAVE",			MC_TEMPLATE_ID,	Save,				NULL},
	{"CUT",			MC_TEMPLATE_ID,	Edit_Cut,		NULL},
	{"COPY",			MC_TEMPLATE_ID,	Edit_Copy,		NULL},
	{"PASTE",		MC_TEMPLATE_ID,	Edit_Paste,		NULL},
	{"CLEAR",		MC_TEMPLATE_ID,	Edit_Clear,		NULL},

	{"GOTO",			"INDEX/A",			1,					&GotoHook},
#ifdef MUZAK
	{"MUZAK",		NULL,					0,					&MuzakHook},
#endif

};

/*
 *  ASL file requester function
 */

char *requestfile(char *title,char *pattern,char *file,BOOL saveflag,struct Window *window)
{
	struct FileRequester *req;
	ULONG funcflags;

	static char oldpath[1024]="";

	static char buffer[1024];

  if (saveflag)
    funcflags = FILF_SAVE;
  else
    funcflags = 0;

  if (req=AllocAslRequest(ASL_FileRequest,NULL))
	{
		AslRequestTags(req,
									ASL_Hail,title,
									ASL_Dir,oldpath,
									ASL_Pattern,pattern,
									ASL_File,file,
									ASL_FuncFlags, funcflags,
									ASLFR_Window, window,
									TAG_DONE);

		if (strlen(req->fr_File)==0)
		{
			buffer[0]='\000';
		}
		else
		{
			strcpy(oldpath,req->fr_Drawer);
			strcpy(buffer,req->fr_Drawer);
			if ((strlen(buffer)>0) && (buffer[strlen(buffer)-1]!=':'))
				strcat(buffer,"/");
			strcat(buffer,req->fr_File);
		}
		FreeAslRequest(req);
	}
	else
		buffer[0]='\000';

  return(buffer);
}


void DoIncludeText(char* incfile,struct Gadget *gadget,struct Window *window)
{
	char *incbuffer = NULL;

#ifdef GLUEDEB
	printf("Include file: '%s'\n",incfile);
#endif
	if (strlen(incfile)>0)
	{
		BPTR lock;
		if (lock = Lock (incfile, SHARED_LOCK))
		{
			struct FileInfoBlock *fib;

			if (fib = (struct FileInfoBlock *) AllocDosObject (DOS_FIB, NULL))
			{
#ifdef GLUEDEB
				printf("\nFile present\n\n");
#endif
				if (Examine (lock, fib))
				{
#ifdef GLUEDEB
					printf("\nFile size: %d\n\n",fib->fib_Size);
#endif
					if (incbuffer = (char *) malloc (fib->fib_Size + 1))
					{
						int fd;

						if (fd = open (incfile,O_RDONLY,0))
						{
							read(fd,incbuffer, fib->fib_Size);
							close (fd);
							incbuffer[fib->fib_Size]='\000';
#ifdef GLUEDEB
							printf("\nFile read:\n{\n %s\n}\n\n",incbuffer);
#endif
						}
						else
						{
							/* unable to open infile */
						}

					}
					else
					{
					}
				}

				FreeDosObject (DOS_FIB, fib);
			}
			else
			{
				/* unable to alloc dos object */
			}
			UnLock (lock);
		}
		else
		{
			fprintf (stderr,"File '%s' not found\n",incfile);
		}

		if (window)
		{
			SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_InsertText, incbuffer, TAG_DONE);
			SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Modified, TRUE, TAG_DONE);
		}
		else
		{
#ifdef GLUEDEB
			printf("No window\n");
#endif
		}
	}

#ifdef GLUEDEB
			printf("Before free\n");
#endif
	if (incbuffer)
		free (incbuffer);

#ifdef GLUEDEB
			printf("After free\n");
#endif
}


void ClearText(struct Gadget *gadget,struct Window *window)
{
	SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Text, "", TAG_DONE);
/*
	SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_InsertText, incbuffer, TAG_DONE);
	SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Modified, TRUE, TAG_DONE);
*/
}


void IncludeText(struct Gadget *gadget,struct Window *window)
{
	static char incfile[1024];

	strcpy(incfile,requestfile("Include...","#?","",FALSE,window));
	DoIncludeText(incfile,gadget,window);
}


void SaveText(struct Gadget *gadget,struct Window *window)
{
	char *text;
	ULONG size;
	ULONG modified;

	if (window)
	{
		// Set to readonly mode so I can grab the text from the gadget
		SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_ReadOnly, TRUE, TAG_DONE);
		GetAttr(TEXTFIELD_Size, gadget, &size);
		GetAttr(TEXTFIELD_Text, gadget, (ULONG *)&text);
		GetAttr(TEXTFIELD_Modified, gadget, &modified);
#ifdef GLUEDEB
		printf("Modified: %d\n",modified);
#endif
		if (text && size && modified)
		{
			int fd;

			if (fd = creat (filename,0))
			{
				write(fd,text,size);
				close (fd);
			}
			SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Modified, FALSE, TAG_DONE);

		}
		SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_ReadOnly, FALSE, TAG_DONE);
	}
	else
	{
#ifdef GLUEDEB
		printf("No window\n");
#endif
	}
}


/* Init function */
static int
init (int argc, char **argv)
{
	int retval = 0;

	if (!(MUIMasterBase = OpenLibrary (MUIMASTER_NAME, MUIMASTER_VMIN)))
	{
		fprintf (stderr,"Can't Open MUIMaster Library");
		retval = 20;
	}

	if (!(AslBase = OpenLibrary("asl.library", 37L)))
	{
		fprintf (stderr,"Can't Open ASL Library");
		retval = 20;
	}

	if ((retval == 0) && (argc))
	{
		/* see if the big dummy is asking for help? */
		if ((argc == 2) && (stricmp (argv[1], "HELP") == 0))
		{
			/* yeh, wouldn't you know it - You Dumb Shit! */
			fprintf (stdout, "%s", MyExtHelp);
			retval = 20;
		}
		else
		{
			/* this guy seems serious.... */
			/* My custom RDArgs */
			struct RDArgs *myrda;

			/* Need to ask DOS for a RDArgs structure */
			if (myrda = (struct RDArgs *) AllocDosObject (DOS_RDARGS, NULL))
			{
				/*
				 * The array of LONGs where ReadArgs() will store the data from
				 * the command line arguments.  C guarantees that all the array
				 * entries will be set to zero.
				 */
	      	LONG *result[OPT_COUNT] = {NULL};

				/* lets see how serious he is - parse my command line */
				if (ReadArgs (CMD_TEMPLATE, (LONG *)result, myrda))
				{
#ifdef GLUEDEB
						printf("\nParsed TEXT: %s\n\n",result[OPT_TEXT]);
						if (result[OPT_SIZE]) printf("\nParsed FONT: %s\n\n",result[OPT_FONT]);
						if (result[OPT_SIZE]) printf("\nParsed SIZE: %d\n\n",*result[OPT_SIZE]);
#endif

					if (show_bodytext = (result[OPT_TEXT]) ? TRUE : FALSE)
					{
						BPTR lock;

#ifdef GLUEDEB
						printf("\nParsed TEXT: %s\n\n",result[OPT_TEXT]);
#endif
						strcpy(filename,(char *)result[OPT_TEXT]);
						if (lock = Lock ((char *)filename, SHARED_LOCK))
						{
							struct FileInfoBlock *fib;

							if (fib = (struct FileInfoBlock *) AllocDosObject (DOS_FIB, NULL))
							{
#ifdef GLUEDEB
								printf("\nFile present\n\n");
#endif
								if (Examine (lock, fib))
								{
#ifdef GLUEDEB
									printf("\nFile size: %d\n\n",fib->fib_Size);
#endif
									if (body_text = (char *) malloc (fib->fib_Size + 1))
									{
										int fd;

										if (fd = open ((char *)filename,O_RDONLY,0))
										{
											read(fd,body_text, fib->fib_Size);
											close (fd);
											body_text[fib->fib_Size]='\000';
#ifdef GLUEDEB
											printf("\nFile read:\n{\n %s\n}\n\n",body_text);
#endif
										}
										else
										{
											/* unable to open infile */
										}

									}
									else
									{
									}
								}

								FreeDosObject (DOS_FIB, fib);
							}
							else
							{
								/* unable to alloc dos object */
							}
							UnLock (lock);
						}
						else
						{
#ifdef GLUEDEB
							printf ("File '%s' not found\n",filename);
#endif
						}
					}

					if (result[OPT_FONT]&&result[OPT_SIZE])
					{
#ifdef GLUEDEB
						printf ("Got font...\n");
#endif
						strcpy(fontname,(char*)result[OPT_FONT]);
						usefont.ta_Name=fontname;
						usefont.ta_YSize=*result[OPT_SIZE];
						fontuse=TRUE;
					}

					if (result[OPT_BASE])
					{
#ifdef GLUEDEB
						printf ("Got base...\n");
#endif
						strcpy(base,(char*)result[OPT_BASE]);
						baseuse=TRUE;
					}

					if (result[OPT_SCREEN])
					{
#ifdef GLUEDEB
						printf ("Got a screen...\n");
#endif
						strcpy(pscreen,(char*)result[OPT_SCREEN]);
					}
					else
						pscreen[0]=NULL;
				}
				else
				{
					retval = 20;	/* nah, he screwed it up - something went wrong in the parse */
				}

					FreeArgs (myrda);

				if (retval >= 20)
				{
					fprintf (stderr, "Try - Geditor HELP for options.\n");
				}

				FreeDosObject (DOS_RDARGS, myrda);
			}
			else
			{
				/* Unable to alloc readargs structure */
				retval = 20;
			}
		}
	}
	else
	{
		/* launched from workbench */
		retval = 20;
	}

	return (retval);
}

/* main function */
int
main (int argc, char **argv)
{
	int retval = 0;

	struct ObjApp * App = NULL;	/* Application object */
	BOOL	running = TRUE;
	ULONG	signal;

	/* Program initialisation ( you need to write it yourself) */
	if ((retval = init (argc, argv)) != 0)
	{
		/* Ate shit and died! */
		goto oops;
	}

	/* Create Application : generated by MUIBuilder */
	if (App = CreateApp(baseuse?base:NULL));
	{
		struct Window *window;
		struct Gadget *gadget;

		GetAttr(MUIA_Boopsi_Object, App->text, (ULONG *)&gadget);
#ifdef GLUEDEB
			printf("window: %0lx, gadget: %0lx\n",window,gadget);
#endif

		SetGadgetAttrs(gadget, NULL, NULL, TEXTFIELD_Modified, FALSE, TAG_DONE);
		if (fontuse) SetGadgetAttrs(gadget, NULL, NULL, TEXTFIELD_TextAttr, &usefont, TAG_DONE);

		if (pscreen[0])
		{
#ifdef GLUEDEB
			printf("Screen: %s\n",pscreen);
#endif
			set(App->Geditor,MUIA_Window_PublicScreen,pscreen);
			set(App->about,MUIA_Window_PublicScreen,pscreen);
		}
		else
		{
#ifdef GLUEDEB
			printf("No screen\n");
#endif
		}

		set(App->App,MUIA_Application_Commands,&Arexx_list);

		set(App->Geditor,MUIA_Window_Open, TRUE);

		GetAttr(MUIA_Window_Window, App->Geditor, (ULONG *)&window);

#ifdef GLUEDEB
			printf("window: %0lx, gadget: %0lx\n",window,gadget);
#endif
		kludgewindow=window;
		kludgegadget=gadget;

		while (running)
		{
			switch (DoMethod(App->App,MUIM_Application_Input,&signal))
			{
			case MUIV_Application_ReturnID_Quit:
				running = FALSE;
				break;

			case OK:
#ifdef GLUEDEB
				printf("OK\n");
#endif
				SaveText(gadget,window);
				running = FALSE;
				break;

			case Cancel:
#ifdef GLUEDEB
				printf("Cancel\n");
#endif
				running = FALSE;
				break;

			case Include:
#ifdef GLUEDEB
				printf("Include\n");
#endif
				IncludeText(gadget,window);
				break;

			case Save:
#ifdef GLUEDEB
				printf("Save\n");
#endif
				SaveText(gadget,window);
				break;

			case Edit_Cut:
#ifdef GLUEDEB
				printf("Cut\n");
#endif
				if (window)
					SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Cut, 0, TAG_DONE);
				break;

			case Edit_Copy:
#ifdef GLUEDEB
				printf("Copy\n");
#endif
				if (window)
					SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Copy, 0, TAG_DONE);
				break;

			case Edit_Paste:
#ifdef GLUEDEB
				printf("Paste\n");
#endif
				if (window)
					SetGadgetAttrs(gadget, window, NULL, TEXTFIELD_Paste, 0, TAG_DONE);
				break;

			case Edit_Clear:
#ifdef GLUEDEB
				printf("Clear\n");
#endif
				ClearText(gadget,window);
				break;

			}
			if (running && signal) Wait(signal);
		}
		DisposeApp(App);
	}

oops:
	if (body_text)
		free (body_text);

	CloseLibrary(AslBase);
	CloseLibrary(MUIMasterBase);

#ifdef MUZAK
	if (muzakon)
		stopmusic();
#endif
	exit(retval);
}
