#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <libraries/dosextens.h>
#include <exec/types.h>
#include <exec/nodes.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <stdio.h>
#include "df1:iff/jiff.h"

#define ESC		0x1b
#define EDITORDIR 	"sys:c"	/* Where to find it */
#define EDITCMD		"e" /* Name of program */
#define	EDITNAMELENGTH 	7	/* Change this when making changes */
#define RAMED 		"ram:EDITOR"	/* Where it ends up */
#define RAMEDLEN	10	/* Must equal length of name */	
#define FBSIZE  (long)(sizeof (struct FileInfoBlock))
#define MAXFILE		100
#define MAXFNAME	16
#define MAXCHAR		30
#define MAXCD		255

#define SLIDE_GADGET	0
#define ERR_GADGET	2
#define EXECUTE_GADGET  3
#define CURDIR_GADGET	4
#define CPDIR_GADGET	5

#define DF0_GADGET	6
#define DF1_GADGET	7
#define DF2_GADGET	8
#define DF3_GADGET	9

#define RAM_GADGET	10
#define DH0_GADGET	11
#define DH1_GADGET      12
#define DH2_GADGET	13

#define SINFO_GADGET	14
#define DINFO_GADGET	15
#define DELDIR_GADGET	16
#define DELETE_GADGET   17

#define SWAP_GADGET	18
#define SEARCH_GADGET   19
#define EXEC_GADGET     20
#define BYTE_GADGET     21

#define MAKDIR_GADGET	22
#define GETDIR_GADGET   23
#define EDIT_GADGET     24
#define HTYPE_GADGET	25

#define RENAME_GADGET	26
#define MOVE_GADGET	27
#define TYPE_GADGET     28
#define PRINT_GADGET    29 
     
#define CLEAR_GADGET    30
#define ALL_GADGET	31
#define PARENT_GADGET	32
#define ROOT_GADGET	33
#define COPY_GADGET	34
#define SHOW_GADGET	35

#define BUT_FIRST DF0_GADGET
#define FIRST_GADGET	But_gad[SHOW_GADGET-6]
#define Kill_EDITOR	But_gad[EDIT_GADGET-6]
#define BUT_LAST	SHOW_GADGET
#define WinIDCMP  CLOSEWINDOW | REFRESHWINDOW | GADGETUP | MOUSEBUTTONS
#define GADFLAGS  NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,NULL,NULL,NULL,NULL,NULL
#define GADTEXT 3,2,JAM2,0,0,NULL
extern struct FileHandle  *Open();
/* extern APTR AllocMem(); */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct IntuiMessage *message;
struct RastPort *rp;
struct RastPort ShowAllRastPort;
struct Screen *ShowAllScreen = NULL;
struct Window *w;
struct Window *pic_window;
struct LayerBase *LayersBase;

struct TextAttr ShowAllFont =
    {
	(UBYTE *) "topaz.font", 
	8,
	0,
	0,
    };

static struct NewScreen ShowAllNewScreen =
	{
	0, 0, XMAX, YMAX, PLANES,
	0, 1,
	0,
	CUSTOMSCREEN,
	&ShowAllFont,
	(UBYTE *) "",
	NULL,
	NULL,
	};

static
struct NewWindow MyWindow =
	{
	0,0,14,10,
	0,1,
	CLOSEWINDOW | MOUSEBUTTONS | MOUSEMOVE | ACTIVEWINDOW | INACTIVEWINDOW,
	SMART_REFRESH | ACTIVATE | WINDOWCLOSE | REPORTMOUSE | BORDERLESS,
	NULL,
	NULL,
	(UBYTE *) "",
	NULL,
	NULL,
	14,10,14,10,
	CUSTOMSCREEN,
	};


/*Error Gadget string gadget*/
USHORT str_pairs2[] = { 0,0,  639,0,  639,9,  0,9, 0,0,};
struct Border str_border2 =
{
	-1,-1,/*Leftedge, Topedge*/
	1,1,JAM1,/*FrontPen, BackPen, Drawmode*/
	5,	/*Number of Pairs*/
	(APTR) &str_pairs2,  /*XY, Pointer to XY pairs*/
	NULL,
};

/*Error display*/
char err_buf[MAXCD+1];
struct StringInfo err_str =
{ &err_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };

struct Gadget Err_gad =
{
	NULL, /*last in the list of gadgets*/
	10,144,
	622,9,
	GADGHCOMP, GADGIMMEDIATE | RELVERIFY | STRINGCENTER,
	STRGADGET,
	(APTR) &str_border2,
	NULL,
	NULL,  /*Intuitext pointer*/
	0,&err_str,
	ERR_GADGET,
	NULL,
};

/*Source Destination string gadgets*/
USHORT str_pairs[] = { 0,0,  280,0,  280,9,  0,9, 0,0,};
struct Border str_border =
{
	-1,-1,/*Leftedge, Topedge*/
	1,1,JAM1,/*FrontPen, BackPen, Drawmode*/
	5,	/*Number of Pairs*/
	(APTR) &str_pairs,  /*XY, Pointer to XY pairs*/
	NULL,
};

/* Execute String Gadget */
struct IntuiText Exe_text = {1,0,JAM1,283,0,NULL,"E",NULL,};
char Exe_buf[MAXCD+1];
struct StringInfo Exe_str =
{ &Exe_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };
struct Gadget Exe_gad =
{
	&Err_gad,
	345,114,
	278,9,
	GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
	STRGADGET,
	(APTR) &str_border,
	NULL,
	&Exe_text,
	0,
	&Exe_str,
	EXECUTE_GADGET,
	NULL,
};

struct IntuiText Curdir_text = {1,0,JAM1,283,0,NULL,"S",NULL,};
char cd_buf[MAXCD+1];
struct StringInfo Curdir_str =
{ &cd_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };
struct Gadget Curdir_gad =
{
	&Exe_gad,
	345,124,
	278,9,
	GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
	STRGADGET,
	(APTR) &str_border,
	NULL,
	&Curdir_text,
	0,
	&Curdir_str,
	CURDIR_GADGET,
	NULL,
};

/*Destination definitions*/
char cp_buf[MAXCD+1];
struct IntuiText Cpdir_text = {1,0,JAM1,283,0,NULL,"D",NULL,};
struct StringInfo Cpdir_str =
{ &cp_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };

