/* GadMGet.c  by Jeremy Friesner -- jfriesne@ucsd.edu  
   Version 2.05, released August 1, 1995*/

#ifndef MGET_C
#define MGET_C

#define INTUI_V36_NAMES_ONLY
#define MAXFILELINELENGTH 300 
#define MAXFILENAMELENGTH 300 
#define CHAR_NUL		(char)0
#define CHAR_SPACE		(char)32
#define CHAR_NEWLINE 		(char)10
#define CHAR_ESCAPE 		(char)27
#define CHAR_RETURN 		(char)13
#define INVALID 666

#define FIND_REQUESTTYPE 	0
#define LINELENGTH_REQUESTTYPE 	1
#define OUTPUTFILE_REQUESTTYPE 	2
#define SELECT_REQUESTTYPE      3
#define DESELECT_REQUESTTYPE    4

#define SEARCH_FORWARD 		1
#define SEARCH_BACKWARD 	2
#define SEARCHTYPE_BOTTOM 	1
#define SEARCHTYPE_TOP 		2
#define SEARCHTYPE_NEXT 	3
#define SEARCHTYPE_PREVIOUS 	4
#define SEARCHTYPE_FORWARD 	5
#define SEARCHTYPE_BACKWARD 	6

#define SORTBYDIR  		1
#define DIRNAMESIZE 		10

#define SORTBYNAME 		2
#define NAMESIZE 		20

#define SORTBYDESC 		3
#define DESCSIZE 		42

#define SORTBYSIZE 		4
#define SIZESIZE 		5

#define SORTBYAGE  		5
#define AGESIZE  		5

#define TREESORT   		1
#define BUBBLESORT 		2

#define ACTION_NONE		0x00
#define ACTION_SAVE		0x01
#define ACTION_OUTPUT		0x02

#define DEFAULT_EXECNAME	"GadMget"

#include "GadMget.h"

extern UWORD lastcode;
extern ULONG appwinsig;
extern struct NewGadget mgetNGad[];
extern struct Window *findwindow;
extern struct AppMessage *amsg;
extern struct MsgPort *awport;
extern struct AppWindow *appwin;
extern struct TextAttr listfont;

extern LONG lTreeTicker;
extern LONG lTreeSubTicker;
extern char *sTreeWriteHere;
extern char *szTickerString;

FILE *fpOut = stdout;
int IntuitionBase; 
ULONG winopenerror, lockscrnerror;
ULONG handlereturn;
BOOL done=FALSE,BStartedFromWB=FALSE;
char windowtitle[95] = "Loading...";

char sListFontName[36] = "";
int nListFontSize = 0;  /* Default to a bad value */
char version[] = "$VER: GadMget V2.05";
__far char template[] = "Template:  GadMGet FILE/A,OUTPUT/K,LINELENGTH/K,TOP/K,LEFT/K,\
WIDTH/K,HEIGHT/K,PUBSCREEN/K,WBSCREEN/S,DEFPUBSCREEN/S,NOFILES/S,GETREADMES/S,\
NOPARSE/S,CASESENSITIVE/S,SORTCASESENSITIVE/S,SEARCHCASESENSITIVE/S,NOCOMMAND/S,\
NOSPLIT/S,NOAPPWINDOW/S,COMMAND/K,NOSIMPLEPATHS/S,NOCD/S,HEADER/K,FOOTER/K,\
FONT/K,FONTSIZE/K,KEEPBLANKLINES/S,KEEPGETSORT/S,KEEPFILESORT/S,FILESORT/K,\
GETSORT/K,AMINETPATH/K,EOL/K,COMMENTCHAR/K,OMITCOMMENTS/K,LOADBUFFERS/K,\
CLOSEACTION/K\n";
char pnamestring[20],searchstring[MAXFILELINELENGTH];
char szPubScreenName[40],*pubscreenname = NULL,defDir[200],defFile[40];
char szCommandString[40] = "mget ";
__far char inputfile[MAXFILENAMELENGTH]="ram:RECENT";
const char szBookMark[]="| --- GadMGet: Begin Selected Files --- ";
char sEndOfLineString[10] = "\r\n";
char sAminetPathString[50] = "../../";
__far char sOutFileName[MAXFILENAMELENGTH]="";
__far char szHeaderFile[MAXFILENAMELENGTH];
__far char szFooterFile[MAXFILENAMELENGTH];
char sMultiSelect[150]="";
__far char szFilePattern[50]="#?";
char cCommentChar = '|';

char *pcWhatToAbort;
char *pcExecName=NULL;

int nTopListTop, nTopListHeight, nBottomListHeight;
int nSortType[2] = {SORTBYDIR, SORTBYDIR};
int nKeepSorted[2] = {FALSE, FALSE};
int Not[2] = {TRUE, FALSE};		/* NOT lookup array */
int nForTreeSortUseOnly;		/* only global because nested functions ain't happenin!  Don't use elsewhere! */
int nLoadBufferSize = 30 * 1024; 	/* default = 30k */
int nCloseAction = ACTION_OUTPUT;	/* default = output on close box click */

struct List *lForTreeSortUseOnly;

static char *szLoadBuffer1 = NULL;
static char *szLoadBuffer2 = NULL;
static char *szLoadBuffer3 = NULL;
static char *szLoadBufferT = NULL;
static char *pcLoadCurrent = NULL;
static char *pcEOFat	   = NULL;

/* Input column info */
static int nNameCol = 0;
static int nKCol    = 35;
static int nDirCol  = 21;
static int nAgeCol  = 35;  /* Note that this should be the RIGHT side of the age string! */
static int nPlusCol = 36;
static int nDescCol = 37;

/* default flags */
int 	screentype 		= USE_CUSTOMSCREEN,	
	getreadmes		= FALSE, 
	filesflag  		= TRUE,			/* get .lha files */
	filelist_length 	= 0, 			/* no files loaded */
     	getlist_length		= 0,			/* no files selected either */
	search_index		= 0,			/* buffer at first item */
	mgetfind_findtype   	= SEARCHTYPE_FORWARD,   /* global var used between mgetfind* */
	simplepaths 		= TRUE,			/* don't use ncftp style mgets */
	searchcasesensitive 	= FALSE,
	sortcasesensitive   	= FALSE,					
	maxoutputlinelength 	= 254, 			/* shell's limit */
	requesttype 	    	= FIND_REQUESTTYPE,     /* subwindow is for string searches */
	nSortAlgorithm      	= TREESORT,		/* default sort type */
	appwindow 		= TRUE,			/* = YES */

	omitcomments		= FALSE,		/* load comment lines */
	screenisopen 		= FALSE,		/* = NO */
	windowisopen 		= FALSE, 		/* = NO */
	noparse 		= FALSE,		/* = yes, parse */
	nocommand		= FALSE,		/* = yes, generate command */
	nosplit 		= FALSE,		/* = yes, split */
	nocd			= FALSE,		/* = generate CD commands */
	mgetNGad_height 	= 248,			/* default first listview height */
	keepblanklines		= FALSE;                /* = don't show blank lines */

ULONG kbytes_selected = 0;								
	 
UWORD 	windowwidth 	= MAXINT,	/* window will be sized to fill */
	windowheight  	= MAXINT,	/* screen unless these are */
	windowtop 	= 0, 		/* overridden by parameters */
	windowleft 	= 0;
		
void *findvi = NULL;

struct Library *Intuitionbase	= NULL;
struct GfxBase *GraphicsBase	= NULL;
struct Library *GadToolsBase	= NULL;
struct Library *UtilityBase	= NULL;
struct Library *AslBase		= NULL;
struct Library *IconBase	= NULL;
struct Library *WorkbenchBase	= NULL;

struct IntuiMessage *message 	= NULL;
struct List *filelist 		= NULL, 
	    *getlist 		= NULL;
struct Node *search_current 	= NULL;
struct Gadget *findgadlist 	= NULL;
struct TextFont *listfontdata 	= NULL;
struct DiskObject *appIconObj   = NULL;

__chip UWORD waitPointer[] =
	{
	0x0000, 0x0000,
	0x0400, 0x07c0,
	0x0000, 0x07c0,
	0x0100, 0x0380,
	0x0000, 0x07e0,
	0x07c0, 0x1ff8,
	0x1ff0, 0x3fec,
	0x3ff8, 0x7fde,
	0x3ff8, 0x7fbe,
	0x7ffc, 0xff7f,
	0x7efc, 0xffff,
	0x7ffc, 0xffff,
	0x3ff8, 0x7ffe,
	0x3ff8, 0x7ffe,
	0x1ff0, 0x3ffc,
	0x07c0, 0x1ff8,
	0x0000, 0x07e0,
	0x0000, 0x0000};
	

void debug(int a)
{
	fprintf(fpOut,"debug  %i\n",a);
	Delay(80);
}




void EOLParse(char *sString)
{
char sTempString[50], sTemp2[2] = " "; 
char * sCurrent = sString;
int i=0, nStringLength;

if (sString == NULL) return;
nStringLength = strlen(sString); 
memset(sTempString,CHAR_NUL,sizeof(sTempString));

while ((i<(sizeof(sTempString)-1))&&(*sCurrent != CHAR_NUL))
{
	if (*sCurrent == '\\')
	{
		sCurrent++; i++;
		switch(*sCurrent)
		{
			case 'r':
				strncat(sTempString,"\r",sizeof(sTempString));
			break;
			
			case 'n':
				strncat(sTempString,"\n",sizeof(sTempString));
			break;
		
			case CHAR_NUL:
				i = nStringLength + 1;	/* get out of the loop! */
			break;
			
			case '\\':
				strncat(sTempString,"\\",sizeof(sTempString));
			break;				
			
			default:
				sTemp2[0] = *sCurrent;
				strncat(sTempString,"\\",sizeof(sTempString));				
				strncat(sTempString,sTemp2,sizeof(sTempString));
				i++;
			break;
		}
	}
	else
	{
		sTemp2[0] = *sCurrent;
		strncat(sTempString, sTemp2, sizeof(sTempString));
		i++;
	}
	sCurrent++;
}
strncpy(sString,sTempString,nStringLength);
return;
}





/* If *index isn't NULL, that location will be set to the index
   value of the tail of the list */
struct Node * TailOf(struct List *thislist, int *index)
{
	struct Node *CurrentNode = thislist->lh_Head;
	int nTempIndex = 0;
	
	/* traverse to tail of list */
	while ((CurrentNode != NULL)&&(CurrentNode->ln_Succ != NULL))
	{
		nTempIndex++;
		CurrentNode = CurrentNode->ln_Succ;
	}

	if (index != NULL) *index = nTempIndex;

	return(CurrentNode);
}






/* Return index in list of the current 1st visible node */
LONG ListViewTop (struct Gadget *gad, struct Window *win)
{
   LONG top;

	/* use Official attributes function if running under 3.0+, otherwise
	   hack into the Gadget struct to find out */
   if (GadToolsBase->lib_Version >= 39)
      GT_GetGadgetAttrs (gad, win, NULL, GTLV_Top, &top, TAG_END);
   else
      top = (LONG)(*(short *)(((char *)gad)+sizeof(struct Gadget)+4));

   return (top);
}



/* return pointer to first visible node in thisGad, thislist */
struct Node * ListViewTopNode(struct Gadget *thisGad, struct List *thislist)
{
	int nTemp = 0;
	int nTop = ListViewTop(thisGad,mgetWnd);
	struct Node *CurrentNode = NULL;

	CurrentNode = thislist->lh_Head;
	while (nTemp < nTop) {CurrentNode = CurrentNode->ln_Succ; nTemp++;}
	return(CurrentNode);
}



int isAminetParsable(char *dataline)
{
	BOOL BValidLine;
	
	/* check to make sure string is a valid file line */
	if ((dataline == NULL)||(dataline[0] == CHAR_NUL)||(dataline[Not[keepblanklines]] == CHAR_NUL)) return(FALSE);	
		
	if (!noparse)
	{
		if (((dataline[nNameCol] < '0')||(dataline[nNameCol] > 'z')) ||
		    ((dataline[nKCol] != 'K')&&(dataline[nKCol] != 'M')&&(dataline[nKCol] != '?')) || 
		    (dataline[nDirCol] < '0') || (dataline[nDirCol] > 'z') ||
		    (dataline[nDescCol] < 'A') || (dataline[nDescCol] > 'z') ||
		    ((dataline[nPlusCol] != '+')&&(dataline[nPlusCol] != '*')&&(dataline[nPlusCol] != ' ')) ||
		    ((filesflag == 0)&&(dataline[nPlusCol] != '+')))
		{
			/* Problem line--rescan! */
			BValidLine = ReScanAminetLine(dataline);
			if (filesflag == 0) return(BValidLine && (dataline[nPlusCol] == '+'));
			else return(BValidLine);
		}
	}	
	return(TRUE);
}


/* This function looks at an Aminet line and if successful, will update
   the global n#?Col variables to reflect the columns found in this line
   Returns 0 on failure (and won't update the global vars), or 1 on 
   success (vars were all updated) */
int ReScanAminetLine(char *dataline)
{
	BOOL BDone = FALSE, BFoundAgeAlready = FALSE;
	int nCount = 0;
	int nTempNameCol = -1;
	int nTempKCol    = -1;
	int nTempDirCol  = -1;
	int nTempPlusCol = -1;
	int nTempDescCol = -1;
	int nTempAgeCol  = -1;
	int nState = 0; 	
	
	/* State 0 = haven't found filename yet */
	/* State 1 = reading thru filename */
	/* State 2 = haven't found directory yet */
	/* State 3 = haven't found K/M thingy yet */
	/* State 4 = haven't found weeks yet */
	/* State 5 = Looking for plus symbol */
	/* State 6 = Backtracking for age field */
	
	char *pcThisChar = dataline;
	
	if (pcThisChar == NULL) return(0);
	
	while((*pcThisChar != CHAR_NUL)&&(BDone == FALSE))
	{
		switch (nState)
		{
			case 0:		/* Looking for start of file name */
				if ((*pcThisChar >= '0')&&(*pcThisChar <= 'z'))
				{
					nTempNameCol = nCount;
					nState = 1;
				}
				pcThisChar++; 
				nCount++;
				break;
			
			case 1:		/* Reading thru filename */
				if (*pcThisChar == ' ')
				{
					nState = 2;
				}
				else
				{
					pcThisChar++; 
					nCount++;
				}
				break;
			
			case 2:	/* Moving over spaces after filename */
				if (*pcThisChar != ' ')
				{
					nTempDirCol = nCount;
					nState = 3;
				}
				pcThisChar++;
				nCount++;
				break;
			
			case 3:	/* Moving thru directory */
				if (*pcThisChar == ' ')
				{
					nState = 4;
				}
				pcThisChar++;
				nCount++;
				break;
			
			case 4: /* Looking for KCol */
				if ((*pcThisChar == 'K')||(*pcThisChar == 'M')||(*pcThisChar == '?'))
				{
					nTempKCol = nCount;
					nState = 5;
				}		
				pcThisChar++;
				nCount++;
				break;

			case 5: /* Looking for plus symbol, or the age number */
				if (*pcThisChar == '+')		
				{
					/* found the + */
					nTempPlusCol = nCount;
					nTempDescCol = nCount + 1;
					BDone = TRUE;
				}
				else if (((*pcThisChar >= '0')&&(*pcThisChar <= '9'))&&(BFoundAgeAlready != 2))
				{
					/* Found the age field, hopefully--this will keep being set until we find the last digit in the age */
					nTempAgeCol = nCount;
					BFoundAgeAlready = TRUE;
					
					pcThisChar++;
					nCount++;
				}
				else if (*pcThisChar != ' ')
				{
					/* Found the description, for sure */
					nTempPlusCol = nCount - 1;
					if (nTempPlusCol < 0) nTempPlusCol = 0;
					nTempDescCol = nCount;

					pcThisChar -= 2;  /* move back to the left of the */
					nCount     -= 2;  /* first comment char AND the space */
					BDone = TRUE;	
				}
				else
				{	
					/* must be a space--continue onward */
					pcThisChar++;
					nCount++;
					
					/* If we were already doing the age, mark so as to not find another age! */
					if (BFoundAgeAlready == TRUE) BFoundAgeAlready = 2;	
				}
				break;
		}
	}
	
	/* Now we see if we've got something valid */
	if (nState < 5) return(0);
	
	/* This in case there was no plus on this line! */
	if (nTempPlusCol == -1) nTempPlusCol = nTempKCol + 1;
	if (nTempDescCol == -1) nTempDescCol = (nTempPlusCol + (dataline[nTempPlusCol] != CHAR_NUL));
	
	/* Assign global vars */
	nNameCol = nTempNameCol;
	nDirCol  = nTempDirCol;
	nKCol    = nTempKCol;
	nPlusCol = nTempPlusCol;
	nAgeCol  = nTempAgeCol;
	nDescCol = nTempDescCol;
	return(1);
}
	
	
	
			
int listviewgadgetClicked (VOID)
{
int i;
struct Node *current = filelist->lh_Head;
char *dataline = NULL;

 
 for (i=0; i<lastcode; i++) current = current->ln_Succ;

 if (current != NULL)
 {
	/* Take it out of filelist */
	AttachLists(FALSE);
	TransferToSelected(current);
	AttachLists(TRUE);
 }
 return(1);	
}