struct Gadget Cpdir_gad =
{
	&Curdir_gad,
	345,134,
	278,9,
	GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
	STRGADGET,
	(APTR) &str_border,
	NULL,
	&Cpdir_text,
	0,
	&Cpdir_str,
	CPDIR_GADGET,
	NULL,
};

/*File Select Gadget Declarations*/
struct Image slide_img;
struct PropInfo slide_prop;
struct Gadget Slide_gad =
{
	&Cpdir_gad,  /*Next gadget*/
	322,12,	  /*Left, Top edge*/
	20,132,	  /*Width Height*/
	GADGHNONE,   /*Flags*/
	GADGIMMEDIATE | RELVERIFY,
	PROPGADGET,  /*Gadget type*/
	(APTR)&slide_img,   /*Border definition*/
	NULL, /*Select render*/
	NULL,	  /*Gadget text*/
	0,	  /*MutualExclude*/
	(APTR) &slide_prop, /*Special Info - proportional specification*/
	SLIDE_GADGET,
	NULL,
};

/*Button Gadget IDs*/

struct IntuiText But_text[] =
{
	GADTEXT,"  DF0:  ",NULL,
	GADTEXT,"  DF1:  ",NULL,
	GADTEXT,"  DF2:  ",NULL,
	GADTEXT,"  DF3:  ",NULL,
	GADTEXT,"  RAM:  ",NULL,
	GADTEXT,"  DH0:  ",NULL,
	GADTEXT,"  DH1:  ",NULL,
	GADTEXT,"  DH2:  ",NULL,
	GADTEXT," SINFO  ",NULL,
	GADTEXT," DINFO  ",NULL,
	GADTEXT," DELDIR ",NULL,
	GADTEXT," DELETE ",NULL,
	GADTEXT,"  SWAP  ",NULL,
	GADTEXT," SEARCH ",NULL,
	GADTEXT,"  RUN   ",NULL,
	GADTEXT,"  BYTE  ",NULL,
	GADTEXT," MAKDIR ",NULL,
	GADTEXT," GETDIR ",NULL,
        GADTEXT,"  EDIT  ",NULL,
	GADTEXT," HTYPE  ",NULL,
	GADTEXT," RENAME ",NULL,
	GADTEXT,"  MOVE  ",NULL,
	GADTEXT,"  TYPE  ",NULL,
	GADTEXT,"  PRINT ",NULL,
	GADTEXT," CLEAR  ",NULL,
	GADTEXT,"   ALL  ",NULL,
	GADTEXT," PARENT ",NULL,
	GADTEXT,"  ROOT  ",NULL,
	GADTEXT,"  COPY  ",NULL,
	GADTEXT,"  SHOW  ",NULL,
};

struct Gadget But_gad[] =
{
	GADFLAGS,DF0_GADGET,NULL,
	GADFLAGS,DF1_GADGET,NULL,
	GADFLAGS,DF2_GADGET,NULL,
	GADFLAGS,DF3_GADGET,NULL,
	GADFLAGS,RAM_GADGET,NULL,
	GADFLAGS,DH0_GADGET,NULL,
	GADFLAGS,DH1_GADGET,NULL,
	GADFLAGS,DH2_GADGET,NULL,
	GADFLAGS,SINFO_GADGET,NULL,
	GADFLAGS,DINFO_GADGET,NULL,
	GADFLAGS,DELDIR_GADGET,NULL,
	GADFLAGS,DELETE_GADGET,NULL,
	GADFLAGS,SWAP_GADGET,NULL,
	GADFLAGS,SEARCH_GADGET,NULL,
	GADFLAGS,EXEC_GADGET,NULL,
	GADFLAGS,BYTE_GADGET,NULL,
	GADFLAGS,MAKDIR_GADGET,NULL,
	GADFLAGS,GETDIR_GADGET,NULL,
	GADFLAGS,EDIT_GADGET,NULL,
	GADFLAGS,HTYPE_GADGET,NULL,
	GADFLAGS,RENAME_GADGET,NULL,
	GADFLAGS,MOVE_GADGET,NULL,
	GADFLAGS,TYPE_GADGET,NULL,
	GADFLAGS,PRINT_GADGET,NULL,
	GADFLAGS,CLEAR_GADGET,NULL,
	GADFLAGS,ALL_GADGET,NULL,
	GADFLAGS,PARENT_GADGET,NULL,
	GADFLAGS,ROOT_GADGET,NULL,
	GADFLAGS,COPY_GADGET,NULL,
	GADFLAGS,SHOW_GADGET,NULL,
};

/*BORDER DEFINITION FOR FILE SELECT AREA*/
USHORT Fil_pairs[] = { 10,13,  321,13,  321,144, 10,144, 10,13,};
struct Border Fil_border =
{
	-1,-1,	 /*Leftedge, Topedge*/
	1,0,JAM1,	 /*FrontPen, BackPen, Drawmode*/
	5,		  /*Number of Pairs*/
	(APTR) Fil_pairs,   /*XY, Pointer to XY pairs*/
	NULL,	 /*More borders*/
};


struct NewWindow nw =
{
	0,10,
	640,154,
	0,1,		 /* Detail, block pens */
	WinIDCMP,	 /* IDCMP flags */
	WINDOWSIZING | WINDOWDEPTH | WINDOWDRAG | REPORTMOUSE | WINDOWCLOSE
	| ACTIVATE | RMBTRAP | SMART_REFRESH,
	&FIRST_GADGET, /* First gadget in the list */
	NULL,	 /* User checkmark */
	"DirUtil II - Version 4.0 ",
	NULL,  
	NULL,	 /* Pointer to superbitmap */
	100,40,640,149,  /* Now sizeable */
	WBENCHSCREEN,
};

/*The following structure is used to hold the directory entries*/
struct DirTable
{
	char  dt_fname[MAXCHAR];/* File name */
	short dt_select; /* Select flag */
	short dt_dir;	/* Directory flag */
	long  dt_size;	/* File size */
};

struct DirTable dirtable[MAXFILE+1];
struct InfoData *InfoData;
struct FileLock *InitialCurrentDirLock, *CurrentDirLock, *RAMEDLOCK, *fl;
struct FileHandle *window = NULL; /*file handle for type & print*/
struct FileHandle *workfp = NULL; /*file handle to file to be displayed*/
struct ILBM_info *info = NULL;
long bytes;
int files;
int ac;
int numdir;
int cur_index;
int NILFD = 0;
int linecount;
unsigned int index;
int done = FALSE;
char curdir[MAXCD+1],requestedcd[MAXCD+1];
char command[300];
unsigned char buffer[80];
unsigned char buf[512];
unsigned char blank[37] = "                                    ";
void	Print_to_printer(), copy(), new_dir(), ShowAll(), quit_ShowAll(),
	sel_file(), par_dir(), Print_to_screen(), Hprint_to_screen(),
	MyOpen(), DoHex(), MyDone(), WaitSpace(), DoHeader(), MyClose(),
	put_ea_cmap(),Search(),GotOne();
struct FileLock *oldlock;

main(argc,argv)
char *argv[];
{
	struct Gadget *gad_ptr;
	struct IntuiText *text_ptr;
	ULONG MessageClass;
	USHORT code;
	register i;
	char editorname[EDITNAMELENGTH];
	ac = argc;
	if((argc>2) || ((argc==2) && (!strcmp(argv[1],"?")))) {
		printf("Usage: %s [editor]\n\n", *argv);
		exit();
		}
	/* If the editor option is used, the default editor command is     */
	/* loaded into the RAM disk and will appear in the DirUtil listing */
	/* for RAM: but it can not be deleted while your are still in      */
	/* DirUtil.  Upon calling, DirUtil will look for a text editor     */
	/* in SYS:c having the name EDIT.  A copy of this program will     */
	/* be placed in RAM: and locked.  If you are running multiple      */
	/* DirUtil's, the succeeding DirUtil's will not be able to make    */
	/* a RAM: copy of EDIT, but the first copy will still be there,    */
	/* I think...							   */

	if((argc==0) || ((argc==2) && (!strcmp(argv[1],"EDITOR"))) ||
	    ((argc==2) && (!strcmp(argv[1],"editor")))) {
		if(!(NILFD = Open("nil:", MODE_OLDFILE))) {
			if(ac == 2) {
				puts("DirUtil FATAL: Can't open NIL:\n");
				exit();
			}
		}
		sprintf(editorname,"%s/%s",EDITORDIR,EDITCMD);
		copy(editorname, "ram:");
		if(!(RAMEDLOCK = Lock(RAMED,ACCESS_READ))) {
			if(ac==2) {
				printf("DirUtil FATAL: Can't get lock on %s\n",RAMED);
				exit();
			}
		}
	}

	*cp_buf = 0;
	strcpy(curdir,"ram:");
	strcpy(requestedcd,curdir);
	if(!(CurrentDirLock = Lock(curdir,ACCESS_READ))) {
		if (ac == 2) {
			puts("DirUtil FATAL: Could not lock RAMdisk!\n");
			close_things(); 
			exit();
		}
	}
	InitialCurrentDirLock = CurrentDir(CurrentDirLock);

	/*Gadget initialization*/
	slide_prop.Flags = FREEVERT | AUTOKNOB;
	slide_prop.VertBody = 0;
	slide_prop.VertPot = 0x8000;

	/*Setup the button gadgets*/
	for (i=0;i<(BUT_LAST-BUT_FIRST)+1;i++) {
		gad_ptr = &But_gad[i];
		text_ptr = &But_text[i];

		gad_ptr->LeftEdge = ((i%4) * 71) + 347;
		gad_ptr->TopEdge = ((i/4) * 12) + 12;

		if(i)
			gad_ptr->NextGadget = &But_gad[i-1];
		else
			gad_ptr->NextGadget = &Slide_gad;
		gad_ptr->GadgetText = text_ptr;
		text_ptr->LeftEdge = 0;
		text_ptr->TopEdge = 0;
	}

GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",(long)0); 
LayersBase = (struct LayersBase *) OpenLibrary("layers.library", (long)0);
IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",(long)0);

if (!(w = (struct Window *) OpenWindow(&nw) )) {
	if (ac == 2) puts("Could not open window\n");
	close_things();	exit();
}
	rp = w->RPort;
	DrawBorder(rp,&Fil_border,0,0);

	getdir(curdir);
	new_dir();

	display_error("O.K.",0);
	RefreshGadgets(&FIRST_GADGET,w,NULL);
	if(!RAMEDLOCK) OffGadget(&Kill_EDITOR,w,NULL);

	for (;;) {
		WaitPort(w->UserPort); 
		message = (struct IntuiMessage *) GetMsg(w->UserPort);
		MessageClass = message->Class;
		code = message->Code;
		ReplyMsg(message);
		switch (MessageClass) {
			case GADGETUP:
			case GADGETDOWN:
				display_error("O.K.",0);
				do_gadgets(message,w);
				break;

			case REFRESHWINDOW:
				BeginRefresh(w); EndRefresh(w);
				dis_files(cur_index);
				DrawBorder(rp,&Fil_border,0,0);
				break;

			case CLOSEWINDOW:
				close_things(); exit();
				break;

			case MOUSEBUTTONS:
				if (code == SELECTDOWN) sel_file();
				break;
			default:
				break;
		} /*end switch*/
	} /*end for*/
}

Info2(dir)
char *dir;
{
InfoData = AllocMem(sizeof(struct InfoData),0);
fl = Lock(dir,ACCESS_READ);
Info(fl,InfoData);
sprintf(command,"%d Usable Bytes Free",((InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed - 2) <= 0) ? 0 : ((InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed - 2) * InfoData->id_BytesPerBlock));
display_error(command,0);
FreeMem(InfoData,sizeof(struct InfoData));
UnLock(fl);
}

do_gadgets(mes,win)
struct IntuiMessage *mes;
struct Window *win;
{
	struct FileLock *MakeDirLock;
	struct Gadget *igad;
	int gadgid;		 /*ID Code identifying which gadget*/
	unsigned short i;