int list2Clicked (VOID)
{
 /* This function will move a clicked item from the lower list to the upper one */
 int i;
 struct Node *current = getlist->lh_Head;

 for (i=0; i<lastcode; i++) current = current->ln_Succ;
	
 if (current != NULL)
 {
	AttachLists(FALSE);
	TransferToFiles(current);
	AttachLists(TRUE);
 }
}






void TransferToSelected(struct Node *current)
{

	if (isAminetParsable(current->ln_Name) == FALSE) return;  /* don't transfer what you cant understand */

	UpdateByteCount(current->ln_Name,1);
	
	/* Watch out for the nasty case where our search buffer just got removed */
	if (search_current == current) 
	{
		if (search_current != filelist->lh_Head)	/* make sure we're not the first in the list */
		{
			search_current = search_current->ln_Pred;
			search_index--;
		}
		else
		{
			search_current = search_current->ln_Succ;
			search_index++;
		}
		
		/* Check to see if we've walked off the front or back of the list */
		/* If we have, default to the head of the list */
		if (search_current == NULL) 
		{
			
				search_current = filelist->lh_Head;
				search_index = 0;
		}
	}

	Remove(current);
	/* And insert it in getlist */
	if ((nKeepSorted[1] == 1)&&(!noparse))
	{
		SmartAdd(getlist,current,nSortType[1]);
	}
	else
	{
		AddTail(getlist,current);
	}
	
	filelist_length--;
	getlist_length++;
	
	ChangeWindowTitle();
}




void TransferToFiles(struct Node *current)
{
	UpdateByteCount(current->ln_Name,-1);

	/* Take it out of getlist */
	Remove(current);
	current->ln_Succ = NULL;		/* Clear now invalid field */

	/* And insert it in filelist */
	 if ((nKeepSorted[0] == 1)&&(!noparse))
	 {	
	 	SmartAdd(filelist,current,nSortType[0]);
	 }
	else
	{
		AddTail(filelist,current);
	}
	
	/* and that's it! */
	filelist_length++;
	getlist_length--;

	ChangeWindowTitle();
}








/* Returns file size, in weeks, of the given Aminet line--only
   works if said file size is available, of course */
int AminetFileAge(char *sString)
{
	int nTemp;
	int nSum = 0;

	if (isAminetParsable(sString) == FALSE) return(0);

	/* New:  Assume that nAgeCol is the rightmost numeral of the number! */
	nTemp = nAgeCol;
	
	if (nTemp < 0) return(-999);	/* there is no age! */
	
	/* no number? */
	if ((sString[nTemp] < '0')||(sString[nTemp] > '9')) return(-999);

	/* go to front of string */
	while ((nTemp > 0)&&(sString[nTemp] >= '0')&&(sString[nTemp] <= '9')) nTemp--;
	nTemp++;
	
	while ((sString[nTemp] >= '0')&&(sString[nTemp] <= '9'))
	{
		nSum *= 10;
		nSum += sString[nTemp] - '0';
		nTemp++;
	}
	return(nSum);
}



int AminetFileSize(char *sString)
{
/* Returns file size, in kilobytes, of the given Aminet line */
int multiplier;
int filesize = 0, wholenum;
int outputlength = -1;
int tenthofmultiplier = 0;

	if (isAminetParsable(sString) == FALSE) return(0);
	
	switch (sString[nKCol])
	{
		case 'M':
			multiplier = 1024;   /* 1024 k in a M */
			tenthofmultiplier = 102;
			break;
			
		case 'K': 
			multiplier = 1;	 /* 1 k in a k */
			break;
		
		case '?':
			multiplier = 0;
			break;
			
		default:
			return(FALSE);
	}
	
	if (sString[nKCol-2] == '.')		/* for when it's like:  3.5M */
	{
		/* figure out kilobytes */
		wholenum = (int) (sString[nKCol-3] - '0');
		
		if ((wholenum >= 0)&&(wholenum <= 9)) filesize = filesize + (multiplier * wholenum);
		
		wholenum = (int) (sString[nKCol-1] - '0');
		if ((wholenum >= 0)&&(wholenum <= 9)) filesize = filesize + (tenthofmultiplier * wholenum);
	}
	else
	{
		wholenum = (int) (sString[nKCol-3] - '0');
		if ((wholenum >= 0)&&(wholenum <= 9)) filesize = filesize + (100 * multiplier * wholenum);

		wholenum = (int) (sString[nKCol-2] - '0');
		if ((wholenum >= 0)&&(wholenum <= 9)) filesize = filesize + ( 10 * multiplier * wholenum);

		wholenum = (int) (sString[nKCol-1] - '0');
		if ((wholenum >= 0)&&(wholenum <= 9)) filesize = filesize + (      multiplier * wholenum);
	}
	
	return(filesize);
}
 

 
void SmartAdd(struct List *thislist, struct Node *addme, int nThisSortType)
{
/* a simple add into the correct order of the list */
struct Node *current, *past;
char sBuffer1[43], sBuffer2[43];

current = thislist->lh_Head;
past = NULL;

if ((addme == NULL)||(addme->ln_Name == NULL)) return();

while (current != NULL)			
{
	/* Only sort if this is an Aminet file line, or not an Aminet Sort */	
	if ((current->ln_Name != NULL)&&(isAminetParsable(current->ln_Name)&&isAminetParsable(addme->ln_Name)))
	{
		switch(nThisSortType)
		{
			case SORTBYDIR:
				strncpy(sBuffer1,addme->ln_Name+nDirCol,DIRNAMESIZE);
				strncpy(sBuffer2,current->ln_Name+nDirCol,DIRNAMESIZE);
				if ((strchr(sBuffer1,'/') != NULL)&&
		    		 (strchr(sBuffer2,'/') != NULL)&&
			 		 (strncmp(sBuffer1,sBuffer2,DIRNAMESIZE) < 0))
				{
					Insert(thislist, addme, past);	/* and put it back in after current */
					return();
				}
			break;
		
			case SORTBYDESC:
				if (strncmp(addme->ln_Name+nDescCol,current->ln_Name+nDescCol,DESCSIZE) < 0)
				{
					Insert(thislist, addme, past);	/* and put it back in after current */
					return();
				}
			break;
			
			case SORTBYNAME:
				memset(sBuffer1,NUL,NAMESIZE);  /* sort sometimes goes into infinite loops if you don't have this??? */
				memset(sBuffer2,NUL,NAMESIZE);  /* It shouldn't, though, because strncpy terminates everything right? */
				strncpy(sBuffer1,addme->ln_Name+nNameCol,NAMESIZE);
				strncpy(sBuffer2,current->ln_Name+nNameCol,NAMESIZE);	
				if (strncmp(sBuffer1,sBuffer2,NAMESIZE) < 0)
				{
					Insert(thislist, addme, past);	/* and put it back in after current */		
					return();
				}
			break;
			
			case SORTBYSIZE:
				if (AminetFileSize(addme->ln_Name) < AminetFileSize(current->ln_Name))
				{
					Insert(thislist, addme, past);	/* and put it back in after current */
					return();
				}
				
			case SORTBYAGE:
				if (AminetFileAge(addme->ln_Name) < AminetFileAge(current->ln_Name))
				{
					Insert(thislist, addme, past);	/* and put it back in after current */
					return();
				}
				break;
			}
	}	
	past = current;				/* step to next in list */
	current = current->ln_Succ;
}
	
AddTail(thislist,addme);		/* If we've got to the end without returning, add it to the end */
return();
}





int CompareByDir(struct Node *past, struct Node *current)
{
	static char sBuffer1[43], sBuffer2[43];  /* static to avoid re- and de-allocing */
	
	if (isAminetParsable(current->ln_Name) == FALSE) return(-999); 	/* error! */
  	   
	if (sortcasesensitive == TRUE) 
		return(strncmp(past->ln_Name+nDirCol,current->ln_Name+nDirCol,DIRNAMESIZE));  /* For Lists, > 0 = switch */

	/* case insensitive */	
	strncpy(sBuffer1,past->ln_Name+nDirCol,DIRNAMESIZE);
	strncpy(sBuffer2,current->ln_Name+nDirCol,DIRNAMESIZE);
	UpperCase(sBuffer1);		/* not case sensitive */
	UpperCase(sBuffer2);
	
	return(strncmp(sBuffer1,sBuffer2,DIRNAMESIZE));  /* For Lists, > 0 = switch */
}



	
int CompareByDesc(struct Node *past, struct Node *current)
{
	static char sBuffer1[43], sBuffer2[43];  /* static to avoid re- and de-allocing */

	/* Make sure the comment is ok! */
	if (isAminetParsable(current->ln_Name) == FALSE) return(-999); 	/* error! */
	
	if (sortcasesensitive == TRUE) return(strncmp(past->ln_Name+nDescCol,current->ln_Name+nDescCol,DESCSIZE));
 
    /* For Lists, > 0 = switch */
	strncpy(sBuffer1,past->ln_Name+nDescCol,DESCSIZE);		/* copies to modify */
	strncpy(sBuffer2,current->ln_Name+nDescCol,DESCSIZE);	
	UpperCase(sBuffer1);		/* not case sensitive */
	UpperCase(sBuffer2);
	
   return(strncmp(sBuffer1, sBuffer2,DESCSIZE));
} 
	


	


int CompareByName(struct Node *past, struct Node *current)
{
	static char sBuffer1[43], sBuffer2[43];  /* static to avoid re- and de-allocing */

	/* Make sure the comment is ok! */
	if (isAminetParsable(current->ln_Name) == FALSE) return(-999); 	/* error! */

	if (sortcasesensitive == TRUE) return(strncmp(past->ln_Name+nNameCol,current->ln_Name+nNameCol,NAMESIZE));
	
	/* case insensitive test below */	
	strncpy(sBuffer1,past->ln_Name+nNameCol,NAMESIZE);
	strncpy(sBuffer2,current->ln_Name+nNameCol,NAMESIZE);	
	UpperCase(sBuffer1);
	UpperCase(sBuffer2);
	
	return(strncmp(sBuffer1,sBuffer2,NAMESIZE));
}





int CompareBySize(struct Node *past, struct Node *current) 
{
	return(AminetFileSize(past->ln_Name) - AminetFileSize(current->ln_Name));
}


int CompareByAge(struct Node *past, struct Node *current) 
{
	return(AminetFileAge(past->ln_Name) - AminetFileAge(current->ln_Name));
}


void SortList(struct List *thislist, int nThisSortType)
{
	static char sSortTypeString[40];
	char *sSortWinString;
	
	SetMenuValues();

	pcWhatToAbort = "Sort";
		
	strcpy(sSortTypeString, "Sorting by \0");
	
	if (windowisopen) SetWindowTitles(mgetWnd, "Sorting--please be patient", (char *) ~0); 

	/* Generate Window title prompt */
	switch(nThisSortType)
	{
		case SORTBYDIR:  strcat(sSortTypeString,"Directory: ");   break;
		case SORTBYSIZE: strcat(sSortTypeString,"Size: ");	  break;
		case SORTBYDESC: strcat(sSortTypeString,"Description: "); break;
		case SORTBYNAME: strcat(sSortTypeString,"FileName: ");    break;
		case SORTBYAGE:  strcat(sSortTypeString,"Age: ");         break;
		default:	 strcat(sSortTypeString,"Unknown: ");	  break;
	}

	sSortWinString = strrchr(sSortTypeString,' ') + 1;		/* Where to write next */
	sTreeWriteHere = sSortWinString;
	szTickerString = sSortTypeString;
			
	if (thislist == NULL) return;
	
	/* Remove list from ListView if necessary  */
 	if (windowisopen)
 	{
		AttachLists(FALSE);
		SetWaitPointer(mgetWnd);
	}

	switch (nSortAlgorithm)
	{
 		case BUBBLESORT: BubbleSortList(thislist, nThisSortType, sSortWinString, sSortTypeString); break;
 		case TREESORT:   TreeSortList  (thislist, nThisSortType, sSortWinString, sSortTypeString); break;
 	}
 	
	/* Replace list into ListView */
	AttachLists(TRUE);
	ClearWaitPointer(mgetWnd);
	
	ChangeWindowTitle();
	SetMenuValues();
}





int TreeSortUserCompare(struct Node *thisnode, struct Node *thatnode)
{
	int nResult;

	switch(nForTreeSortUseOnly)  /* using a global variable here stinks :( */
	{
		case SORTBYDIR:  nResult = CompareByDir (thisnode, thatnode); break;
		case SORTBYNAME: nResult = CompareByName(thisnode, thatnode); break;
		case SORTBYSIZE: nResult = CompareBySize(thisnode, thatnode); break;
		case SORTBYDESC: nResult = CompareByDesc(thisnode, thatnode); break;
		case SORTBYAGE:  nResult = CompareByAge (thisnode, thatnode); break;
	}
	if (nResult == 0) return(1);  /* default value can't be zero! */
	return(nResult);
}




void TreeSortList(struct List *thislist, int nThisSortType, char *sSortWinString, char *sSortTypeString)	
{
	struct Node *CurrentNode = thislist->lh_Head;
	tree *mytree = NULL;									

	/* make tree out of our list */
	tree_init(&mytree);

	/* set global variables for TreeSortUserCompare and TransferNode's use */	
	nForTreeSortUseOnly = nThisSortType;   /* Used by TreeSortUserCompare  */
	lForTreeSortUseOnly = thislist;  		/* Used by TransferNode         */
	
	lTreeTicker = 0;
	lTreeSubTicker = 0;
	
	while (CurrentNode != NULL)
	{		
		if ((CurrentNode->ln_Succ != NULL) &&	/* <--This is necessary to avoid the "killer node" ??? */
		    (CurrentNode->ln_Name != NULL) &&
		    (*CurrentNode->ln_Name != cCommentChar))
			tree_add(&mytree, TreeSortUserCompare, (char *) CurrentNode, DeleteNodeError);
	
		CurrentNode = CurrentNode->ln_Succ;		/* move down the list */
		
		if (CheckForUserAbort() == TRUE) CurrentNode = NULL;	/* kick out on abort */		
	}
	
	/* traverse tree, inserting into new list */
	/* nAbort now stays true only if both of the below are true */
	if (tree_trav(&mytree,TransferNode) == FALSE)
		MakeReq("Tree Sort Error","Warning:  Tree Sort failed; list may be incomplete", NULL);
	
	/* now clean up the tree -- since Nodes are still in a List, we don't want to delete them */
 	tree_mung(&mytree, DoNothing);
}	



int CheckForUserAbort(void)
{
	static int nReturn;
	static char szPrompt[20]="";
	static struct IntuiMessage *imsg;
	
	if (mgetWnd == NULL) return(FALSE);
	
	while (imsg = GT_GetIMsg(mgetWnd->UserPort)) 
	{
		switch (imsg->Class)
		{
			case IDCMP_VANILLAKEY: case IDCMP_CLOSEWINDOW:
				if ((imsg->Code == CHAR_ESCAPE)||(imsg->Class == IDCMP_CLOSEWINDOW))
				{
					GT_ReplyIMsg(imsg);
					sprintf(szPrompt,"Abort the %s?",pcWhatToAbort);
					nReturn = (MakeReq(szPrompt,"GadMget Abort Request","Continue|Abort") == 0);
					if (mgetWnd != NULL) SetWaitPointer(mgetWnd);
					return(nReturn);
				}
				else GT_ReplyIMsg(imsg);
				break;
				
		 	case IDCMP_NEWSIZE: case IDCMP_REFRESHWINDOW:
				HandlemgetIDCMP(imsg);	/* do window resize */
		 		break;

			case IDCMP_MENUPICK:
				SetMenuValues();	/* undo the damage */
				GT_ReplyIMsg(imsg);
				break;
							 		
		 	default:
		 		GT_ReplyIMsg(imsg);
		 		break;
		}
	}
	return(FALSE);
}


int DoNothing (struct Node *thisnode)
{
   /* and here is the magic code to .... do nothing! */
   return(0);
}





int TransferNode(struct Node *thisnode)
{	
	if (isAminetParsable(thisnode->ln_Name))
	{
		Remove(thisnode); 
		AddTail((struct List *) lForTreeSortUseOnly, thisnode); 
	}
	return(TRUE);
}






int PrintNodeData(struct Node *thisnode)
{

	if (thisnode == NULL) return(FALSE);
	if (thisnode->ln_Name == NULL) return(FALSE);
	
	printf("[%s]\n",thisnode->ln_Name);
	return(TRUE);
}






int DeleteNodeError(struct Node *thisnode)
{
	printf("tree_add tried to delete this node:\n");
	PrintNodeData(thisnode);
}