	igad = (struct Gadget *) mes->IAddress;
	gadgid = igad->GadgetID;
	switch (gadgid) {
		case CURDIR_GADGET:
			ModifyIDCMP(w,0);
			nullterm(cd_buf,MAXCD);
			Curdir_str.NumChars = strlen(cd_buf);
			Curdir_str.BufferPos = strlen(cd_buf);
			getdir(cd_buf);
			new_dir();
			ModifyIDCMP(w,WinIDCMP);
			break;
		case CPDIR_GADGET:
			nullterm(cp_buf,MAXCD);
			Cpdir_str.NumChars = strlen(cp_buf);
			Cpdir_str.BufferPos = strlen(cp_buf);
			break;
		case EXECUTE_GADGET:
			nullterm(Exe_buf,MAXCD);
			Exe_str.NumChars = strlen(Exe_buf);
			Exe_str.BufferPos = strlen(Exe_buf);
			break;
		case SLIDE_GADGET:
			rdis_files();
			break;
		case ROOT_GADGET:
		case PARENT_GADGET:
			par_dir(gadgid);
			break;
		case SHOW_GADGET:
			display_error("Now showing selected pictures",0);
		case DELETE_GADGET:
		case COPY_GADGET:
		case RENAME_GADGET:
		case TYPE_GADGET:
		case HTYPE_GADGET:
		case PRINT_GADGET:
		case EXEC_GADGET:
		case MOVE_GADGET:
		case SEARCH_GADGET:
		case DELDIR_GADGET:
			action_on_selected(gadgid);
			break;
		case EDIT_GADGET:
			display_error("Now editing selected files",0);
			action_on_selected(gadgid);
			break;
		case SWAP_GADGET:
			strcpy(command,cd_buf);
			strcpy(cd_buf,cp_buf);
			strcpy(cp_buf,command);
			Cpdir_str.NumChars = strlen(cp_buf);
			Cpdir_str.BufferPos = strlen(cp_buf);
			RefreshGadgets(&Cpdir_gad,w,NULL);
			getdir(cd_buf);
			new_dir();
			break;
 		case SINFO_GADGET:
			Info2(cd_buf);
			break;
		case DINFO_GADGET:
			Info2(cp_buf);
			break;
		case BYTE_GADGET:
			bytes = 0;
			files = 0;
			for (i=0;i<numdir;i++)
			if ((dirtable[i].dt_select == 1) && (!(dirtable[i].dt_dir))) {
				bytes = bytes + dirtable[i].dt_size;
				files++;
			};
			sprintf(command,"%d Bytes in %d Files",bytes,files);
			display_error(command,0);
			break;
		case MAKDIR_GADGET:
		/*Attempt to create the named directory. Note that since
		the CurrentDir is whatever is in the CurrentDir gadget,
		if you don't give a complete path name, it will assume
		to create the directory in the current directory.
		Also, 1.1 CreateDir does not care if you try to create
		a directory entry on top of a file of the same name.
		Code around this...*/
			if(MakeDirLock = Lock(cp_buf,ACCESS_READ)) {
				UnLock(MakeDirLock);
				display_error("Directory or File Already Exists " ,IoErr());
				break;
			} 
			if (!(MakeDirLock = CreateDir(cp_buf))) {
				display_error("CreateDir Failed ",IoErr());
				break;
			}
			UnLock(MakeDirLock);
			getdir(curdir); new_dir(); break;
		case DF0_GADGET:
			getdir("df0:"); new_dir(); break;
		case DF1_GADGET:
			getdir("df1:"); new_dir(); break;
		case DF2_GADGET:
			getdir("df2:"); new_dir(); break;
		case DF3_GADGET:
			getdir("df3:"); new_dir(); break;
		case RAM_GADGET:
			getdir("ram:"); new_dir(); break;
		case DH0_GADGET:
			getdir("dh0:"); new_dir(); break;
		case DH1_GADGET:
			getdir("dh1:"); new_dir(); break;
		case DH2_GADGET:
			getdir("dh2:"); new_dir(); break;
		case GETDIR_GADGET: 
			getdir(requestedcd);
			new_dir();
			break;
		case CLEAR_GADGET:
			for (i=0;i<numdir;i++)
			dirtable[i].dt_select = 0;
			dis_files(cur_index);
			break;
		case ALL_GADGET:
			for (i=0;i<numdir;i++)
			if (!dirtable[i].dt_dir) dirtable[i].dt_select = 1;
			dis_files(cur_index);
			break;
		default:
			break;
	}
}

getdir(DirToGet) 
char *DirToGet;
{
	struct FileLock *filelock;
	struct FileInfoBlock *fb;
	char EffectiveDir[MAXCD+1];

	if (!(*DirToGet)) strcpy(EffectiveDir,":");
	else strcpy(EffectiveDir,DirToGet);

	/* If we cant open requested dir, don't change */
TRYAGAIN:
	if (!(filelock = Lock(EffectiveDir,ACCESS_READ))) {
		strcpy(EffectiveDir,curdir);
		display_error("Can't Lock Requested Directory ",IoErr());
		if(!(filelock = Lock(EffectiveDir,ACCESS_READ))) {
			display_error("Can't Lock Current Dir. Switching to Ram: ",IoErr());
			strcpy(EffectiveDir,"ram:");
			goto TRYAGAIN;
		}
	}
	/* Allocate the file info block */
	fb = AllocMem(FBSIZE,MEMF_CLEAR | MEMF_PUBLIC);
	if (!Examine(filelock,fb)) {
		FreeMem(fb,FBSIZE);
		UnLock(filelock);
		display_error("Can't Read Info Block. Switching to Ram: ",IoErr());
		strcpy(EffectiveDir,"ram:");
		goto TRYAGAIN;
	}
	if(fb->fib_DirEntryType < 0) {  /*ITS A FILE- NOT A DIRECTORY*/
		strcpy(EffectiveDir,curdir);/*Forget request, use current*/
		FreeMem(fb,FBSIZE);
		UnLock(filelock);
		display_error("Directory Requested was Regular File - No Changes ",IoErr());
		goto TRYAGAIN;
	}

	/*Copy directory string into gadget structure*/
	strcpy(cd_buf,EffectiveDir);
	Curdir_str.NumChars = strlen(EffectiveDir);
	Curdir_str.BufferPos = strlen(EffectiveDir);
	strcpy(curdir,EffectiveDir);
	strcpy(requestedcd,EffectiveDir);
	RefreshGadgets(&Cpdir_gad,w,NULL);

	numdir = 0;
	cur_index = 0;

	/*Loop through each of the files in this directory*/
	while (ExNext(filelock,fb)) {
		if (fb->fib_DirEntryType < 0) dirtable[numdir].dt_dir = 0;
		else dirtable[numdir].dt_dir = -1;
		dirtable[numdir].dt_select = 0;
		dirtable[numdir].dt_size = fb->fib_Size;
		strcpy(dirtable[numdir].dt_fname,fb->fib_FileName);
		nullterm(dirtable[numdir].dt_fname,MAXCHAR);

		if (++numdir == MAXFILE) break;
	}

	qsort(dirtable,numdir,(sizeof (struct DirTable))); 
	FreeMem(fb,FBSIZE);
	UnLock(CurrentDirLock); /*Release old CD lock */
	UnLock(filelock);	 /*Release new request lock*/
	CurrentDirLock = Lock(EffectiveDir);
	CurrentDir(CurrentDirLock); /*MAKE IT THE CURRENT DIRECTORY*/
}