void BubbleSortList(struct List *thislist, int nThisSortType, char *sSortWinString, char *sSortTypeString)
{
   /* a simple swap-sort */
	int nSwappedThisPass = 1, nUpdateTitle = 0, nUpdateCount = 0;
	struct Node *current, *past;

	while (nSwappedThisPass > 0)
	{
		/* start a pass */
		past = thislist->lh_Head;
		if (past == NULL) return;
		
		current = past->ln_Succ;
		nSwappedThisPass = 0;		/* start with none recorded */

		while (current != NULL)			
		{
			/* Only sort if this is an Aminet file line, or not an Aminet Sort */	
			if ((current->ln_Name != NULL)&&(past->ln_Name != NULL)&&
			    (isAminetParsable(current->ln_Name)&&isAminetParsable(past->ln_Name)))
			{
				if ((past->ln_Name != NULL)&&(*past->ln_Name != cCommentChar))
				{
					if ((nThisSortType == SORTBYDIR) &&(CompareByDir (past,current) > 0) ||
					    (nThisSortType == SORTBYSIZE)&&(CompareBySize(past,current) > 0) ||
					    (nThisSortType == SORTBYDESC)&&(CompareByDesc(past,current) > 0) ||
					    (nThisSortType == SORTBYNAME)&&(CompareByName(past,current) > 0))
					{
					/* Swap the two nodes */
				 	Remove(past);
				 	Insert(thislist, past, current);
				 	nSwappedThisPass++;
					}
				}
			}	
			past = current;
			current = current->ln_Succ;
		}
		
		if (windowisopen)
		{
			sprintf(sSortWinString,"%i",nUpdateCount);
			SetWindowTitles(mgetWnd, sSortTypeString, (char *) ~0);
			nUpdateCount++; 
 		}  			

		if (CheckForUserAbort() == TRUE) nSwappedThisPass = 0;	/* kick out on abort */		
	}		
	return;
}
		

/* Returns the length of the first "word" in the string, i.e. number
   of letters before the space */		
int LengthOfWord(char *szString)
{
	char *pcTemp = szString;
	int nCount = 0;

	/* skip any leading spaces */
	while (*pcTemp == ' ') pcTemp++;
	
	/* Count chars in word */	
	while ((*pcTemp != CHAR_NUL)&&(*pcTemp != ' ')) 
	{
		nCount++;
		pcTemp++;
	}
	
	return(nCount);
}




int OutputList(struct List *thislist)
{
 #define LASTDIRBUFSIZE 30

 char *p;
 int k,l,z,next_bytes,putnameOK = 0,putcommandOK = 1; 
 int printed_bytes = maxoutputlinelength - 1, printreturnfirst = 0;
 char outname[MAXFILELINELENGTH],szLastDir[LASTDIRBUFSIZE];
 struct Node *current;

 memset(szLastDir,NUL,LASTDIRBUFSIZE);
 
 /* Get any readme files first, so user can browse them while d/l'ing the rest */
 if (getreadmes)
	{
	current = thislist->lh_Head;
 	while (current != NULL)
 	{
	 	/* watch out for empty nodes! */
		if (isAminetParsable(current->ln_Name))
		{
			z = strlen(current->ln_Name);
			/* Extra filtering code, borrowed from mgetlistviewclicked()... */
			if ((current->ln_Name[nNameCol] < '0')||(current->ln_Name [nNameCol] > 'z')) z = 0;
			if (current->ln_Name[nDirCol] < '0') z = 0;
			if ((filesflag == 0)&&(current->ln_Name[nPlusCol] != '+')) z = 0;
			/* end code from mgetlistviewclicked() ... */
		}
		else z=0;
		
		if (z>nDirCol)
		{
			k = LengthOfWord(&current->ln_Name[nNameCol]);	/* length of filename */
			l = LengthOfWord(&current->ln_Name[nDirCol]);   /* length of directory */
	
			if ((k<(nDirCol+1))&&(k>0)&&(l<12)&&(l>2))
			{
				memset(outname,NUL,MAXFILELINELENGTH);
				strncat(outname,&current->ln_Name[nDirCol],l);
				
				/* Here we have the directory name--see if it's different, generate cd */
				if ((current->ln_Name[nPlusCol] == '+')&&
				    (nocd == 0)&&
				    (simplepaths == 1)&&
				    (strncmp(szLastDir,outname,LASTDIRBUFSIZE) != 0)) 
				{
					memset(szLastDir,NUL,LASTDIRBUFSIZE);
					GenerateCDCommand(&printreturnfirst, &printed_bytes, szLastDir, outname);
					putnameOK = 1;
					putcommandOK = 0;
				}
				
				if (simplepaths == 1)
				{	
					/* remove path so it won't be printed again in the mget command */
					memset(outname,NUL,sizeof(outname));
				}
				else
				{
					strncat(outname,"/",1);
				}
				
				strncat(outname,&current->ln_Name[nNameCol],k);
				outname[79]=0;	/* just in case, we'll reterminate the string */			
			
				if (current->ln_Name[nPlusCol] == '+')
					{	
					/* find the last '.' in outname, and change whatever's after it to 'readme'! */
					p = strrchr(outname,'.');
					
					/* and if there is no "." ? */
					if (p == NULL)
					{
						strcat(outname,".");
						p = strrchr(outname,'.');
					}
					
					strcpy(p+1,"readme");
					
					next_bytes = strlen(outname) + 1;	/* + 1 for the space */
					if ((next_bytes>3)&&(next_bytes<39))
						{
						if ((putcommandOK == 1)&&(!nosplit)&&((printed_bytes + next_bytes) > maxoutputlinelength))
							{
							PrintCommandString(&printreturnfirst, &printed_bytes);			
							putnameOK = 1;
							}			
						fprintf(fpOut,"%s ",outname);
						printed_bytes = printed_bytes + next_bytes;
						putcommandOK = 1;
						}
					}
				}
			}
		current = current->ln_Succ;	
		}
	}		

 if (filesflag)
 {	
 	current = thislist->lh_Head;	
	while (current != NULL)
	{
	 	/* watch out for empty nodes! */
		if (isAminetParsable(current->ln_Name))
		{
			z = strlen(current->ln_Name);
			/* Extra filtering code, borrowed from mgetlistviewclicked()... */
			if ((current->ln_Name[nNameCol] < '0')||(current->ln_Name [nNameCol] > 'z')) z = 0;
			if ((filesflag == 0)&&(current->ln_Name[nPlusCol] != '+')) z = 0;
			/* end code from mgetlistviewclicked() ... */
		}
		else z=0;

		if (z>nDirCol)
		{
			k = LengthOfWord(&current->ln_Name[nNameCol]);	/* length of filename */
			l = LengthOfWord(&current->ln_Name[nDirCol]);   /* length of directory */

			if ((k<(nDirCol+1))&&(k>0)&&(l<12)&&(l>2))
			{
				memset(outname,NUL,MAXFILELINELENGTH);
				strncat(outname,&current->ln_Name[nDirCol],l);

				/* Here we have the directory name--see if it's different, generate cd */
				if ((nocd == 0)&&
					(simplepaths == 1)&&
					(strncmp(szLastDir,outname,LASTDIRBUFSIZE) != 0)) 
				{
					memset(szLastDir,NUL,LASTDIRBUFSIZE);
					GenerateCDCommand(&printreturnfirst, &printed_bytes, szLastDir, outname);
					putcommandOK = 0;
					putnameOK = 1;
				}
				
				if (simplepaths == 1)
				{	
					/* remove path so it won't be printed again in the mget command */
					memset(outname,NUL,sizeof(outname));
				}
				else
				{
					strncat(outname,"/",1);
				}
				
				
				strncat(outname,&current->ln_Name[nNameCol],k);
				outname[79]=0;	/* just in case, we'll reterminate the string */			
				if (filesflag)
				{	
					next_bytes = strlen(outname) + 1;	/* + 1 for the space */
					if ((next_bytes>3)&&(next_bytes<33))
					{
						if ((putcommandOK == 1)&&(!nosplit)&&((printed_bytes + next_bytes) > maxoutputlinelength))
						{
							PrintCommandString(&printreturnfirst, &printed_bytes);	
							putnameOK = 1;
						}			
						fprintf(fpOut,"%s ",outname);
						putcommandOK = 1;
						printed_bytes = printed_bytes + next_bytes;
					}
				}
			}
		}	
	current = current->ln_Succ;	
	}
 }
return(1);
}




void PrintCommandString(int *printreturnfirst, int *printed_bytes)
{
	if (*printreturnfirst) fprintf(fpOut,sEndOfLineString); 
	*printreturnfirst = 1;
		
	if (nocommand) 
	{
		*printed_bytes = 0;
	}
	else
	{
		fprintf(fpOut,"%s",szCommandString);
		*printreturnfirst = 1;
		*printed_bytes = strlen(szCommandString) + 1;	/* reset counter for next batch */
	}
	return;
}




void GenerateCDCommand(int *printreturnfirst, int *printed_bytes, char *szLastDir, char *outname)
{
	if (*printreturnfirst) fprintf(fpOut,sEndOfLineString);
	fprintf(fpOut,"cd ");
				
	/* On the first item, we will be starting at the aminet root
	   directory, so we won't need to print the ../.. .  After that,
		though, we will.  printreturnfirst serves nicely to tell
		whether or not we're in the first iteration. */   
	
	if (*printreturnfirst == 1) fprintf(fpOut,sAminetPathString);
			
	fprintf(fpOut,"%s",outname);
	*printreturnfirst = 1;
	PrintCommandString(printreturnfirst, printed_bytes);

	/* update buffer */	
	strncpy(szLastDir,outname,30);	

	return;
}			



int RawOutputList(struct List *thislist)
{
 struct Node *current = thislist->lh_Head;
 int minlinelength = 1;

 if (keepblanklines == 1) minlinelength = 0;

 if (mgetWnd != NULL) SetWaitPointer(mgetWnd);

  	
 while (current != NULL)
 {	
	if ((current->ln_Name != NULL)&&(current->ln_Name[0] < 128)&&(strlen(current->ln_Name) >= minlinelength))
	{
		if (current->ln_Name[0] < minlinelength) 	/* was 14? */
			fprintf(fpOut,"\n",current->ln_Name);
		else	fprintf(fpOut,"%.300s\n",current->ln_Name);
	}
	current = current->ln_Succ;
 }

 ClearWaitPointer(mgetWnd);

 return(1);
}









int MakeReq(char *sText, char *sTitle, char *sGadgets)
{
	struct EasyStruct myreq;
	LONG number = 0L;
	int nResult;
	
	if (sTitle == NULL) sTitle = "GadMGet Error";
	if (sText == NULL) sText = "A nasty error happened!";
	if (sGadgets == NULL) sGadgets = "OK";
	
	myreq.es_TextFormat   = sText;
	myreq.es_Title        = sTitle;
	myreq.es_GadgetFormat = sGadgets;
	
	SetWaitPointer(mgetWnd);
	nResult = EasyRequest(mgetWnd, &myreq, NULL, NULL, number);
	ClearWaitPointer(mgetWnd);
	return(nResult);
}


int mgettreesort (VOID)
{
	nSortAlgorithm = TREESORT;
	SetMenuValues();
}

int mgetbubblesort (VOID)
{
	nSortAlgorithm = BUBBLESORT;
	SetMenuValues();
}	

int mgetsortcase (VOID)
{
	sortcasesensitive = Not[sortcasesensitive];
	if (nKeepSorted[0] == 1) SortList(filelist,nSortType[0]);
	if (nKeepSorted[1] == 1) SortList(getlist, nSortType[1]);
	SetMenuValues();
}








int mgetabout (VOID)
{
	char sAboutText[100];

	sprintf(sAboutText,"    %s\n\n  by Jeremy Friesner\n  jfriesne@ucsd.edu\n\nCompiled: %s",
			pnamestring, __DATE__);
	MakeReq(sAboutText,"About GadMGet","Hey, Cool!");
		
	#ifdef OLD
	strcpy(sAboutText,pnamestring);
	strcat(sAboutText,"\n\nby Jeremy Friesner\njfriesne@ucsd.edu\n");
	MakeReq(sAboutText,"About GadMGet","Hey, Cool!");
	#endif 
	
	return(1);
}








int mgetquit (VOID)
{
	done=TRUE;
}




int mgetmultiselect(VOID)
{
int lin, nSortAtEnd = FALSE;
struct Node *select_current = filelist->lh_Head, *select_next = NULL;
char sUpperBuffer[MAXFILELINELENGTH],sUpperSearchString[MAXFILELINELENGTH];

requesttype = SELECT_REQUESTTYPE;	   /* This is a HORRIBLE way to program, but I don't want  */
lin = mgetfind();								/* to try to change the parameters since it might screw */
requesttype = FIND_REQUESTTYPE;			/* up the mget_listview2 functions...				        */

 if (lin == TRUE) 
 {
	SetWaitPointer(mgetWnd);
	AttachLists(FALSE);
			
	if (searchcasesensitive)	
	{			
		while (select_current != NULL)
		{
			if ((nKeepSorted[1] == TRUE)&&(getlist_length > 240))
			{
			  	nSortAtEnd = TRUE;						/* remember to sort when done */
			  	nKeepSorted[1] = FALSE;
			}	   

			if ((select_current->ln_Name != NULL)&&
			    (strstr(select_current->ln_Name,sMultiSelect) != 0))
			{
				select_next = select_current->ln_Succ;
				TransferToSelected(select_current);
				select_current = select_next;
			}
			else
			{
				select_current = select_current->ln_Succ; 
			}
		}
	}
	else
	{
		strncpy(sUpperSearchString,sMultiSelect,sizeof(sUpperSearchString));
		UpperCase(sUpperSearchString);
		while (select_current != NULL)
		{
			if ((nKeepSorted[1] == TRUE)&&(getlist_length > 240))
			{
			  	nSortAtEnd = TRUE;						/* remember to sort when done */
			  	nKeepSorted[1] = FALSE;
			}	   

			if (select_current->ln_Name != NULL)
			{
				strncpy(sUpperBuffer,select_current->ln_Name,sizeof(sUpperBuffer)-1);
				UpperCase(sUpperBuffer);

				if (strstr(sUpperBuffer,sUpperSearchString) != 0)
				{
					select_next = select_current->ln_Succ;
					TransferToSelected(select_current);
					select_current = select_next;
				}
				else
				{
					select_current = select_current->ln_Succ; 
				}
			}
			else
			{
					select_current = select_current->ln_Succ; 
			}
		}
	}

 if (nSortAtEnd == TRUE)
 {
 	mgetgetkeep();		/* Sort files now, at the end */
 }

 AttachLists(TRUE);
 ChangeWindowTitle();
 ClearWaitPointer(mgetWnd);
 }
}





int mgetmultideselect(VOID)
{
int lin, nSortAtEnd = FALSE;
struct Node *select_current = getlist->lh_Head, *select_next = NULL;
char sUpperBuffer[MAXFILELINELENGTH], sUpperSearchString[MAXFILELINELENGTH];

requesttype = DESELECT_REQUESTTYPE;	   /* This is a HORRIBLE way to program, but I don't want  */
lin = mgetfind();			   /* to try to change the parameters since it might screw */
requesttype = FIND_REQUESTTYPE;		   /* up the mget_listview2 functions...		   */

if (lin == TRUE) 
 {
 	SetWaitPointer(mgetWnd);
	AttachLists(FALSE);
	
	if (searchcasesensitive)	
	{
		while (select_current != NULL)
		{
		   if ((nKeepSorted[0] == TRUE)&&(filelist_length > 240))
			{
	 			nSortAtEnd = TRUE;						/* remember to sort when done */
	  			nKeepSorted[0] = FALSE;
			}

			if ((select_current->ln_Name != NULL)&&
			    (strstr(select_current->ln_Name,sMultiSelect) != 0))
			{
				select_next = select_current->ln_Succ;
				TransferToFiles(select_current);
				select_current = select_next;
			}
			else
			{
				select_current = select_current->ln_Succ; 
			}
		}
	}
	else
	{
		strncpy(sUpperSearchString,sMultiSelect,sizeof(sUpperSearchString));
		UpperCase(sUpperSearchString);
		while (select_current != NULL)
		{
		   if ((nKeepSorted[0] == TRUE)&&(filelist_length > 240))
			{
	 			nSortAtEnd = TRUE;						/* remember to sort when done */
	  			nKeepSorted[0] = FALSE;
			}

			if (select_current->ln_Name != NULL)
			{
				strncpy(sUpperBuffer,select_current->ln_Name,sizeof(sUpperBuffer)-1);
				UpperCase(sUpperBuffer);

				if (strstr(sUpperBuffer,sUpperSearchString) != 0)
				{
					select_next = select_current->ln_Succ;
					TransferToFiles(select_current);
					select_current = select_next;
				}
				else
				{
					select_current = select_current->ln_Succ; 
				}
			}
			else
			{
					select_current = select_current->ln_Succ; 
			}
		
		}
	}

 if (nSortAtEnd == TRUE)
 {
 	mgetfileskeep();		/* Sort files now, at the end */
 }

 AttachLists(TRUE);
 ChangeWindowTitle();
 ClearWaitPointer(mgetWnd);
 }
}





int mgetcase (VOID)
{
searchcasesensitive = Not[searchcasesensitive];
SetMenuValues();
}




int mgetCD (VOID)
{
simplepaths = Not[simplepaths];
SetMenuValues();
}






int mgetfindtop (VOID)
{
	mgetfind_findtype = SEARCHTYPE_TOP;
	mgetfind();
	mgetfind_findtype = SEARCHTYPE_FORWARD;
	return(TRUE);
}



int mgetfindbottom (VOID)
{
	mgetfind_findtype = SEARCHTYPE_BOTTOM;
	mgetfind();
	mgetfind_findtype = SEARCHTYPE_FORWARD;
	return(TRUE);
}


int mgetfindback (VOID)
{
	mgetfind_findtype = SEARCHTYPE_BACKWARD;
	mgetfind();
	mgetfind_findtype = SEARCHTYPE_FORWARD;
	return(TRUE);
}


int mgetfind (VOID)
{
ULONG winsig, signals;
int done = 0, found = 0, index = -1;
int fwindowwidth = 450, fwindowheight = 35 + Scr->RastPort.TxHeight;
int fwindowleft = (mgetLeft + (windowwidth/2) - (fwindowwidth/2));
int fwindowtop  = (mgetTop  + (windowheight/2)- (fwindowheight/2));
int WindowHeightLines = nTopListHeight/(listfont.ta_YSize);
struct NewGadget stringGad;
struct IntuiMessage *imsg;
struct Gadget *newgad = NULL;
char numstring[100], *ss = searchstring, sTempOutString[300];
char *wp = NULL,windowtitlestring0[] = "Search Window", 
                windowtitlestring1[] = "Line Length Window",
                windowtitlestring2[] = "Output File Change Window",
                windowtitlestring3[] = "Select Multiple Items Window",
                windowtitlestring4[] = "Deselect Multiple Items Window";
FILE *fpTemp = NULL;

findvi  = GetVisualInfo(Scr, TAG_END);
if (findvi == NULL) return(0);
if (findwindow != NULL) return(0);


if (fwindowleft < 0) fwindowleft = mgetLeft;
if (fwindowheight < 0) fwindowtop = mgetTop;

 newgad = CreateContext(&findgadlist);
 if (newgad == 0)
	{
	MakeReq("Couldn't create findwindow gad context!\n",NULL,NULL);
	return(0);
	}

 if (newgad == NULL) return(0);

 stringGad.ng_TextAttr	 = &topaz8;	/* Cant figure out how to get system default into a TextAttr!  No name string available! */
 stringGad.ng_VisualInfo = findvi;
 stringGad.ng_LeftEdge	 = 5;
 stringGad.ng_TopEdge    = 18 + Scr->RastPort.TxHeight;
 stringGad.ng_Width	 = (fwindowwidth-10);
 stringGad.ng_Height	 = 13;
 stringGad.ng_GadgetText = "Please enter search string.";
 stringGad.ng_GadgetID	 = 35;	
 stringGad.ng_Flags	 = PLACETEXT_ABOVE;

 switch (requesttype)
 {
 	case FIND_REQUESTTYPE:
    	wp = windowtitlestring0;
   break;

   case LINELENGTH_REQUESTTYPE:
 		wp = windowtitlestring1;
 		stringGad.ng_GadgetText = "Please enter new maximum line length.";
 		sprintf(numstring,"%i\0",maxoutputlinelength);	
 		ss = numstring;
   break;
   
   case OUTPUTFILE_REQUESTTYPE:
 		wp = windowtitlestring2;
 		stringGad.ng_GadgetText = "Please enter new output file path/device.";
 		sprintf(numstring,"%s",sOutFileName);
 		strncpy(sTempOutString,sOutFileName,sizeof(sTempOutString));
 		ss = sTempOutString;
   break;
   
   case SELECT_REQUESTTYPE:
   	wp = windowtitlestring3;
   	stringGad.ng_GadgetText = "Please enter key string to select files with.";
   	sprintf(numstring,"%s",sMultiSelect);
 		strncpy(sTempOutString,sMultiSelect,sizeof(sTempOutString));
 		ss = sTempOutString;   	
   break;
   
   case DESELECT_REQUESTTYPE:
   	wp = windowtitlestring4;
   	stringGad.ng_GadgetText = "Please enter key string to deselect files with.";
   	sprintf(numstring,"%s",sMultiSelect);
   	strncpy(sTempOutString,sMultiSelect,sizeof(sTempOutString));
   	ss = sTempOutString;
  	break;
 }
 

 newgad = CreateGadget(STRING_KIND, newgad, &stringGad, 
			  GTST_String, ss, 
			  STRINGA_Justification, GACT_STRINGCENTER, 
			  GA_Immediate, TRUE,
			  TAG_END);  

 if (newgad == NULL) 
 {
	FreeGadgets(findgadlist);
	FreeVisualInfo(findvi);
	return(0);
 }

 if (GadToolsBase->lib_Version == 37)
 {
	/* Only do it the "illegal" way under v37.  GA_Immediate in the CreateGadget
	   line, above, won't work under v37 but will on later releases. */
	newgad->Activation |= GACT_IMMEDIATE; 
 }	

 switch (screentype)
 {
	case USE_PUBSCREEN:
		findwindow = OpenWindowTags(NULL,
			WA_Left,		fwindowleft,
			WA_Top,		fwindowtop,
			WA_Width,	     fwindowwidth,
			WA_Height,	fwindowheight,
			WA_PubScreen,	Scr,
			WA_PubScreenFallBack, TRUE,
			WA_IDCMP,		STRINGIDCMP|IDCMP_CLOSEWINDOW|
						IDCMP_REFRESHWINDOW|IDCMP_ACTIVEWINDOW,
			WA_Flags,		WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
			WA_Gadgets,	findgadlist,
			WA_Title,	     wp,
			WA_ScreenTitle,	pnamestring,
			TAG_DONE );
	break;
	
	case USE_CUSTOMSCREEN:
		findwindow = OpenWindowTags(NULL,
			WA_Left,		fwindowleft,
			WA_Top,		fwindowtop,
			WA_Width,	     fwindowwidth,
			WA_Height,	fwindowheight,
			WA_CustomScreen, Scr,
			WA_IDCMP,		STRINGIDCMP|IDCMP_CLOSEWINDOW|
						IDCMP_REFRESHWINDOW|IDCMP_ACTIVEWINDOW,
			WA_Flags,		WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
			WA_Gadgets,	findgadlist,
			WA_Title,	     wp,
			WA_ScreenTitle,	pnamestring,
			WA_CustomScreen,	Scr,
			TAG_DONE );
	break;

	case USE_WBSCREEN:
		findwindow = OpenWindowTags(NULL,
			WA_Left,		fwindowleft,
			WA_Top,		fwindowtop,
			WA_Width,	     fwindowwidth,
			WA_Height,	fwindowheight,
			WA_IDCMP,		STRINGIDCMP|IDCMP_CLOSEWINDOW|
						IDCMP_REFRESHWINDOW|IDCMP_ACTIVEWINDOW,
			WA_Flags,		WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
			WA_Gadgets,	findgadlist,
			WA_Title,	     wp,
			WA_ScreenTitle,	pnamestring,
			TAG_DONE );
	break;
	}

if (findwindow == NULL) return(0);
GT_RefreshWindow(findwindow, NULL); 

SetWindowTitles(mgetWnd, "MGet window inactive--close daughter window to continue", (char *) ~0); 
SetWaitPointer(mgetWnd);

winsig = 1 << findwindow->UserPort->mp_SigBit;

 while (!done)
 {
	signals = Wait(winsig);
	if (signals&winsig)
	{
		while ((!done) && (imsg = GT_GetIMsg(findwindow->UserPort)))
		{
			
			switch(imsg->Class)
			{			
				case IDCMP_ACTIVEWINDOW:
					ActivateGadget(newgad,findwindow,NULL);
					break;
						
				case IDCMP_GADGETUP:
					strncpy(ss,((struct StringInfo*)newgad->SpecialInfo)->Buffer,sizeof(searchstring));
					done = 1;
					break;
		
				case IDCMP_CLOSEWINDOW:
					done = 2;
					break;
					
				case IDCMP_REFRESHWINDOW:
					GT_BeginRefresh(findwindow);
					GT_EndRefresh(findwindow, TRUE);
					break;
			}
			GT_ReplyIMsg(imsg);
		}
	}
 }
	
CloseWindow(findwindow);
FreeGadgets(findgadlist);
FreeVisualInfo(findvi); 
findwindow = NULL;

ClearWaitPointer(mgetWnd);
ChangeWindowTitle();  /* just in case */

 if ((requesttype == SELECT_REQUESTTYPE)||(requesttype == DESELECT_REQUESTTYPE))
 {
 	if (strlen(sTempOutString) == 0) return(FALSE);  /* empty string = abort, don't move any items */
	strncpy(sMultiSelect,sTempOutString,sizeof(sMultiSelect));
 	ChangeWindowTitle();
 	return(TRUE);
 }
 
 if (requesttype == LINELENGTH_REQUESTTYPE) 
 {
		ChangeWindowTitle();	
		return(atoi(ss));
 }
 
 if (requesttype == OUTPUTFILE_REQUESTTYPE)
 {
	if (strlen(sTempOutString) == 0)
	{
		if (BStartedFromWB == FALSE)
		{
			fpOut = stdout;
			*sOutFileName = CHAR_NUL;	/* blank out filename string */
		}
		else
		{
			strncpy(sTempOutString,"ram:GadMget.output",sizeof(sOutFileName));
		}
	}
	else
	{
		fpTemp = fopen(sTempOutString,"w");
		if (fpTemp == NULL)
		{
			MakeReq("Couldn't open output file!\n",NULL,NULL);
		}
		else
		{
			fpOut = fpTemp;
			strncpy(sOutFileName,sTempOutString,sizeof(sOutFileName));
			fclose(fpTemp);
		}
	}
	ChangeWindowTitle();
	return(0);
 }
	
 if ((done == 2)||(strlen(searchstring) == 0))
 {
	ChangeWindowTitle();
	return(0);	/* can use searchstring now instead of ss */
 }			/* because we're no longer worried about the nums */

 /* Now find it in the filelist */
 index = SearchList(searchstring,mgetfind_findtype);
 if (index == -1) DisplayBeep(Scr); else findgadgoto(index,3);
 return(1);
}






int mgetfindnext (VOID)
{
int next_index;

/* bump to next node */
next_index = SearchList(searchstring,SEARCHTYPE_NEXT);
if (next_index == -1) DisplayBeep(Scr); else findgadgoto(next_index,2);

return(TRUE);
}



int mgetfindprevious (VOID)
{
int prev_index;

/* bump to previous node */
prev_index = SearchList(searchstring,SEARCHTYPE_PREVIOUS);
if (prev_index == -1) DisplayBeep(Scr); else findgadgoto(prev_index,2);

return(TRUE);
}

int mgetfindcurrent (VOID)
{
if ((search_index == -1)||(search_current == NULL)) DisplayBeep(Scr); else findgadgoto(search_index,2);

return(TRUE);
}


int mgetfilesbydir (void)
{
nSortType[0] = SORTBYDIR;

SortList(filelist,nSortType[0]);
}


int mgetfilesbysize (void)
{
nSortType[0] = SORTBYSIZE;

SortList(filelist,nSortType[0]);
}


int mgetfilesbyname (void)
{
nSortType[0] = SORTBYNAME;

SortList(filelist,nSortType[0]);
}


int mgetfilesbydesc (void)
{
nSortType[0] = SORTBYDESC;

SortList(filelist,nSortType[0]);
}

int mgetfilesbyage (void)
{
nSortType[0] = SORTBYAGE;

SortList(filelist,nSortType[0]);
}


int mgetfileskeep (void)
{
if (nKeepSorted[0] == 1) 
	{
		nKeepSorted[0] = 0;
	}
	else
	{
		nKeepSorted[0] = 1;
		SortList(filelist,nSortType[0]);
	}
SetMenuValues();
}


int mgetgetbydir (void)
{
nSortType[1] = SORTBYDIR;

SortList(getlist,nSortType[1]);
}


int mgetgetbysize (void)
{
nSortType[1] = SORTBYSIZE;

SortList(getlist,nSortType[1]);
}


int mgetgetbyname (void)
{
nSortType[1] = SORTBYNAME;

SortList(getlist,nSortType[1]);
}


int mgetgetbydesc (void)
{
nSortType[1] = SORTBYDESC;

SortList(getlist,nSortType[1]);
}


int mgetgetbyage (void)
{
nSortType[1] = SORTBYAGE;

SortList(getlist,nSortType[1]);
}


int mgetgetkeep (void)
{
	if (nKeepSorted[1] == TRUE) 
	{
		nKeepSorted[1] = FALSE;
	}
	else
	{
		nKeepSorted[1] = TRUE;
		SortList(getlist,nSortType[1]);
	}
	SetMenuValues();
}





int SearchList(char *key, int nSearchType)
{
	int found = 0, nTemp = 0, nSearchDir = SEARCH_FORWARD;
	char sUpperBuffer[MAXFILELINELENGTH], sUpperSearchString[MAXFILELINELENGTH];

 	pcWhatToAbort = "Search";
					   
	/* keep a separate temporary search_* in case we fail */
	int temp_search_index;
	struct Node *temp_search_current;

	if (mgetWnd != NULL) SetWindowTitles(mgetWnd, "Searching...", (char *) ~0); 
	SetWaitPointer(mgetWnd);

 	/* make sure search_current at least is *something* !! */
 	if (search_current == NULL)
 	{
		search_current = ListViewTopNode((struct Gadget *) mgetGadgets[0], filelist);
		search_index = ListViewTop((struct Gadget *) mgetGadgets[0], filelist);
	}

	/* temporary copy */
	temp_search_current = search_current;
	temp_search_index = search_index;
	
	/* Start at current top of display */
	switch (nSearchType)
	{
		case SEARCHTYPE_FORWARD:
			temp_search_current = ListViewTopNode((struct Gadget *) mgetGadgets[0], filelist);
			temp_search_index = ListViewTop((struct Gadget *) mgetGadgets[0], filelist);
			break;
	
		case SEARCHTYPE_BACKWARD:
			temp_search_current = ListViewTopNode((struct Gadget *) mgetGadgets[0], filelist);
			temp_search_index = ListViewTop((struct Gadget *) mgetGadgets[0], filelist);
			nSearchDir = SEARCH_BACKWARD;
			break;
			
		case SEARCHTYPE_NEXT:
			temp_search_current = temp_search_current->ln_Succ;
			temp_search_index++;
			break;
		
		case SEARCHTYPE_PREVIOUS:
			if (temp_search_current != filelist->lh_Head) temp_search_current = temp_search_current->ln_Pred;
				else temp_search_current = NULL;
			temp_search_index--;
			nSearchDir = SEARCH_BACKWARD;
				break;
			
		case SEARCHTYPE_TOP:
			temp_search_current = filelist->lh_Head;
			temp_search_index = 0;
			break;
			
		case SEARCHTYPE_BOTTOM:
			temp_search_current = TailOf(filelist, &temp_search_index);
			nSearchDir = SEARCH_BACKWARD;
			break;		
	}		
			

	if (searchcasesensitive)	
	{
		while ((temp_search_current != NULL)&&(found == 0))
		{
			if ((temp_search_current->ln_Name != NULL)&&(strstr(temp_search_current->ln_Name,searchstring) != 0))
			found = 1;
			else
			{
				if (nSearchDir == SEARCH_FORWARD)
				{
					temp_search_current = temp_search_current->ln_Succ; 
					temp_search_index++;
				}
				else
				{
					temp_search_current = temp_search_current->ln_Pred; 
					temp_search_index--;
				}
			}
			if (CheckForUserAbort() == TRUE) temp_search_current = NULL;
		}
	}
	else
	{
		strncpy(sUpperSearchString,key,sizeof(sUpperSearchString));
		UpperCase(sUpperSearchString);
		while ((temp_search_current != NULL)&&(found == 0))
		{
			if (temp_search_current->ln_Name != NULL)
			{
				strncpy(sUpperBuffer,temp_search_current->ln_Name,sizeof(sUpperBuffer)-1);
				UpperCase(sUpperBuffer);
				if (strstr(sUpperBuffer,sUpperSearchString) != 0) found = 1;
			}
			if (found == 0)
			{
			 	if (nSearchDir == SEARCH_FORWARD)
				{
					temp_search_current = temp_search_current->ln_Succ; 
					temp_search_index++;
				}
				else
				{
					if (temp_search_current == filelist->lh_Head) temp_search_current = NULL; 
										 else temp_search_current = temp_search_current->ln_Pred; 
					temp_search_index--;
				}
			}
			if (CheckForUserAbort() == TRUE) temp_search_current = NULL;
		}
	}
	
	ChangeWindowTitle();
	ClearWaitPointer(mgetWnd);

	if (found == 1) 
	{	
		search_current = temp_search_current;		/* cast the temp copy in stone */
		search_index = temp_search_index;
		return(search_index); 
	}
	else 
	{
		return(-1);
	}
}