rdis_files()
{
 USHORT Vpot;
	int numd;
	int pos;

	if (numdir > MAXFNAME) {
	Vpot = slide_prop.VertPot;
		Vpot >>= 1;
		Vpot &= 0x7fff;
		numd = numdir - MAXFNAME;
		pos = ((float) Vpot / (float) 0x7fff) * numd;
		cur_index = pos;
		dis_files(pos);
	}
}

void new_dir()
{
	USHORT Vbody;

	if (numdir <= MAXFNAME) 
		Vbody = 0xffff;
	else {
		Vbody = ((float) 0x7fff)/(((float) numdir)/((float) MAXFNAME));
		Vbody <<= 1;
	}
	cur_index = 0;
	ModifyProp(&Slide_gad,w,NULL,slide_prop.Flags,0,0,0,Vbody);
	dis_files(0);
	return;
}

dis_files(pos)
int pos;
{
	register i;

	for (i=0;i<MAXFNAME;i++) dis_name(i+pos,i);
}

dis_name(file,pos)
register file,pos;
{
static char file_name[MAXCHAR+8];
static struct IntuiText file_text = {2,0,JAM2,15,13,NULL,(UBYTE *)file_name,NULL };

	/*Set the top position*/
	file_text.TopEdge = (pos*8)+14;

	if (file == -1 || file >= numdir) {
		sprintf(file_name,"%-38.38s","");
		file_text.FrontPen = 2;
		file_text.BackPen = 2;  /*black*/
	} else {
		if (dirtable[file].dt_dir) {
			sprintf(file_name,"%-30.30s%-8.8s",dirtable[file].dt_fname,"");
			if (dirtable[file].dt_select) {
				file_text.FrontPen = 2; /*Black on Orange*/
				file_text.BackPen = 3;
			} else {
				file_text.FrontPen = 3; /*Orange on Black*/
				file_text.BackPen = 2;
			}
		} else {
			sprintf(file_name,"%-30.30s %7ld",dirtable[file].dt_fname,
			dirtable[file].dt_size);
			if (dirtable[file].dt_select) {
				file_text.FrontPen = 2; /*Black on White*/
				file_text.BackPen = 1;
			} else {
				file_text.FrontPen = 1; /*White on Black*/
				file_text.BackPen = 2;
			}
		}
	}

	/*Display the text*/
	PrintIText(rp,&file_text,0,0);
}

void sel_file()
{
	int file,i;
	char *ptr;

	if (message->MouseX < 12 || message->MouseX > 318 || message->MouseY < 14 || message->MouseY >= (MAXFNAME*8+14))
		return;
	file = message->MouseY - 14;
	file /= 8;
	if((!numdir) || (file > MAXFNAME) || ((file+cur_index) > numdir))
		return;

	/*Check to see if selection is a directory, or regular file  */
	/*For now, only allow one directory to be selected at a time */
	if (dirtable[file+cur_index].dt_dir) {
		for(i=0;i<numdir;i++)
		if((dirtable[i].dt_dir)&&(i != file+cur_index)) dirtable[i].dt_select = 0;
		ptr = curdir + strlen(curdir) - 1;
		if(dirtable[file+cur_index].dt_select ^= 1) 
			sprintf(requestedcd,"%s%s%s",curdir,((*ptr == ':') ? "":"/"),
			dirtable[file+cur_index].dt_fname);
		else
			strcpy(requestedcd,curdir);
		dis_files(cur_index);
		return;
	}
	dirtable[file+cur_index].dt_select ^= 1;
	dis_name(file+cur_index,file);
}