void findgadgoto (int index, int numberofflashes)
{
int i, xmin, ymin, xmax, ymax, ystep, midscreen;
int WindowHeightLines = nTopListHeight/(listfont.ta_YSize);
LONG yTop = 0;

 midscreen = index-(WindowHeightLines/2);
 if (midscreen < 0) midscreen = 0;

 GT_SetGadgetAttrs((struct Gadget *) mgetGadgets[0], mgetWnd, NULL, GTLV_Top, midscreen, TAG_END);
 yTop = ListViewTop((struct Gadget *) mgetGadgets[0], mgetWnd);
 ystep = index - yTop;
  
 xmin = Scr->WBorLeft + 4;
 ymin = (nTopListTop + ((listfont.ta_YSize) *ystep) + 2);
 xmax = windowwidth - Scr->WBorLeft - 20;
 ymax = ymin + (listfont.ta_YSize) - 1;

 SetDrMd(mgetWnd->RPort, 50); 
 for (i=0;i<numberofflashes;i++)
 	{
 	RectFill(mgetWnd->RPort,xmin,ymin,xmax,ymax);
 	Delay(5);
 	RectFill(mgetWnd->RPort,xmin,ymin,xmax,ymax);
 	if (i<(numberofflashes-1)) Delay(5);
 	}
}





int ClearList(struct List *thislist)
{
	struct Node *current;
	const int nodesize = sizeof(struct Node);
	BOOL BOnScreen = ((thislist == filelist)||(thislist == getlist));
	int nUpdate, nTally = 0;
		
	if (thislist == NULL) return(FALSE);
	if (thislist == filelist) 
	{
		search_current = NULL;
		filelist_length = 0;
	}
	if (thislist == getlist)
	{	
		getlist_length = 0;
		kbytes_selected = 0;
	}		
	if (BOnScreen == TRUE) AttachLists(FALSE);

	pcWhatToAbort = "Clear";
	
	SetWaitPointer(mgetWnd);
		
	while (current = RemHead(thislist))
	{
		if (current->ln_Name != NULL)
		{
			#ifdef MEMPOOLS_H
			free(current->ln_Name);
			#else
			FreeMem(current->ln_Name,current->ln_Pri+127);
                        #endif
		}		
		#ifdef MEMPOOLS_H
		free(current);
		#else				
		FreeMem(current,nodesize);   
		#endif

		if (nUpdate == 0) 
		{
			if (CheckForUserAbort() == TRUE) break;
			if (mgetWnd != NULL) 
			{
				sprintf(windowtitle,"Clearing List: %i",nTally);
				SetWindowTitles(mgetWnd, windowtitle, (char *) ~0);
			}
		}
		if (nUpdate < 0) nUpdate = 213;
		nUpdate--;
		nTally++;
		
	}
	if (BOnScreen == TRUE) AttachLists(TRUE);
	ClearWaitPointer(mgetWnd);
	return(TRUE);
}






int mgetclearfiles (void)
{
   	/* delete files list */
   	ClearList(filelist);	
   	ChangeWindowTitle();
}



int mgetclearget (void)
{
	/* delete get list */
	ClearList(getlist);
   	ChangeWindowTitle();
}







int mgetnoparse (void)
{
	if (noparse) 
	{
		noparse = 0; 
		if (nKeepSorted[0] == 1) SortList(filelist,nSortType[0]);
		if (nKeepSorted[1] == 1) SortList(getlist, nSortType[1]);
		SetMenuValues();
	}
	else 
	{
		noparse = 1;		
		SetMenuValues();
	}
}








int mgetfiles (void)
{
	if (filesflag) 
	{
		filesflag = 0;
		getreadmes = 1;
		SetMenuValues();	 
	}
	else filesflag = 1;
}







int mgetreadmes (void)
{
	if (getreadmes) 
	{
		getreadmes = 0; 
	 	filesflag = 1;
	 	SetMenuValues();
	}
	else getreadmes = 1;
}






int mgetsplit (void)
{
	nosplit = Not[nosplit];
	SetMenuValues();	
}






int mgetlinelength (void)
{
	int lin;

	requesttype = LINELENGTH_REQUESTTYPE;	/* This is a HORRIBLE way to program, but I don't want  */
	lin = mgetfind();			/* to try to change the parameters since it might screw */
	requesttype = FIND_REQUESTTYPE;		/* up the mget_listview2 functions...				 */

	if (lin >  0) maxoutputlinelength = lin;
}




int mgetoutputfile (void)
{
	int lin;	

	requesttype = OUTPUTFILE_REQUESTTYPE;	/* This is a HORRIBLE way to program, but I don't want  */
	lin = mgetfind();			/* to try to change the parameters since it might screw */
	requesttype = FIND_REQUESTTYPE;		/* up the mget_listview2 functions...			*/
}





#ifdef DEBUG
void PrintList(struct List *thislist)
{
struct Node *nodecurrent = thislist->lh_Head;

fprintf(fpOut,"thislist = %p\n",thislist);

 while (nodecurrent != NULL)
 {
	if (nodecurrent->ln_Name == NULL) 
		fprintf(fpOut,"[ <NULL> ]\n"); 
	else 
		fprintf(fpOut,"[%s]\n",nodecurrent->ln_Name);

	nodecurrent = nodecurrent->ln_Succ;
 }
	
return();
}
#endif




int LengthOfList(struct List *thislist)
{
	struct Node *nodecurrent = thislist->lh_Head->ln_Succ;
	int nLength = 0;
	
 	while (nodecurrent != NULL)
 	{
 		nLength++;
		nodecurrent = nodecurrent->ln_Succ;
 	}
	
	return(nLength);
}




int mgetsave (void)
{
	FILE * fpTemp = fpOut;

	/* Confirm with ASL for really big files! */
	if (((filelist_length + getlist_length) > 10000) &&
	    (RequestAFile(inputfile,TRUE) == FALSE)) return(FALSE);		
		
	fpOut = fopen(inputfile,"w");	
	if (fpOut == NULL)
	{
		MakeReq("Couldn't open file.",NULL,NULL);
		return (0);
	}

	strcpy(windowtitle,"Saving current state to ");
	strncat(windowtitle,inputfile,sizeof(windowtitle));
	if (mgetWnd != NULL) SetWindowTitles(mgetWnd, windowtitle, (char *) ~0);			

	RawOutputList(filelist);
	
	if (LengthOfList(getlist) > 0)
	{
		fprintf(fpOut,"%s\n",szBookMark);
		RawOutputList(getlist);
	}
	fclose(fpOut);
	
	fpOut = fpTemp;
	
	ChangeWindowTitle();
}


int mgetfastquit (void)
{
	CleanUp();
	exit(0);
}


int mgetsaveas (void)
{
	/* FileRequest a file */
	*inputfile = CHAR_NUL;
	if (RequestAFile(inputfile,TRUE) == FALSE) return(FALSE);
	
	mgetsave();
}


int mgetmarkexit (void)
{
	mgetsave();
	CleanUp();
	exit(0);
}


/* szFileName string must be readable AND writable! */
BOOL GetValidFile(char * szFileName)
{
	while (FileExists(szFileName) == FALSE)
 	{
 		/* If user aborted, stop trying */
		if (RequestAFile(szFileName,FALSE) == FALSE) return(FALSE);
 	}
 	SetReqDefaults(szFileName);
 	return(TRUE);
}



BOOL FileExists(char * szFileName)
{
	FILE * fpTest = fopen(szFileName, "r");
 	if (fpTest != NULL) fclose(fpTest);
 	return(fpTest != NULL);
}


int mgetopenfile (void)
{
    return(OpenMgetFile(NULL));
}

int OpenMgetFile(char * szOptFileName)
{	 	
	/* If arg specified, adopt that */
	if (szOptFileName == NULL) 
	{
	 	szOptFileName  = inputfile;
	 	*szOptFileName = CHAR_NUL;	/* force requester */
		if (GetValidFile(szOptFileName) == FALSE) return(FALSE); 
	}
	else
		if (FileExists(szOptFileName) == FALSE) return(FALSE);

	SetReqDefaults(szOptFileName);
		
	ClearList(filelist);		 

	/* These are all dependant on a given filelist, so RESET! */
	filelist_length = 0;
	search_current = NULL;
	search_index = 0;

	pcWhatToAbort = "Load";
	ReadmyFile(szOptFileName);
	search_current = NULL;
	search_index = 0;

	ChangeWindowTitle();
	return(1);
}



void AttachLists(BOOL BAttach)
{
	if (mgetWnd == NULL) return;
	
	if (BAttach == TRUE)
	{
		 GT_SetGadgetAttrs(mgetGadgets[0], mgetWnd, NULL, GTLV_Labels, filelist, TAG_END);
		 GT_SetGadgetAttrs(mgetGadgets[1], mgetWnd, NULL, GTLV_Labels, getlist, TAG_END);		
	}
	else
	{
		 GT_SetGadgetAttrs(mgetGadgets[0], mgetWnd, NULL, GTLV_Labels, ~0, TAG_END);
		 GT_SetGadgetAttrs(mgetGadgets[1], mgetWnd, NULL, GTLV_Labels, ~0, TAG_END);
	}
}




int mgetappend(void)
{
	AppendMgetFile(NULL);	
}


int AppendMgetFile(char * szOptFileName)
{
	int returnme = 0;
	
	pcWhatToAbort = "Append";

	/* If arg specified, adopt that */
 	if (szOptFileName == NULL)
 	{
 		szOptFileName = inputfile;
 		*inputfile = NUL;	/* force requester */
		if (GetValidFile(szOptFileName) == FALSE) return(FALSE); 
 	}
 	else
		if (FileExists(szOptFileName) == FALSE) return(FALSE);
		 
	SetWaitPointer(mgetWnd);
	SetReqDefaults(szOptFileName);
 

 	pcWhatToAbort = "Append";
	returnme = ReadmyFile(szOptFileName);
	ChangeWindowTitle();
	return(returnme);
}






int mgetCloseWindow (void)
{
	done=TRUE;
}


int mgeticonify (void)
{
	struct MsgPort		*myport  = NULL;
	struct AppIcon		*appicon = NULL;
	struct AppMessage	*amsg  = NULL;
	BOOL BOpen = FALSE;
	char szPathName[MAXFILENAMELENGTH] = "";
	char * pcTemp;
	static char * pcFileName;

	if (appIconObj == NULL) 
	{		
		/* Add path, if there isn't a base in the filename */
		pcTemp = strchr(pcExecName,':');
		if (pcTemp == NULL) strcpy(szPathName,"PROGDIR:");		
			       else pcFileName = pcTemp+1;
		pcTemp = strchr(pcExecName,'/');
		if (pcTemp != NULL) pcFileName = pcTemp+1;
			
		if (pcFileName == NULL) pcFileName = pcExecName;
		
		strncat(szPathName, pcExecName, sizeof(szPathName));
		appIconObj = GetDiskObjectNew(szPathName);
		
		/* backup--use default icon */
		if (appIconObj == NULL) 
		{
			appIconObj = GetDefDiskObject(WBTOOL);
			if (appIconObj == NULL) return(FALSE);
		}
	}

	/* The type must be set to NULL for an AppIcon */
	appIconObj->do_Type = 0L;
	
	myport = CreateMsgPort();
	if (myport)
	{
		AttachLists(FALSE);
		appicon = AddAppIconA(0L, 0L, pcFileName, myport, NULL, appIconObj, NULL);
		if (appicon)
		{
			ClosemgetWindow();
			CloseDownScreen();	/* this handles the workbenchscreen and publicscreen cases too */
			WaitPort(myport);
			BOpen = HandleAppEvents(myport);	/* will open screen and window again here */
			RemoveAppIcon(appicon);
		}
		/* Remove any pending messages */
		while (amsg = (struct AppMessage *) GetMsg(myport)) ReplyMsg((struct Message *)amsg);
		DeleteMsgPort(myport);
		AttachLists(TRUE);
	}
	ChangeWindowTitle();
	SetMenuValues();
	return(1);
}







void SetMenuValues (void)
{
 struct Menu *currentMenu = mgetMenus;
 struct MenuItem *currentItem, *currentSub;

 if (mgetWnd != NULL) ClearMenuStrip(mgetWnd);
 
 currentItem = currentMenu->FirstItem;	  /* Project Menu -- Open */
 currentItem = currentItem->NextItem;     /* Append */
 currentItem = currentItem->NextItem;     /* Save */
 currentItem = currentItem->NextItem;     /* Save As */
 currentItem = currentItem->NextItem;     /* Clear  */
 currentItem = currentItem->NextItem;     /* About */
 currentItem = currentItem->NextItem;     /* Iconify */
 if ((IconBase == NULL)||(IconBase->lib_Version < 37))   
 	currentItem->Flags &= ~(ITEMENABLED);
   else currentItem->Flags |= ITEMENABLED;	
 
 
 /* Make sure the CaseSensitive item in the second menu is checked correctly. */	
 currentMenu = currentMenu->NextMenu;     /* Search Menu */
 currentItem = currentMenu->FirstItem;	  /* #1 : Find Forward */
 currentItem = currentItem->NextItem;	  /* #2 : Find Backward*/
 currentItem = currentItem->NextItem;	  /* #3 : Find from Top */
 currentItem = currentItem->NextItem;	  /* #4 : Find from Bottom */
 currentItem = currentItem->NextItem;	  /* #5 : Find Next */
 currentItem = currentItem->NextItem;	  /* #5 : Find Previous */
 currentItem = currentItem->NextItem;     /* #6 : Find Current */
 currentItem = currentItem->NextItem;     /* #6 : Select */
 currentItem = currentItem->NextItem;     /* #6 : Deselect */
 currentItem = currentItem->NextItem;	  /* #6 : Case Sensitive. */
 
 if (searchcasesensitive)  currentItem->Flags |= CHECKED; 
		    else  currentItem->Flags &= ~(CHECKED);	

 /* next we do the Sort menu. */
 currentMenu = currentMenu->NextMenu;
 if (noparse) currentMenu->Flags &= ~(MENUENABLED);
	   else currentMenu->Flags |= MENUENABLED;

 currentItem = currentMenu->FirstItem;	/* #1: Files List */
 currentSub = currentItem->SubItem;    /* #1.1 : By Directory */
 
 currentSub = currentSub->NextItem;    /* #1.2 : By Size */
 
 currentSub = currentSub->NextItem;    /* #1.3 : By FileName */
 currentSub = currentSub->NextItem;    /* #1.4 : By Description */
 currentSub = currentSub->NextItem;    /* #1.5 : By Age */
 currentSub = currentSub->NextItem;    /* #1.6 : Keep Sorted */
 if (nKeepSorted[0] == 0) currentSub->Flags &= ~(CHECKED);
	   					else currentSub->Flags |= CHECKED;

 currentItem = currentItem->NextItem;  /* #2: Get List */
 currentSub = currentItem->SubItem;    /* #2.1 : By Directory */
 currentSub = currentSub->NextItem;    /* #2.2 : By Size */
 currentSub = currentSub->NextItem;    /* #2.3 : By FileName */
 currentSub = currentSub->NextItem;    /* #2.4 : By Description */
 currentSub = currentSub->NextItem;    /* #2.5 : By Age */
 currentSub = currentSub->NextItem;    /* #2.6 : Keep Sorted */
 if (nKeepSorted[1] == 0) currentSub->Flags &= ~(CHECKED);
	   					else currentSub->Flags |= CHECKED;

 									 
 currentItem = currentItem->NextItem;	/* #3: Sort Type */
 currentSub = currentItem->SubItem;    /* #3.1: Tree Sort */
 if (nSortAlgorithm == TREESORT) currentSub->Flags |= CHECKED;
	   		    else currentSub->Flags &= ~(CHECKED);
 currentSub = currentSub->NextItem;		/* #3.2: Bubble Sort */
 if (nSortAlgorithm == BUBBLESORT)   currentSub->Flags |= CHECKED;
 			    else currentSub->Flags &= ~(CHECKED);

 currentItem = currentItem->NextItem;	/* #4: Case Sensitive */
 if (sortcasesensitive == FALSE) currentItem->Flags &= ~(CHECKED);
 									 else currentItem->Flags |= (CHECKED);
 									   
  						
 /* Output menu. */
 currentMenu = currentMenu->NextMenu;
 
 currentItem = currentMenu->FirstItem;		/* #1: Aminet Parse */
 
 if (noparse) currentItem->Flags &= ~(CHECKED);
	   else currentItem->Flags |= CHECKED;
	   
	   
 currentItem = currentItem->NextItem;		/* #2: Get Files */
 
 if (noparse) currentItem->Flags &= ~(ITEMENABLED);
	   else currentItem->Flags |= ITEMENABLED;
 if (filesflag) currentItem->Flags |= CHECKED;
	  	else currentItem->Flags &= ~(CHECKED);
	  	
 currentItem = currentItem->NextItem;		/* #3: Get Readmes */
 if (noparse) currentItem->Flags &= ~(ITEMENABLED);
	   else currentItem->Flags |= ITEMENABLED;
 if (getreadmes) currentItem->Flags |= CHECKED;
	  	 else currentItem->Flags &= ~(CHECKED);
	
 currentItem = currentItem->NextItem;		/* #4: Split Commands */
 
 if (noparse) currentItem->Flags &= ~(ITEMENABLED);
	   else currentItem->Flags |= ITEMENABLED;
 if (nosplit) currentItem->Flags &= ~(CHECKED);
	  	 else currentItem->Flags |= CHECKED;
	  	 
 
 currentItem = currentItem->NextItem;		/* #5: Use CD's */
 if (noparse) currentItem->Flags &= ~(ITEMENABLED);
	   else currentItem->Flags |= ITEMENABLED;
 if (simplepaths) currentItem->Flags |= CHECKED;
	  	 else currentItem->Flags &= ~(CHECKED);
	  	 
 currentItem = currentItem->NextItem;		/* #6: Line length */
 if ((noparse)||(nosplit)) currentItem->Flags &= ~(ITEMENABLED);
	   else currentItem->Flags |= ITEMENABLED;

 ResetMenuStrip( mgetWnd, mgetMenus );                 
}






/* Turns all \n's in input string into <space><newline>'s */
void FindReturns(char *mystring)
{
 char *thischar=mystring, *prevchar=mystring;

 while (*thischar != NULL)
 {
	
	if ( (*prevchar  ==   92) &&						/* any '/'s ? */
	     ((*thischar ==   78)||(*thischar == 110)) &&      /* N's or n's */
	     (prevchar   !=  NULL) &&						/* Sanity chk */
	     (thischar   !=  NULL))
		
		{
		*prevchar = CHAR_SPACE;   /* set this to a space--easier than shortening string */
		*thischar = CHAR_NEWLINE;   /* and end this line with a newline char */
		}
	prevchar = thischar;
	thischar++;
 }
}









int AddFile(struct List *mylist, char *newstring, int stringlength)
{
 struct Node *newnode;
 char *newname;
 UBYTE diff = MAXFILELINELENGTH;
 const int minlinelength = 1;

 if (keepblanklines == 1) minlinelength = 0;
 if ((newstring == NULL)||((omitcomments == TRUE)&&(*newstring==cCommentChar))) return(0);
 
#ifdef MEMPOOLS_H
 if (!(newnode = (struct Node *) malloc(sizeof(struct Node))))
#else
 if (!( newnode = AllocMem(sizeof(struct Node),MEMF_CLEAR) ))
#endif
 {
	/* emergency bailout! */
	ClearList(filelist); 
	filelist = NULL;
	
	#ifdef MEMPOOLS_H
        free(filelist);
	#else
	FreeMem(filelist,sizeof(struct List));
	#endif
	
	MakeReq("AddFile:  Aborting due to lack of memory",NULL,NULL);
	CleanUp();
	exit(20);
 }
 
#ifdef MEMPOOLS_H
 if (!( newname = (char *) malloc(stringlength+1)))
#else
 if (!( newname = AllocMem(stringlength+1,MEMF_CLEAR) ))
#endif
 {
	/* emergency bailout! */
	#ifdef MEMPOOLS_H
	free(newnode);
	#else
	FreeMem(newnode,sizeof(struct Node));
	#endif
	
	ClearList(filelist); 
	filelist = NULL;
	
	#ifdef MEMPOOLS_H
	free(filelist);
	#else
	FreeMem(filelist,sizeof(struct List));
	#endif
	
	MakeReq("AddFile:  Aborting due to lack of memory",NULL,NULL);
	CleanUp();
	exit(20);
 }
 memset(newname,CHAR_NUL,stringlength+1);	/* clear bytes--this can probably be removed later */
 	
strncpy(newname,newstring,stringlength);   /* copy over the bytes */

newnode->ln_Pri = stringlength - 126;	/* store string length in unused field */
newnode->ln_Name=newname;      	/* and set ze pointer! */

AddTail(mylist, newnode);
return(1);
}



/* Prints out a file.  Makes sure there is a sEndOfLineString after the end of every line */
int PrintFile(char *szFileName, int PrintReturnFirst)
{
	FILE *input_file = fopen(szFileName,"r");
	char inputline[MAXFILELINELENGTH], *a, *b;
	int nLen;

 	if (input_file == NULL) 
 	{
		return(0);
 	}

 	if (PrintReturnFirst == 1)
 	{
 		fprintf(fpOut,sEndOfLineString);
 		
 	}
 		
	/* Read until we get a line-end */
	while(!feof(input_file))
	{
		memset(inputline,NUL,MAXFILELINELENGTH);
		fgets(inputline,MAXFILELINELENGTH,input_file);  /* Read up to MAXFILELINELENGTH chars from inputfile */
		
		nLen = strlen(inputline);
		
		if (nLen >= 2)
		{
			/* make sure that it ends in a sEndOfLineString */
			a = &inputline[strlen(inputline)-2];
			b = &inputline[strlen(inputline)-1];
			
			if ((*a == '\r')&&(*b == '\n')) /* the easy case */
			{
				fprintf(fpOut,"%s",inputline);
			}
			else
			{
				if ((*a != '\r')&&(*b == '\n'))  /* the normal case, for Amigas */
				{
				/* make the newline a return, and then append a newline */
					*b = '\r';
					fprintf(fpOut,"%s\n",inputline);
				}
				else
				{
				if ((*a == '\r')&&(*b != '\n'))	/* the abnormal case */
					{
						*b = '\n';
						fprintf(fpOut,"%s",inputline);
					}
					else
					{
						/* *a != \r, *b != \n */
						fprintf(fpOut,"%s%s",inputline,sEndOfLineString);
					}
				}
			}
		}
		else
		if (nLen == 1) fprintf(fpOut,sEndOfLineString);
	}	
	fclose(input_file);
	return(1);
}


BOOL FillLoadBuffer(FILE * fpIn, UBYTE bWhich)
{
	int nBufferSize = nLoadBufferSize/3;
	int nBytesRead;
	
	if (fpIn == NULL) return(FALSE);
	if (pcEOFat != NULL) return(FALSE);
	
	if (bWhich & 0x01)
	{
		nBytesRead = fread(szLoadBuffer1, sizeof(UBYTE), nBufferSize, fpIn);
		/* printf("Filling Buffer 1, (read %i of %i)\n",nBytesRead, nBufferSize);  */

		if (nBytesRead < nBufferSize)
		{
			/* found EOF! */
			pcEOFat = &szLoadBuffer1[nBytesRead];
			*pcEOFat = CHAR_NUL;	/* NULL terminate here */
			return(TRUE);
		}
	}
	
	if (bWhich & 0x02)
	{
		nBytesRead = fread(szLoadBuffer2, sizeof(UBYTE), nBufferSize, fpIn);
		/* printf("Filling Buffer 2, (read %i of %i)\n",nBytesRead, nBufferSize); */
		if (nBytesRead < nBufferSize)
		{
			/* found EOF! */
			pcEOFat = &szLoadBuffer2[nBytesRead];
			*pcEOFat= CHAR_NUL;	/* NULL terminate here */
			return(TRUE);
		}
	}

	if (bWhich & 0x04)
	{
		nBytesRead = fread(szLoadBuffer3, sizeof(UBYTE), nBufferSize, fpIn);
		/* printf("Filling Buffer 3, (read %i of %i)\n",nBytesRead, nBufferSize); */
		if (nBytesRead < nBufferSize)
		{
			/* found EOF! */
			pcEOFat = &szLoadBuffer3[nBytesRead];
			*pcEOFat= CHAR_NUL;	/* NULL terminate here */
			return(TRUE);
		}
	}

	return(TRUE);
}


/* operates much like strchr, only knows to wrap around once. */
char * FindCharInBuffer(char * szStartAt, char cLookForArg)
{	
	register char * pcTemp = szStartAt;
	register char * szBeganAt = szStartAt;
	register char cLookFor = cLookForArg;
	
	while ((*pcTemp != CHAR_NUL)&&(*pcTemp != cLookFor))
	{		
		pcTemp++;
		if (pcTemp >= szLoadBufferT) pcTemp = szLoadBuffer1;
		else if (pcTemp == szBeganAt) return(NULL);
	}
	return(pcTemp);
}



/* Return a pointer to the next sentence in the buffer */
char * GetMoreText(FILE * fpIn)
{
	int nStartPartition=0, nEndPartition=0;
	char *pcStartOfString; 
	char *pcEndOfString;
	static BOOL BThisIsTheLast = FALSE;
	
	if (BThisIsTheLast == TRUE)
	{
		BThisIsTheLast = FALSE;
		return(NULL);
	}
	
	
	/* Make sure we don't go off the end */
	if (pcLoadCurrent >= szLoadBufferT) pcStartOfString = szLoadBuffer1;
	
	/* Get start (first char) and end (nul char) of current string */
	pcStartOfString = pcLoadCurrent;


	/* Find the end of the current line */
	pcEndOfString = FindCharInBuffer(pcStartOfString, CHAR_NEWLINE);
	if (pcEndOfString == NULL) return(NULL);	/* should never happen! */
		
	
	/* terminate our string */
	*pcEndOfString = CHAR_NUL;
	if (*(pcEndOfString-1) == CHAR_RETURN) *(pcEndOfString-1) = CHAR_SPACE;

	/* If we're at the EOF, then cause the file loading to stop */
	if (pcStartOfString == pcEOFat) return(NULL);
	
	/* If we somehow skip over the EOF, we'll return this line and then 
	   be sure to return NULL next time */
	if (pcEOFat)
	{
		if (((pcStartOfString <= pcEOFat)&&(pcEndOfString >= pcEOFat)) ||
		    ((pcStartOfString >= pcEOFat)&&(pcEndOfString <= pcEOFat)))
			     BThisIsTheLast = TRUE;
	}
	
	/* Cases:
	
		1) Entirely in buffer 1.   Return pointer to string.
		2) Entirely in buffer 2.    ""
		3) Entirely in buffer 3.    ""
		4) In 1 and 2.		    "", load buffer 3.  
		5) In 2 and 3.              "", load buffer 1.
		6) In 3 and 1.             Copy two pieces to szLoadBufferT, load buffer 2.
	*/

	
	/* First figure out which case we're in. */
	if (pcStartOfString >= szLoadBuffer3) nStartPartition = 3;	
	else if (pcStartOfString >= szLoadBuffer2) nStartPartition = 2;
  	else if (pcStartOfString >= szLoadBuffer1) nStartPartition = 1;

	if (pcEndOfString == (szLoadBufferT-1)) nEndPartition = 1;	/* wrap around */
	else if (pcEndOfString >= szLoadBuffer3) nEndPartition = 3;
	else if (pcEndOfString >= szLoadBuffer2) nEndPartition = 2;
	else if (pcEndOfString >= szLoadBuffer1) nEndPartition = 1;
	
	/* If start and end aren't in one partition, do extra stuff */
	if (nStartPartition != nEndPartition)
	{
		if ((nStartPartition == 1)&&(nEndPartition == 2)) 
		{
			FillLoadBuffer(fpIn, 0x4); 
		}
		else if ((nStartPartition == 2)&&(nEndPartition == 3)) 
		{
			FillLoadBuffer(fpIn, 0x1);
		}
		else if ((nStartPartition == 3)&&(nEndPartition == 1))
		{
			FillLoadBuffer(fpIn, 0x2); 
			*(szLoadBufferT-1) = CHAR_NUL;
			strncpy(szLoadBufferT,pcStartOfString,MAXFILELINELENGTH);
			strncat(szLoadBufferT,szLoadBuffer1,MAXFILELINELENGTH);
			pcStartOfString = szLoadBufferT;
			*(szLoadBufferT-1) = '~';
		}
	}

	/* Set this to the next string for next time */
	pcLoadCurrent = pcEndOfString+1;
	
	/* return the current string */
	return(pcStartOfString);
}




BOOL SetUpBufferPairs(FILE * fpIn, BOOL BAlloc)
{	
	if (BAlloc == TRUE)
	{
		/* Allocate memory */
		while (szLoadBuffer1 == NULL)
		{
			szLoadBuffer1 = (char *) malloc(nLoadBufferSize+1+MAXFILELINELENGTH);
			if (szLoadBuffer1 == NULL) 
			{	
				nLoadBufferSize /= 10;
				while ((nLoadBufferSize % 3) != 0) nLoadBufferSize++;
				if (nLoadBufferSize < 1024) return(FALSE);
			}
		}
		
		if (szLoadBuffer1 == NULL) return(FALSE);

		szLoadBuffer2 = &szLoadBuffer1[nLoadBufferSize/3];
		szLoadBuffer3 = &szLoadBuffer1[2*nLoadBufferSize/3];
		
		szLoadBufferT = &szLoadBuffer1[nLoadBufferSize];
		*szLoadBufferT = '~';		
		szLoadBufferT++;		/* start overflow array after NUL */
		
		pcLoadCurrent = szLoadBuffer1;
		pcEOFat = NULL;

		FillLoadBuffer(fpIn, 0x1|0x2 );
	}
	else
	{
		/* Free memory, if it's allocated. */
		if (szLoadBuffer1 != NULL) 
		{
			free(szLoadBuffer1);
			szLoadBuffer1 = NULL;
			szLoadBuffer2 = NULL;
			szLoadBuffer3 = NULL;
			szLoadBufferT = NULL;
			pcEOFat       = NULL;
			pcLoadCurrent = NULL;
		}
	}
	return(TRUE);
}


 
/* returns the number of lines successfully parsed and added to the list */
int ReadmyFile(char * szInFile)
{
 FILE *input_file = NULL;
 char *inputline = NULL;
 int nStringLength, okline = 0, nUpdate = 50;
 int filelength = 0, failed_lines = 0;
 int minlinelength = 1;
 struct List * thislist = filelist;
 int nBookMarkLength = strlen(szBookMark);
 
 if (keepblanklines == 1) minlinelength = 0;

 input_file = fopen(szInFile,"r");
 if (input_file == NULL) return(FALSE);

 /* Valid file--set this now. */
 if (szInFile != inputfile) strncpy(inputfile, szInFile, sizeof(inputfile));
 
 SetWaitPointer(mgetWnd);

 SetReqDefaults(szInFile);
 
 AttachLists(FALSE);
 
 if (SetUpBufferPairs(input_file, TRUE) == FALSE)
  	MakeReq("No memory for load buffers",NULL,NULL);
   else inputline = "";
 
 
 while (inputline)
 {
	filelength++;		
	okline=0;  
	/* Read until we get a line-end */
	while((!okline)&&(inputline))
	{
		/* Not necessary, I think: memset(inputline,NUL,MAXFILELINELENGTH); */
		inputline = GetMoreText(input_file);  /* Read up chars from szInFile buffer */
		if (inputline != NULL)
		{
			nStringLength = strlen(inputline);
			if ((nStringLength >= minlinelength)&&(nStringLength < MAXFILELINELENGTH)) okline=1;
		}
	}
	
	if ((inputline)&&((nStringLength < MAXFILELINELENGTH)||(noparse)))
	{		
		/* Check to see if we have a szBookMark */
		if (strncmp(inputline, szBookMark, nBookMarkLength) == 0) thislist = getlist;
		else
		{	
		      	if (AddFile(thislist, inputline, nStringLength) == TRUE)
      			{
		      		if (thislist == filelist) filelist_length++;
	      				else if (thislist == getlist) 
	      				{
	      					if (!noparse) UpdateByteCount(inputline,1);
	      					getlist_length++;
	      				}
				if (nUpdate == 0)
				{
					sprintf(windowtitle,"Loading: %i",filelist_length);
					if (mgetWnd != NULL) SetWindowTitles(mgetWnd, windowtitle , (char *) ~0);
					nUpdate = 125;
					if (CheckForUserAbort() == TRUE) inputline = NULL;
				}
				else nUpdate--;
	     		}
		      	else failed_lines++;
		}
	}
	else failed_lines++;	      
 }
 
 SetUpBufferPairs(input_file, FALSE);
 fclose(input_file);
 
 if ((nKeepSorted[0] == 1)&&(!noparse)) SortList(filelist,nSortType[0]);  /* keep sorted if that is selected! */
 if ((nKeepSorted[1] == 1)&&(!noparse)) SortList(getlist,nSortType[1]);  /* keep sorted if that is selected! */

 AttachLists(TRUE);

 ChangeWindowTitle();
 ClearWaitPointer(mgetWnd);	
 return(filelist_length);
}






void ChangeWindowTitle(void)
{
	char *fstring = inputfile, *f2;
	char sSubString[60];
	int charlength = (windowwidth-81)/8 - 40;

	if (mgetWnd == NULL) return;
	
	if (charlength <= 0) 
	{
		fstring = sSubString;
		fstring[0] = NUL;
	}
	else
	if (strlen(fstring) > charlength)
	{
		f2 = inputfile + strlen(inputfile) - charlength - 1;	
		if (f2 > inputfile)
		{
			fstring = sSubString;
			strcpy(fstring,f2);
		}
	}	
	sprintf(windowtitle,"(%s) %i files, %u kilobytes selected.",fstring, getlist_length, kbytes_selected);   
	SetWindowTitles(mgetWnd, windowtitle , (char *) ~0); 
	return();
}