action_on_selected(gadgid)
int gadgid;
{
	struct IntuiMessage *message;
	register i, i1, temp;
	char filename[MAXCD+MAXCHAR+2];
	char *ptr;
	char command[MAXCD+MAXCHAR+2+RAMEDLEN]; /* See #defines */
	/* At each iteration, check for any IntuiMessages that would signal
	user wants to halt operation: GADGETUP(he hit a gadget) or
	MOUSEBUTTONS(button press on something we dont recognize) */

	ModifyIDCMP(w,GADGETUP | MOUSEBUTTONS);
	for (i=0;i<numdir;i++) {
		if((gadgid != SHOW_GADGET) && (message = (struct IntuiMessage *) GetMsg(w->UserPort))) {
			ReplyMsg(message);
			display_error("OPERATION ABORTED",0);
			break; 
		}	
		if (dirtable[i].dt_select) {
			ptr = curdir + strlen(curdir)-1;
			if (*ptr == ':')
				sprintf(filename,"%s%s",curdir,dirtable[i].dt_fname);
			else
				sprintf(filename,"%s/%s",curdir,dirtable[i].dt_fname);

			switch (gadgid) {
				case DELETE_GADGET:
					if(dirtable[i].dt_dir) {
						display_error("File is a Directory",0);
						break;
					}
					if(!(DeleteFile(filename))) 
						display_error("Could Not Delete Requested File ",IoErr());
					else dirtable[i].dt_select = 2;
					break;

				case DELDIR_GADGET:
					if(!dirtable[i].dt_dir) {
						display_error("File is not a Directory",0);
						break;
					}
					if(!(DeleteFile(filename))) 
						display_error("Could not Delete Requested Directory ",IoErr());
					else dirtable[i].dt_select = 2;
					break;

				case COPY_GADGET:
					copy(filename,cp_buf);
					break;

				case SHOW_GADGET:
					sprintf(command,"%s",filename);
					if(!dirtable[i].dt_dir) ShowAll(filename);
					break;
				case EXEC_GADGET:				
					sprintf(command,"%s %s %s","RUN > NIL:",filename,Exe_buf);
					if (ac == 0) Execute(command,0,NILFD);
					else Execute(command,0,0);
					break;
				case TYPE_GADGET:
					if(!dirtable[i].dt_dir) Print_to_screen(filename);
					break;
				case HTYPE_GADGET:
					if(!dirtable[i].dt_dir) Hprint_to_screen(filename);
					break;
				case PRINT_GADGET:
					if(!dirtable[i].dt_dir) Print_to_printer(filename);
					break;
				case MOVE_GADGET:
				ptr = cp_buf + strlen(cp_buf)-1;
				if (*ptr == ':')
					sprintf(command,"%s%s",cp_buf,dirtable[i].dt_fname);
				else
					sprintf(command,"%s/%s",cp_buf,dirtable[i].dt_fname);
				if(!(Rename(filename,command)))
					display_error("Cannot Rename to Requested Path ",IoErr());
				else dirtable[i].dt_select = 2;
				break;
				case SEARCH_GADGET:
					if(dirtable[i].dt_dir == 0) Search(filename);
					break;
				case RENAME_GADGET:
				/*NOTE: you must select the file to be renamed -
				   this doesnt check cp_buf for a filename!*/
					if(!(Rename(filename,cp_buf))) 
						display_error("Cannot Rename to Requested Path ",IoErr());
					break;
				case EDIT_GADGET:
					if(!dirtable[i].dt_dir) 
					  if(NILFD) {
						sprintf(command,"%s %s",RAMED,filename);
						Execute(command,0,NILFD);
						}
					break;
				default:
				break;
			} /*switch*/
if ((gadgid != DELDIR_GADGET) && (gadgid != DELETE_GADGET) && (gadgid != MOVE_GADGET)) dirtable[i].dt_select = 0;
if(RENAME_GADGET == gadgid) break; /*RENAME FIRST FILE ONLY!*/
		} /*if selected*/
	} /*for all*/

if(RENAME_GADGET == gadgid) getdir(curdir);
else {
temp = numdir;
for (i1=0;i1<numdir;i1++) 	
	if (dirtable[i1].dt_select == 2) {
		strcpy(dirtable[i1].dt_fname,"\xff\xff\xff");
		temp--; 
};
if (numdir != temp) qsort(dirtable,numdir,(sizeof (struct DirTable))); 
numdir = temp;
}; 
new_dir(); 

ModifyIDCMP(w,WinIDCMP);
}

void par_dir(gadgid) /* Parent and Root */
	int gadgid; {
	char *ptr;		 /* With this, we may change curdir */

	ModifyIDCMP(w,0);
	ptr = curdir+strlen(curdir)-1;
	if(PARENT_GADGET == gadgid)
		for (;ptr >= curdir;ptr--) {
			if (*ptr == ':') { 
				*(ptr+1) = 0; 
				break;
			}
			if (*ptr == '/') { 
				*ptr = 0;
				break;
			}
		}
	else /*Gadget was root. Scan back to :*/
		for (;ptr >= curdir;ptr--) 
			if (*ptr == ':') {
				*(ptr+1) = 0;
				break;
			}

	getdir(curdir);
	new_dir();
	ModifyIDCMP(w,WinIDCMP);
	return;
}

/*The following function is used to compare two directory entries*/
comp(dt1,dt2)
struct DirTable *dt1,*dt2;
{
	char *ptr1,*ptr2;
	register c1,c2;

	for (ptr1=dt1->dt_fname,ptr2=dt2->dt_fname;*ptr1 && *ptr2;ptr1++,ptr2++) {
		c1 = *ptr1;
		c2 = *ptr2;

		c1 &= 0xdf;
		c2 &= 0xdf;

		if (c1 > c2) return (-1);

		if (c1 < c2) return (1);
	}

	if (*ptr1) return (-1);

	return (0);
}

void copy(s,pc)
char *s;
char *pc;
{
	struct FileHandle  *copyin;
	struct FileHandle  *copyout;
	int iosize;
	int actual;
	char *copybuf;
	struct FileLock *fl;
	char *ptr;
	char *ptr1;

	if (!(copyin = Open(s,MODE_OLDFILE)))
		return;

	if (!*pc) {
		display_error("No Destination Path Given",0);
		return;
	}

	if ((fl = Lock(pc,ACCESS_READ))) {
		UnLock(fl);
		ptr = strlen(pc) + pc - 1;
		for (ptr1=s+strlen(s)-1;ptr1 > s;ptr1--) {
			if (*ptr1 == '/' || *ptr1 == ':')
				break;
		}
		if (*ptr1 == '/' || *ptr1 == ':')
			ptr1++;
		if (*ptr == ':')
			sprintf(command,"%s%s",pc,ptr1);
		else
		 sprintf(command,"%s/%s",pc,ptr1);
	} else {
		display_error("Illegal Destination Path ",IoErr());
		Close(copyin);
		return;
	}

	if (!strcmp(command,s)) {
		display_error("Cannot Copy File to Itself",0);
		Close(copyin);
		return;
	}

	if (!(copyout = Open(command,MODE_NEWFILE))) {
		display_error("Cannot Write to Requested Path ",IoErr());
		Close(copyin);
		return;
	} else {
		/*Determine the length of the file*/
		iosize = Seek(copyin,0,OFFSET_BEGINING);
		iosize = 12288;
		/*Allocate memory for the copy buffer*/
		do {
			copybuf = AllocMem(iosize,MEMF_PUBLIC);
			if (copybuf == 0)
				iosize = iosize/2;
		} while (copybuf == 0 & iosize > 512);

		/*Copy the file*/
		do {
			actual = Read(copyin,copybuf,iosize);
			if (Write(copyout,copybuf,actual) != actual)
				break;
		} while (actual == iosize);

		/*Free the copy buffer*/
		FreeMem(copybuf,iosize);

		/*Close the input and output buffers*/
		Close(copyout);
		Close(copyin);
	}
}