VOID UpdateByteCount(char *mystring, int addorsub)
{
	kbytes_selected = kbytes_selected + (AminetFileSize(mystring) * addorsub);
	return();
}











VOID CleanUp(void)
{

 if ((fpOut != stdout)&&(fpOut != NULL)) fclose(fpOut);

 SetUpBufferPairs(NULL, FALSE);

 if (appIconObj) FreeDiskObject(appIconObj);

 if (listfontdata)  CloseFont(listfontdata);
 if (windowisopen)  {ClosemgetWindow();  windowisopen = FALSE; mgetWnd = NULL;}
 if (screenisopen)  {CloseDownScreen();  screenisopen = FALSE; Scr = NULL;}
 if (filelist)	    
 {
     ClearList(filelist); 
     #ifdef MEMPOOLS_H
     free(filelist);
     #else
     FreeMem(filelist,sizeof(struct List));
     #endif
     
 }
 if (getlist) 
 {
     ClearList(getlist);
     
     #ifdef MEMPOOLS_H
     free(getlist);
     #else
     FreeMem(getlist,sizeof(struct List));
     #endif
 }
 if (WorkbenchBase) CloseLibrary((struct Library *)WorkbenchBase);
 if (IconBase)      CloseLibrary((struct Library *)IconBase);
 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
 if (AslBase)	    CloseLibrary((struct Library *)AslBase);
 if (UtilityBase)   CloseLibrary((struct Library *)UtilityBase);
 if (GraphicsBase)  CloseLibrary((struct GraphicsLib *)GraphicsBase);
 if (GadToolsBase)  CloseLibrary((struct Library *)GadToolsBase);
 return();
}











int RequestAFile(char *szBuffer, BOOL BSave)
{
	int rvalue = 1;
	LONG lFlags = FILF_PATGAD;
	char szOpen[] = "Open", szSave[] = "Save";
	char * szOkayText = szOpen;
	char * szHailText = "Select a text file to browse.";
	
	if (strlen(defDir) == 0) strcpy(defDir,"ram:");
	if (strlen(defFile)== 0) strcpy(defFile,"RECENT");

	SetWaitPointer(mgetWnd);

	if (BSave == TRUE) 
	{
		szHailText = "Select a file to save to.";
		lFlags |= FILF_SAVE;
		szOkayText = szSave;
	}
	
	struct TagItem frtags[] =
	{
		ASL_Hail,	(ULONG)szHailText,
		ASL_Height,	350,
		ASL_Width,	320,
		ASL_LeftEdge,	50,
		ASL_TopEdge,	35,
		ASL_OKText,	(ULONG)szOkayText,
		ASL_CancelText, (ULONG)"Cancel",
		ASL_File,	defFile,
		ASL_Dir,	defDir,
		ASL_Window,	mgetWnd,
		ASL_FuncFlags,  lFlags,
		ASL_Pattern,	szFilePattern,
		TAG_DONE
	};

	struct FileRequester *fr;
	
	fr = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, frtags);
	if (fr == NULL) rvalue = 0;
			
 	if ((rvalue)&&(AslRequest(fr, NULL)))
	{
		strcpy(szBuffer,fr->rf_Dir);
		strncpy(defDir,fr->rf_Dir,sizeof(defDir));
		strncpy(defFile,fr->rf_File,sizeof(defFile));
		if ((defDir[strlen(defDir)-1] != '/')&&
		    (defDir[strlen(defDir)-1] != ':')) strcat(szBuffer,"/");
		strcat(szBuffer,fr->rf_File);
	}
	else rvalue = 0;
	
	if (fr != NULL) FreeAslRequest(fr);
	ClearWaitPointer(mgetWnd);
	if (rvalue == 1) SetReqDefaults(szBuffer);
	return(rvalue);
}




void SetWaitPointer(struct Window * mywin)
{
	if (mywin != NULL) SetPointer(mywin, waitPointer, 16, 16, -6, 0);
}

void ClearWaitPointer(struct Window * mywin)
{
	if (mywin != NULL) ClearPointer(mywin);
}





void TurnOnAllMenuItems(struct Menu *myMenu)
{
struct MenuItem *mItem;

 while (myMenu != NULL)
	{
	mItem = myMenu->FirstItem;
	while (mItem != NULL)
		{
		mItem->Flags |= ITEMENABLED;
		mItem = mItem->NextItem;
		}
	myMenu = myMenu->NextMenu;
	}
return;
}










VOID SetReqDefaults(char *szFilePath)
{
char *sFileStart;

 sFileStart = strrchr(szFilePath,'/');
 if (sFileStart == NULL)
 	{
 	sFileStart = strrchr(szFilePath,':');
 	if (sFileStart == NULL)
 		{
 		sFileStart = szFilePath;
 		}
 	}
 
 if (sFileStart != NULL) strncpy(defFile,sFileStart+(sFileStart != szFilePath),sizeof(defFile));
 if ((sFileStart != NULL)&&(sFileStart != szFilePath)) strncpy(defDir,szFilePath,(sFileStart - szFilePath) + 1);
 return();
}

 




VOID UpperCase(char *sOldString)
{
char *i = sOldString;
const int diff = 'a' - 'A';

 if (sOldString == NULL) return();
 while (*i != CHAR_NUL)
 {
	if ((*i >= 'a')&&(*i <= 'z')) *i = *i - diff;
	i++;
 }
return();
}





VOID LowerCase(char *sOldString)
{
char *i = sOldString;
const int diff = 'a' - 'A';

 if (sOldString == NULL) return();
 while (*i != CHAR_NUL)
 {
	if ((*i >= 'A')&&(*i <= 'Z')) *i = *i + diff;
	i++;
 }

return();
}






int mgetoutput(void)
{
	FILE *fpTemp = NULL;

	if (getlist_length > 0) 
	{
		/* If no output name given, do default output... */
 		if (strlen(sOutFileName) == 0)
 		{
 			/* for Workbench, absolute default is ram:GadMget.output */
 			if (BStartedFromWB == TRUE)
 			{
 				fpTemp = fopen("ram:Gadmget.Output","w");
 				if (fpTemp == NULL) 
 				{
 				   MakeReq("Error:  Couldn't open ram:GadMget.output for writing!",NULL,NULL);
					CleanUp();
					exit(10);
 				}
 			}
 			else
 			{	/* for the CLI, default is stdout */
 				fpTemp = stdout;
 			}
 		}
 		else
 		{
			/* open requested output file for writing */
			fpTemp = fopen(sOutFileName,"w");
			if (fpTemp == NULL)
			{
				MakeReq("Error:  Couldn't open output file!",NULL,NULL);
			}
		}
			
 		fpOut = fpTemp;
		PrintFile(szHeaderFile,0);
		if (noparse) RawOutputList(getlist);
				   else OutputList(getlist); 
		PrintFile(szFooterFile,1);
		if (fpOut != stdout) fclose(fpOut); else fflush(fpOut);
	}
	return(0);
}



VOID ParseCliArgs(int argc, char *argv[])
{
 int nextpasslookfor = 0;
 FILE *fpTemp = NULL;

 pcExecName = argv[0];

 memset(defDir,NUL,sizeof(defDir));
 memset(defFile,NUL,sizeof(defFile));
 memset(szHeaderFile,NUL,sizeof(szHeaderFile));
 memset(szFooterFile,NUL,sizeof(szFooterFile));
 memset(inputfile,NUL,sizeof(inputfile));
 
 if (argc > 1) 
 {
 	strncpy(inputfile,argv[1],sizeof(inputfile));
 	SetReqDefaults(inputfile);
 }
 		
 if (*inputfile == '?')
 {
	fprintf(fpOut,"%s",template);
	CleanUp();
	exit(0);
 }
 
 for (int i=2; i<=argc; i++)
 {
	if (nextpasslookfor == 2)
	{
		strncpy(szPubScreenName,argv[i-1],sizeof(szPubScreenName));
		pubscreenname = szPubScreenName;
		screentype = USE_PUBSCREEN;
		continue;			/* skip to next loop */
	}
   	if (nextpasslookfor == 7) 		/* FILE PARAMETER */
 	{
 		strncpy(inputfile,argv[i-1],sizeof(inputfile));
 		SetReqDefaults(inputfile);
 	}
	if (nextpasslookfor == 9)		/* COMMAND PARAMETER */
	{
		strncpy(szCommandString,argv[i-1],sizeof(szCommandString));
	}
	if (nextpasslookfor == 16)	/* AMINETPATH PARAMETER */
	{
		strncpy(sAminetPathString,argv[i-1],sizeof(sAminetPathString));
	}
	if (nextpasslookfor == 17)	/* EOL PARAMETER */
	{
		strncpy(sEndOfLineString,argv[i-1],sizeof(sEndOfLineString));
		EOLParse(sEndOfLineString);
	}
	if (nextpasslookfor == 19)	/* COMMENTCHAR PARAMETER */
	{
		cCommentChar = *argv[i-1];
	}

	
	UpperCase(argv[i-1]);

	switch(nextpasslookfor)
	{	
	case(1):
		if (atoi(argv[i-1]) > 0)  maxoutputlinelength = atoi(argv[i-1]);
		break;
		
	/* case 2 is up above, before the Upper() command */
	
	case(3):		/* WIDTH PARAMETER */
		if (atoi(argv[i-1]) > 0)  windowwidth = 155;	/* min level */
		if (atoi(argv[i-1]) > 155) windowwidth = atoi(argv[i-1]);
		break;
	case(4):		/* HEIGHT PARAMETER */
		if (atoi(argv[i-1]) > 0) windowheight = 167;	/* min level */
		if (atoi(argv[i-1]) > 167) windowheight = atoi(argv[i-1]);
		break;
	case(5):		/* TOP PARAMETER */
		if (atoi(argv[i-1]) > 0) windowtop = atoi(argv[i-1]);
		break;
	case(6):		/* LEFT PARAMETER */
		if (atoi(argv[i-1]) > 0) windowleft = atoi(argv[i-1]);
		break;
		
	/* Case 7 is up above, before the Upper() command */
	
	case(8):		/* OUTPUT PARAMETER */
		strncpy(sOutFileName,argv[i-1],sizeof(sOutFileName));
		break;
	
	/* Case 9 is up above, before the Upper() command */
	
	case(10):		/* HEADER PARAMETER */
		strncpy(szHeaderFile,argv[i-1],sizeof(szHeaderFile));
		break;
		
	case(11):		/* FOOTER PARAMETER */
		strncpy(szFooterFile,argv[i-1],sizeof(szFooterFile));
		break;

	case(12):		/* FONT PARAMETER */
		strncpy(sListFontName,argv[i-1],sizeof(sListFontName));
		LowerCase(sListFontName);
		if (strstr(sListFontName,".font") == NULL) strncat(sListFontName,".font",sizeof(sListFontName));
		break;
		
	case(13):		/* FONTSIZE PARAMETER */
		if (atoi(argv[i-1]) > 0) nListFontSize = atoi(argv[i-1]);
		break;
	
	case(14):		/* FILESORT PARAMETER */
		LowerCase(argv[i-1]);
		if (strcmp(argv[i-1],"directory") == 0)   nSortType[0] = SORTBYDIR;
		if (strcmp(argv[i-1],"filename") == 0)    nSortType[0] = SORTBYNAME;
		if (strcmp(argv[i-1],"size") == 0)        nSortType[0] = SORTBYSIZE;
		if (strcmp(argv[i-1],"description") == 0) nSortType[0] = SORTBYDESC;
		if (strcmp(argv[i-1],"age") == 0) 	  nSortType[0] = SORTBYAGE;
		break;
			
	case(15):		/* GETSORT PARAMETER */
		LowerCase(argv[i-1]);
		if (strcmp(argv[i-1],"directory") == 0)   nSortType[1] = SORTBYDIR;
		if (strcmp(argv[i-1],"filename") == 0)    nSortType[1] = SORTBYNAME;
		if (strcmp(argv[i-1],"size") == 0)        nSortType[1] = SORTBYSIZE;
		if (strcmp(argv[i-1],"description") == 0) nSortType[1] = SORTBYDESC;
		if (strcmp(argv[i-1],"age") == 0) 	  nSortType[1] = SORTBYAGE;
		break;

	/* Case 16 is up above the Upper() command */

	/* Case 17 is up above the Upper() command */
	
	case(18):		/* FILEPAT PARAMETER */
		strncpy(szFilePattern,argv[i-1],sizeof(szFilePattern));
		break;
	
	/* Case 19 is up above the Upper() command */

	case(20):		/* LOADBUFFERS PARAMETER */
		nLoadBufferSize = atoi(argv[i-1]);
		if (nLoadBufferSize < 1) nLoadBufferSize = 1;
		nLoadBufferSize *= 1024;
		while ((nLoadBufferSize % 3) != 0) nLoadBufferSize++;
		break;

	case(21):		/* CLOSEACTION PARAMETER */
		LowerCase(argv[i-1]);
		if (strcmp(argv[i-1],"save") == 0)   nCloseAction = ACTION_SAVE;
		if (strcmp(argv[i-1],"output") == 0) nCloseAction = ACTION_OUTPUT;
		if ((strcmp(argv[i-1],"saveoutput") == 0)||(strcmp(argv[i-1],"outputsave") == 0)) 
						     nCloseAction = (ACTION_OUTPUT | ACTION_SAVE);
		if ((strcmp(argv[i-1],"quit") == 0)||(strcmp(argv[i-1],"none") == 0)) 
						     nCloseAction  = ACTION_NONE;
		break;
		
						
	default:
		/* nothing */
		break;		
	}
	nextpasslookfor = 0;
	if (strcmp(argv[i-1],"NOAPPWINDOW") == 0)         appwindow = FALSE;
	if (strcmp(argv[i-1],"SEARCHCASESENSITIVE") == 0) searchcasesensitive = TRUE;	
	if (strcmp(argv[i-1],"SORTCASESENSITIVE") == 0)   sortcasesensitive= TRUE;	
	if (strcmp(argv[i-1],"CASESENSITIVE") == 0) 
	{
		sortcasesensitive= TRUE;	
		searchcasesensitive = TRUE;
	}

	if (strcmp(argv[i-1],"NOPARSE") == 0) 		noparse = TRUE;
	if (strcmp(argv[i-1],"NOCOMMAND") == 0) 	nocommand = TRUE;
	if (strcmp(argv[i-1],"NOSPLIT") == 0) 		nosplit = TRUE;
	if (strcmp(argv[i-1],"GETREADMES") == 0) 	getreadmes = TRUE;	
	if (strcmp(argv[i-1],"NOCD") == 0)		nocd = TRUE;
   	if (strcmp(argv[i-1],"NOFILES") == 0) 
   	{
    		filesflag  = FALSE;
    		getreadmes = TRUE;
    	}
 	if (strcmp(argv[i-1],"LINELENGTH") == 0)        nextpasslookfor= 1;
 	if (strcmp(argv[i-1],"PUBSCREEN") == 0)		nextpasslookfor= 2;
	if (strcmp(argv[i-1],"DEFPUBSCREEN") == 0)	screentype = USE_PUBSCREEN; 	
	if ((strcmp(argv[i-1],"WBSCREEN") == 0)||
	    (strcmp(argv[i-1],"WORKBENCHSCREEN") == 0)) screentype = USE_WBSCREEN;
	if (strcmp(argv[i-1],"NOSIMPLEPATHS") == 0)	simplepaths  = FALSE;	
	if (strcmp(argv[i-1],"KEEPBLANKLINES") == 0)    keepblanklines = TRUE;
	if (strcmp(argv[i-1],"KEEPFILESSORT") == 0)     nKeepSorted[0] = TRUE;
	if (strcmp(argv[i-1],"KEEPGETSORT") == 0)       nKeepSorted[1] = TRUE;
	if (strcmp(argv[i-1],"OMITCOMMENTS") == 0)      omitcomments = TRUE;
																					
	if (strcmp(argv[i-1],"WIDTH") == 0)	nextpasslookfor = 3;
	if (strcmp(argv[i-1],"HEIGHT") == 0)	nextpasslookfor = 4;
	if (strcmp(argv[i-1],"TOP") == 0)	nextpasslookfor = 5;
	if (strcmp(argv[i-1],"LEFT") == 0)	nextpasslookfor = 6;
	if (strcmp(argv[i-1],"FILE") == 0)	nextpasslookfor = 7;
	if (strcmp(argv[i-1],"OUTPUT") == 0)	nextpasslookfor = 8;
	if (strcmp(argv[i-1],"COMMAND") == 0)	nextpasslookfor = 9;
	if (strcmp(argv[i-1],"HEADER") == 0)	nextpasslookfor = 10;
	if (strcmp(argv[i-1],"FOOTER") == 0)	nextpasslookfor = 11;
	if (strcmp(argv[i-1],"FONT") == 0)      nextpasslookfor = 12;
	if ((strcmp(argv[i-1],"FONTSIZE") == 0) ||
	    (strcmp(argv[i-1],"SIZE") == 0))    nextpasslookfor = 13;
	if (strcmp(argv[i-1],"FILESORT") == 0)  nextpasslookfor = 14;
	if (strcmp(argv[i-1],"GETSORT") == 0)   nextpasslookfor = 15;
	if (strcmp(argv[i-1],"AMINETPATH") == 0)nextpasslookfor = 16;
	if (strcmp(argv[i-1],"EOL") == 0)       nextpasslookfor = 17;
	if ((strcmp(argv[i-1],"FILEPAT") == 0)||
	    (strcmp(argv[i-1],"FILEPATTERN") == 0)) nextpasslookfor = 18;
	if (strcmp(argv[i-1],"COMMENTCHAR") == 0)   nextpasslookfor = 19;
	if (strcmp(argv[i-1],"LOADBUFFERS") == 0)   nextpasslookfor = 20;
	if (strcmp(argv[i-1],"CLOSEACTION") == 0)   nextpasslookfor = 21;
 }

return();
}