nullterm(str,len) /*End a string with a null*/
char *str;
int len;
{
	register i;

	str[len] = 0; 
	for (i=len;len >= 0;len--) {
		if (str[i] != ' ' && str[i])
			break;
		str[i] = 0;
	}
}

display_error(errormsg,doserrnum)
char *errormsg;
long doserrnum;
{
	strcpy(err_buf,errormsg);
 	if (doserrnum) sprintf(err_buf,"%s (DOS Error %d)",err_buf,doserrnum);
	err_str.NumChars = strlen(err_buf);
	err_str.BufferPos = strlen(err_buf);
	RefreshGadgets(&Err_gad,w,NULL);
}

close_things()
{
	if (w) CloseWindow(w);
	if (GfxBase) CloseLibrary(GfxBase);
	if (LayersBase) CloseLibrary(LayersBase);
	if (IntuitionBase) CloseLibrary(IntuitionBase);
	UnLock(RAMEDLOCK);
	DeleteFile(RAMED);
	Close(NILFD);
	if (InitialCurrentDirLock) {
		CurrentDir(InitialCurrentDirLock);
		UnLock(CurrentDirLock);
 }
}

qsort( v, n, size)
char *v;
short n;
int size;
{
	short gap, i, j;
	register x;
	char temp, *p1, *p2;
	for (gap=n/2;gap > 0; gap /= 2)
		for (i=gap; i<n; i++)
			for (j = i-gap; j >= 0; j -= gap)
				if ( comp((p1=v+j*size), (p2=v+(j+gap)*size)) < 0) {  
					/*exchange them*/
					for (x=0; x<size; x++) {
						temp = *p1;
						*p1++ = *p2;
						*p2++ = temp;
					}
				}
}

void Print_to_screen(ptr)
char *ptr[];
{

register i, len, len2; 

MyOpen(ptr);
DoHeader(); 
if (!done)
	do{
		len = Read(workfp,buf,512);
		len2 = 0;
		while (len2<len && done == FALSE){
			for (i=len2; buf[i] != 0x0a && i<511; i++)
			if (buf[i] == 0x0c) buf[i] = 0x20;			
			Write(window,&buf[len2],i-len2+1);
			len2 = i + 1;
			if (++linecount > 21 && buf[i] == 0x0a) WaitSpace();
		}
	}while(len == 512 && done == FALSE);
        MyDone();
	MyClose();
	return;
}

void Print_to_printer(ptr)
char *ptr[];
{

register len; 
done = FALSE; /*boolean variables*/

	workfp = Open(ptr,MODE_OLDFILE); /*Try to open the file to print*/
	if(workfp == NULL) done = TRUE;
	else {
		window = Open("prt:",MODE_NEWFILE);
		if(window == NULL) done = TRUE;
	}
	if (!done)
		do{
			len = Read(workfp,buf,512);
			Write(window,&buf[0],len);
		}while(len == 512);

	MyClose();
	return;
}
void Hprint_to_screen(ptr)
char *ptr[];
{

register i, len, len2; 
char r1[2];
MyOpen(ptr);
DoHeader(); 
if (!done)
strcpy(buffer,"    -                                     ");
r1[0]=0x00;r1[1]=0x00;
	do{
		index = 0;
		DoHex(r1,2);
		r1[1] += 16;
		if (!(r1[1])) r1[0]++;
		index = 6;
		len = Read(workfp,buf,16);
		buf[len]=0x0a;
		DoHex(buf,len,6);
		if (len) {
			Write(window,&buffer[0],index);
			if (len != 16) Write(window,&blank[0],42-index);
			Write(window,&buf[0],len+1);
		};
		if (++linecount > 21) WaitSpace();
	}while ((len == 16) && (done == FALSE));
	MyDone();
	MyClose();
	return;
}

void Search(ptr)
unsigned char *ptr[];
{

	unsigned int actual,ind1 = 0, size, bufsize, len, j, i, fast=1;
	unsigned char argv2[60],c1,c2,c,z,*copybuf;

MyOpen(ptr);
if (!done) {

		len = strlen(Exe_buf);
		j=0;
		i=0;

while (i < len) {
	if (Exe_buf[i] != 0x5c) { argv2[j]=Exe_buf[i];
				  j++;
				  i++; 
	}
	else {  c1=Exe_buf[i+1];z=convert(c1);c1 = z<<4;
		c2=Exe_buf[i+2];z=convert(c2);c2 = z|c1;
		argv2[j]=c2;
		i = i+3;
		j++;
	}
}
		len = j;
		size = Seek(workfp,0,OFFSET_END);
		size = Seek(workfp,0,OFFSET_END);
		bufsize = size;
			copybuf = AllocMem(bufsize,0);
			if (copybuf == 0) {
				bufsize = len;
				copybuf = AllocMem(bufsize,0);
				fast = 0;
			}

  if (fast == 0) {
	strcpy(command,"Slow Search Required\n");
	Write(window,command,strlen(command));
	do {

			Seek(workfp,ind1,OFFSET_BEGINNING);
			actual = Read(workfp,copybuf,len);
			for (j=0;(((*(copybuf+j)) == argv2[j]) || argv2[j] == 0x3f) && (j<len);j++); 
			
			if (j==len) GotOne(ind1);

			ind1++;

		if(WaitForChar(window,1)) WaitSpace();

	} while((actual == len) && (done == FALSE)); 
  } else {
		strcpy(command,"Fast Search Enabled\n");
		Write(window,command,strlen(command));
		size = Seek(workfp,0,OFFSET_BEGINNING);
		actual = Read(workfp,copybuf,size);

	while((ind1 < size) && (done == FALSE)) {
		j = 0;
		while ((((*(copybuf+j+ind1)) == argv2[j]) || argv2[j] == 0x3f) && (j<len)) j++;

			if (j==len) GotOne(ind1);

			ind1++;
	} /* while*/
} /* If FAST MODE */

FreeMem(copybuf,bufsize);

MyDone();
} /* if no error */
MyClose();
} 

void GotOne(ind)
unsigned int ind;
{
	sprintf(command,"Hit at --> %7u  [$%6x]\n",ind,ind);
	Write(window,command,strlen(command));
	if (++linecount > 21) WaitSpace();
}

convert(c1) 
unsigned char c1;
{
if ((c1 > 0x2f) && (c1 < 0x3a)) return(c1 & 0x0f);
if ((c1 > 0x60) && (c1 < 0x67)) return(c1-87);
if ((c1 > 0x40) && (c1 < 0x47)) return(c1-55);
}

void DoHex(ptr2,len)
int len;
char ptr2[];
{
unsigned char c1,c2;
unsigned int i,i2=0;
for (i=0;i<len;i++) {
	c1 = ((ptr2[i] & 0xf0) >>4);
	c2 = (ptr2[i] & 0x0f);
		if (c1 > 9) c1 += 87;
			 else c1 += 48;
		if (c2 > 9) c2 += 87;
			 else c2 += 48; 
	buffer[index]=c1;
	buffer[index+1]=c2;
	if((buf[i] < 32) || (buf[i] > 127)) buf[i]=46;
	index += 2;
	if (++i2 == 4) {
			index++;
			i2=0;
	};
}
}

void MyOpen(ptr)
char *ptr[];
{ 
done = FALSE;
linecount = 1;
workfp = Open(ptr,MODE_OLDFILE);
if(workfp == NULL) done = TRUE;
else{
	strcpy(command,"raw:0/0/640/200/Listing of: ");
	strcat(command,ptr);
	window = Open(command,MODE_NEWFILE);
	if(window == NULL) done = TRUE;
}
}

void DoHeader()
{
strcpy(command,"\x1b[33m<CR>\x1b[2m advances one line, \x1b[33mSpace Bar\x1b[2m");
Write(window,command,strlen(command));
strcpy(command," advances one page, and \x1b[33mESC\x1b[2m aborts.\n\x1b[0m");
Write(window,command,strlen(command));
}

void WaitSpace()
{
unsigned char c;

	linecount = 1;
	/*print the messages in color 3*/
	strcpy(command,"\x1b[33mPress SPACE for more...\x1b[0m");
	Write(window,command,strlen(command));
	/*wait for a key*/
	while(Read(window,&c,1),c != ' ') {
		if (c == ESC){
		done = TRUE; /*short circuit*/
		break;
		}
		/*RETURN scrolls by one line*/
		else if (c == '\r'){
			linecount = 21;
			break;
			}
	}
/*erase the message*/
strcpy(command, "\r                        \r");
Write(window,command,strlen(command));
}

void MyDone()
{
unsigned char c;
	strcpy(command,"\r\x1b[33mEnd of File.  Press SPACE\x1b[0m");
	Write(window,command,strlen(command));
	/*Wait for spacebar to quit*/
	while(Read(window,&c,1),c != ' ');
}
void MyClose()
{
	if(workfp) Close(workfp);
	if(window) Close(window);
}

void ShowAll(Picture)
char *Picture[];
{
int i = 0, class;
	if ( (info = read_iff(Picture, 0) ) != NULL)
		{
		ShowAllNewScreen.LeftEdge = info->header.x;
		ShowAllNewScreen.TopEdge = info->header.y;
		ShowAllNewScreen.Width = info->header.w;
		ShowAllNewScreen.Height = info->header.h;
		ShowAllNewScreen.Depth = info->header.nPlanes;
		ShowAllNewScreen.ViewModes = 0;   /*start at default */
		if (ShowAllNewScreen.Depth == 6)
			ShowAllNewScreen.ViewModes |= HAM;
		if (ShowAllNewScreen.Width > 320)
			ShowAllNewScreen.ViewModes |= HIRES;
		if (ShowAllNewScreen.Height > 200)
			ShowAllNewScreen.ViewModes |= LACE;
		if ( (ShowAllScreen = OpenScreen(&ShowAllNewScreen) ) == NULL)
			{
			display_error("Not Enough Memory Available\n",0);
			free_planes(&info->bitmap);
			quit_ShowAll();
			return;
			}
		MyWindow.Screen=ShowAllScreen;
		if ((pic_window = OpenWindow(&MyWindow)) == NULL)
			{
			display_error("Not Enough Memory Available\n",0);
			free_planes(&info->bitmap);
			quit_ShowAll();
			return;
			}
		InitRastPort(&ShowAllRastPort);
		ShowAllRastPort.Mask = (1<<PLANES)-1;  /*just play it safe in case someone
											tries to load 6 bit planes...*/

		put_ea_cmap(&info->cmap, (1 << info->bitmap.Depth));
		ShowAllRastPort.BitMap = &info->bitmap;
		ClipBlit( &ShowAllRastPort, (long)0, (long)0,
			&ShowAllScreen->RastPort, (long)info->header.x, (long)info->header.y,
			(long)info->header.w, (long)info->header.h, (long)COPY_MINTERM);
		
		for (;;) {
			WaitPort(pic_window->UserPort);
			message = GetMsg(pic_window->UserPort);
			class=message->Class;
			ReplyMsg(message);
			if(class == CLOSEWINDOW){
				CloseWindow(pic_window);
				free_planes(&info->bitmap);
				quit_ShowAll();
				return;
				}
			}
		}
	else
		{
		sprintf(buffer,"Couldn't load %s as an IFF file!",Picture);
		display_error(&buffer,0);
		return;
		}
}

void quit_ShowAll()
{
	CloseScreen(ShowAllScreen);
	ShowAllScreen = NULL;
	return;
}

void put_ea_cmap(cmap, colors)
unsigned char *cmap;
int colors;
{
unsigned short amy_cmap[MAXCOL];
int i;
unsigned char r, g, b;

if (colors > MAXCOL)	/*color clipping*/
	colors = MAXCOL;
for (i=0; i<colors; i++)
	{
	amy_cmap[i] = 
		((*cmap++ & 0xf0) << 4) + (*cmap++ & 0xf0) + ((*cmap++ & 0xf0) >> 4);
	}
LoadRGB4( &ShowAllScreen->ViewPort, amy_cmap, (long)colors);
}