VOID wbmain(struct WBStartup *argv)
{
	BStartedFromWB = TRUE;
	IconBase = OpenLibrary("icon.library",33);
	if (IconBase == NULL) exit(2);
	ParseWBArgs(argv);
	pcExecName = (struct WBStartup *)argv->sm_ArgList->wa_Name;
	main(0,argv);
}








VOID ParseWBArgs(struct WBStartup *argv)
{
struct WBArg *wb_arg = argv->sm_ArgList;
struct DiskObject *dobj;
char **toolarray, *sTemp;
FILE *fpTemp = NULL;


memset(defDir,NUL,sizeof(defDir));
memset(defFile,NUL,sizeof(defFile));
memset(szHeaderFile,NUL,sizeof(szHeaderFile));
memset(szFooterFile,NUL,sizeof(szFooterFile));


/* Parse the tooltypes from the program file */
dobj = GetDiskObject(wb_arg->wa_Name);

if (dobj != NULL)
 {
 	toolarray = (char **) dobj->do_ToolTypes;
	if (toolarray != NULL)
	{
	
		if (sTemp = (char *) FindToolType(toolarray,"OUTPUT")) 
		{
		  strncpy(sOutFileName,sTemp,sizeof(sOutFileName));
		}
											
		if (sTemp = (char *) FindToolType(toolarray,"FILE")) 
		{
			strncpy(inputfile,sTemp,sizeof(inputfile));
			SetReqDefaults(inputfile);
		}
		if (sTemp = (char *) FindToolType(toolarray,"NOPARSE"))   	noparse     = TRUE;
		if (sTemp = (char *) FindToolType(toolarray,"NOCOMMAND"))  	nocommand   = TRUE;
   		if (sTemp = (char *) FindToolType(toolarray,"NOSPLIT"))   	nosplit     = TRUE;	
   		if (sTemp = (char *) FindToolType(toolarray,"OMITCOMMENTS"))   	omitcomments = TRUE;	
   		if (sTemp = (char *) FindToolType(toolarray,"GETREADMES"))  getreadmes  = TRUE;
		if (sTemp = (char *) FindToolType(toolarray,"NOFILES"))
		{
			filesflag 	= FALSE;
   	 		getreadmes  = TRUE;
		}
   		if (sTemp = (char *) FindToolType(toolarray,"LINELENGTH"))
   		{
   			if (atoi(sTemp) > 0)  maxoutputlinelength = atoi(sTemp); 
   		}
  				
  		if (sTemp = (char *) FindToolType(toolarray,"PUBSCREEN"))   
  		{
  			strcpy(szPubScreenName,sTemp);
  			pubscreenname = szPubScreenName;
  			screentype = USE_PUBSCREEN;
  		}
  		
  		if (sTemp = (char *) FindToolType(toolarray,"NOSIMPLEPATHS"))	simplepaths = FALSE;		
  		if (sTemp = (char *) FindToolType(toolarray,"NOPARSE"))   	noparse = TRUE;		
		if (sTemp = (char *) FindToolType(toolarray,"NOAPPWINDOW")) 	appwindow = FALSE;
		if (sTemp = (char *) FindToolType(toolarray,"WBSCREEN"))  	screentype = USE_WBSCREEN;
		if (sTemp = (char *) FindToolType(toolarray,"WORKBENCHSCREEN")) screentype = USE_WBSCREEN;								
		if (sTemp = (char *) FindToolType(toolarray,"NOCD"))		nocd = TRUE;
		if (sTemp = (char *) FindToolType(toolarray,"KEEPBLANKLINES")) 	keepblanklines = TRUE;
		if (sTemp = (char *) FindToolType(toolarray,"KEEPFILESORT")) 	nKeepSorted[0] = TRUE;
		if (sTemp = (char *) FindToolType(toolarray,"KEEPGETSORT")) 	nKeepSorted[1] = TRUE;
		
		if (sTemp = (char *) FindToolType(toolarray,"WIDTH")) 							
		{
			if (atoi(sTemp) > 0)  windowwidth = 155;	/* min level */
			if (atoi(sTemp) > 155) windowwidth = atoi(sTemp);
		}
		if (sTemp = (char *) FindToolType(toolarray,"HEIGHT")) 	
		{						
			if (atoi(sTemp) > 0) windowheight = 167;	/* min level */
			if (atoi(sTemp) > 167) windowheight = atoi(sTemp);
		}
		if (sTemp = (char *) FindToolType(toolarray,"TOP")) 							
		{
			if (atoi(sTemp) > 0) windowtop = atoi(sTemp);
		}
		if (sTemp = (char *) FindToolType(toolarray,"LEFT")) 							
		{
			if (atoi(sTemp) > 0) windowleft = atoi(sTemp);
		}					
		if (sTemp = (char *) FindToolType(toolarray,"SEARCHCASESENSITIVE")) 							
		{
			searchcasesensitive = 1;
		}
		if (sTemp = (char *) FindToolType(toolarray,"SORTCASESENSITIVE")) 							
		{
			sortcasesensitive = 1;
		}
		if (sTemp = (char *) FindToolType(toolarray,"CASESENSITIVE")) 							
		{
			searchcasesensitive = 1;
			sortcasesensitive = 1;
		}

		if (sTemp = (char *) FindToolType(toolarray,"COMMAND"))
		{
			strncpy(szCommandString,sTemp,sizeof(szCommandString));
		}
		if (sTemp = (char *) FindToolType(toolarray,"HEADER"))
		{
			strncpy(szHeaderFile,sTemp,sizeof(szHeaderFile));
		}
		if (sTemp = (char *) FindToolType(toolarray,"FOOTER"))
		{
			strncpy(szFooterFile,sTemp,sizeof(szFooterFile));
		}
		if (sTemp = (char *) FindToolType(toolarray,"FONT"))
		{
			strncpy(sListFontName,sTemp,sizeof(sListFontName));
			LowerCase(sListFontName);
			if (strstr(sListFontName,".font") == NULL) strncat(sListFontName,".font",sizeof(sListFontName));
		}
		if (sTemp = (char *) FindToolType(toolarray,"FONTSIZE"))
		{
			if (atoi(sTemp) > 0) nListFontSize = atoi(sTemp);
		}
		if (sTemp = (char *) FindToolType(toolarray,"SIZE"))
		{
			if (atoi(sTemp) > 0) nListFontSize = atoi(sTemp);
		}
		if (sTemp = (char *) FindToolType(toolarray,"FILESORT"))
		{
			LowerCase(sTemp);
			if (strcmp(sTemp,"directory") == 0)   nSortType[0] = SORTBYDIR;
			if (strcmp(sTemp,"filename") == 0)    nSortType[0] = SORTBYNAME;
			if (strcmp(sTemp,"size") == 0)        nSortType[0] = SORTBYSIZE;
			if (strcmp(sTemp,"description") == 0) nSortType[0] = SORTBYDESC;
			if (strcmp(sTemp,"age") == 0) 	      nSortType[0] = SORTBYAGE;
		}
		if (sTemp = (char *) FindToolType(toolarray,"GETSORT"))
		{
			LowerCase(sTemp);
			if (strcmp(sTemp,"directory") == 0)   nSortType[1] = SORTBYDIR;
			if (strcmp(sTemp,"filename") == 0)    nSortType[1] = SORTBYNAME;
			if (strcmp(sTemp,"size") == 0)        nSortType[1] = SORTBYSIZE;
			if (strcmp(sTemp,"description") == 0) nSortType[1] = SORTBYDESC;
			if (strcmp(sTemp,"age") == 0) 	      nSortType[1] = SORTBYAGE;
		}	
						
		if (sTemp = (char *) FindToolType(toolarray,"AMINETPATH"))
			strncpy(sAminetPathString,sTemp,sizeof(sAminetPathString));

		if (sTemp = (char *) FindToolType(toolarray,"FILEPAT"))
			strncpy(szFilePattern,sTemp,sizeof(szFilePattern));
		if (sTemp = (char *) FindToolType(toolarray,"FILEPATTERN"))
			strncpy(szFilePattern,sTemp,sizeof(szFilePattern));

		if (sTemp = (char *) FindToolType(toolarray,"EOL"))
		{
			strncpy(sEndOfLineString,sTemp,sizeof(sEndOfLineString));
			EOLParse(sEndOfLineString);
		}
		
		if (sTemp = (char *) FindToolType(toolarray,"COMMENTCHAR"))
		{
			cCommentChar = (*sTemp);
		}				
		if (sTemp = (char *) FindToolType(toolarray,"LOADBUFFERS"))
		{
			nLoadBufferSize = atoi(sTemp);
			if (nLoadBufferSize < 1) nLoadBufferSize = 1;
			nLoadBufferSize *= 1024;
			while ((nLoadBufferSize % 3) != 0) nLoadBufferSize++;
		}				
		if (sTemp = (char *) FindToolType(toolarray,"CLOSEACTION"))
		{
			LowerCase(sTemp);
			if (strcmp(sTemp,"save") == 0)   nCloseAction = ACTION_SAVE;
			if (strcmp(sTemp,"output") == 0) nCloseAction = ACTION_OUTPUT;
			if ((strcmp(sTemp,"saveoutput") == 0)||(strcmp(sTemp,"outputsave") == 0)) 
							 nCloseAction = (ACTION_OUTPUT | ACTION_SAVE);
			if ((strcmp(sTemp,"none") == 0)||(strcmp(sTemp,"quit") == 0))
						         nCloseAction  = ACTION_NONE;
		}
	}
 FreeDiskObject(dobj);
 }
 
 /* Get the name of the file extended_clicked, if there is one */
 if (argv->sm_NumArgs > 1) 
 {
	wb_arg++;	/* The first name is the programs name, the 2nd is the proj. icon */
	if (wb_arg->wa_Name != NULL) 
	{
		strncpy(inputfile,wb_arg->wa_Name,sizeof(inputfile));
		CurrentDir(wb_arg->wa_Lock);
	}
 }
	
return();
}




/* If arg is TRUE, handle via AppWindow, else via AppIcon */
/* The first file is loaded, the rest are appended */
BOOL HandleAppEvents(struct MsgPort *msgport)
{	
	struct AppMessage * amsg;
	struct WBArg *argptr = NULL;
	int nReturn = 0,i;
	char szFilePath[MAXFILENAMELENGTH];
	
	while (amsg = (struct AppMessage *) GetMsg(msgport))
	{
		if (screenisopen == 0) 
		{
			if (SetupScreen() > 0) 
			{
				printf("GadMget: couldn't reopen screen!\n");
				CleanUp();
				exit(5);
			}
		}
		
		if (windowisopen == 0)
		{
			if (OpenmgetWindow() > 0)
			{
				printf("GadMget: Couldn't reopen window!\n");
				CleanUp();
				exit(5);
			}
		}

		
		/* process messages */
		if (amsg->am_NumArgs > 0L)
		{
			for (i=0;i<amsg->am_NumArgs;i++)
			{
				if (NameFromLock(amsg->am_ArgList[i].wa_Lock, szFilePath, sizeof(szFilePath)))
				{
					if (szFilePath[strlen(szFilePath)-1] != ':') strncat(szFilePath,"/", sizeof(szFilePath));
					strncat(szFilePath, amsg->am_ArgList[i].wa_Name, sizeof(szFilePath));
					if (i==0) OpenMgetFile(szFilePath);
					     else AppendMgetFile(szFilePath);
				}
			}
		}
		/* done with message, release it */
		ReplyMsg((struct Message *)amsg);
	}
	return(TRUE);
}










/********/
/* MAIN */
/********/
VOID main(int argc, char *argv[])
{
FILE *test = NULL;
ULONG winsig,signals;

GraphicsBase = OpenLibrary("graphics.library",37);
 if (GraphicsBase==NULL)
	{
	fprintf(fpOut,"couldn't open Graphics.library v37!");
	CleanUp();
	return;
	}
UtilityBase = OpenLibrary("utility.library",37);
 if (UtilityBase==NULL)
	{
	fprintf(fpOut,"couldn't open utility.library v37!");
	CleanUp();
	return;
	}
GadToolsBase = OpenLibrary("gadtools.library",37);
 if (GadToolsBase==NULL)
	{
	fprintf(fpOut,"couldn't open gadtools.library v37!\n");
	CleanUp();
	return;
	}
AslBase = OpenLibrary("asl.library", 37L);
 if (AslBase == NULL)
	{
	fprintf(fpOut,"couldn't open asl.library v37!\n");
	CleanUp();
	return;
	}
IntuitionBase = OpenLibrary("intuition.library",37);
 if (IntuitionBase == NULL)
 	{
 	fprintf(fpOut,"Couldn't open intuition.library!\n");
 	CleanUp();
 	return;
 	}
WorkbenchBase = OpenLibrary("workbench.library",37);
 if (WorkbenchBase == NULL)
 	{
 	fprintf(fpOut,"Couldn't open workbench.library!\n");
 	CleanUp();
 	return;
 	}
if (IconBase == NULL)
{
	IconBase = OpenLibrary("icon.library",33);
	/* If it's NULL, we'll disable the iconify function */
}


/* construct program name from version string */
memset(pnamestring,NUL,20);
strcpy(pnamestring,version+6);

memset(searchstring,NUL,sizeof(searchstring));

if (argc>1) ParseCliArgs(argc,argv);
 	
/* Now add data to listView */
/* First, initialize List filelist */
	
#ifdef MEMPOOLS_H
 if (!(filelist = (struct List *) malloc(sizeof(struct List))) )
#else
 if (!(filelist = AllocMem(sizeof(struct List),MEMF_CLEAR)) )
#endif
	{
	MakeReq("Couldn't create filelist!  Out of memory?",NULL,NULL);
	CleanUp();
	return();
	}
	
#ifdef MEMPOOLS_H
 if (!(getlist = (struct List *) malloc(sizeof(struct List))) )
#else
 if (!(getlist = AllocMem(sizeof(struct List),MEMF_CLEAR)) )
#endif
	{
	MakeReq("Couldn't create getlist!  Out of memory?",NULL,NULL);
	CleanUp();
	return();
	}
	
 NewList(filelist);
 NewList(getlist);
 
 if ((pcExecName == NULL)||(strlen(pcExecName) == 0)) pcExecName = DEFAULT_EXECNAME;
 
 lockscrnerror = SetupScreen();
 if (lockscrnerror)
 {
	if (BStartedFromWB == FALSE) printf("Couldn't open screen!\n",NULL,"Sigh");
	else
	MakeReq("Couldn't open screen!",NULL,NULL);
	
	CleanUp();
	return();
 }
	
 winopenerror = OpenmgetWindow();
 if (winopenerror)
 {
	MakeReq("Couldn't open window!",NULL,NULL);
	CleanUp();
	return();
 }
 
 if ((OpenMgetFile(inputfile) == TRUE)||(OpenMgetFile(NULL) == TRUE))
 {
	/* First, make sure all the menus are enabled. */
	TurnOnAllMenuItems(mgetMenus);
	
	SetMenuValues();

	if (noparse) SetWindowTitles(mgetWnd, "Please select desired lines now." , (char *) ~0); 
	   	else ChangeWindowTitle();
	
	while (done==FALSE)
	{
		winsig = 1L << mgetWnd->UserPort->mp_SigBit;
		signals = Wait(winsig|appwinsig);
		if (signals&winsig) handlereturn = HandlemgetIDCMP(NULL);
		if (signals&appwinsig) HandleAppEvents(awport);
	}
	if (windowisopen)  ClosemgetWindow();
	if (screenisopen)  CloseDownScreen();
	
	if (nCloseAction & ACTION_SAVE)   mgetsave();
	if (nCloseAction & ACTION_OUTPUT) mgetoutput();	
 }
 CleanUp();
		
 exit(0);	
}

#endif


	