/*-- Rev Header - do NOT edit!
 *
 *  Filename : Find.cc
 *  Purpose  : Find a file in a database
 *
 *  Program  : Find
 *  Author   : Gerhard Müller
 *  Copyright: (c) by Gerhard Müller
 *  Creation : Fri Oct  8 00:50:29 1993
 *
 *  compile  : makefile
 *
 *
 *  Compile version  : 0.1
 *  Ext. Version     : 0.1
 *
 *  REVISION HISTORY
 *
 *  Date       C-Version  E-Version    Comment
 *  ---------  ---------  -----------  -------
 *  12.9.93                            work started
 *
 *
 *
 *-- REV_END --
 */

	/*
	 * C-Includes, C-Definitionen
	 *
	 */

#define class _class
#define template _template

extern "C" {
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <inline/stubs.h>
#include <clib/dos_protos.h>
#ifdef __OPTIMIZE__
#include <inline/exec.h>
#include <inline/dos.h>
#include <inline/utility.h>
#else
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>
#endif

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

#undef template
#undef class


extern "C" {

/* dont mangle our global symbols */

Library			*UtilityBase;

extern ExecBase	*SysBase;

extern BPTR stdin;
extern BPTR stdout;
}


	/*
	 * C++-Includes, C++-Definitionen
	 *
	 */

#include "add/baserel/add.h"		// prototypes for all new C-functions
#include "add/baserel/couta.h"		// defines cout
#include "add/baserel/OwnError.h"	// defines err


	/*
	 * our function-prototypes
	 *
	 */

void	OutputError(void);
void	MyExit();
BOOL	MyInit(int alen, char *aptr);
int		main(int alen, char *aptr);
void	OutputError(void);


/* Version-String */

char *version = "\0$VER: Find 0.01 (" __DATE__ ")";



/* things for commandline-parsing */

#define TEMPLATE "STRING/A,EXACT/S"

typedef struct { char *string; long exact_match; } ARGS;
#define DEFAULT { NULL, NULL }

ARGS			args = DEFAULT;	/* here the arguments are stored */

struct RDArgs	*rda = NULL;	/* for CLI-startup */
UBYTE			**ToolTypes; 	/* for WB-startup */





	/*
	 * This function gets called by exit(), look im MyInit() for corresponding atexit() call
	 * frees all system-depended things
	 */


void MyExit()
{
		/* Free arguments passed by commandline allocated by ReadArgs() */

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


		/* close all our libraries */

	if(UtilityBase)
		CloseLibrary(UtilityBase);

}


	/*
	 * Open some libraries and make the commandline-parsing
	 *
	 */

BOOL MyInit(int alen, char *aptr)
{
	BOOL ok=FALSE;

	/* Are we running under control of Kickstart 2.0 or higher? */

	if(SysBase -> LibNode . lib_Version < 37)
	{
		err.NotifyError("needs Workbench & Kickstart Version 2.04 and above !\n");
		return FALSE;
	}


	atexit(MyExit);			// the function MyExit should be called at exit()-time


	/* open some libraries, not really needed in this programm, just to show how to do */

	if(UtilityBase = OpenLibrary((UBYTE *)"utility.library",37))
	{
		// we have all our libraries
			ok=TRUE;
	}

	if(!ok) return FALSE;


	/* normal startup-code.... */

	ok=FALSE;

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

		if(rda = (RDArgs *)AllocDosObject( DOS_RDARGS, NULL ))
		{
			rda->RDA_ExtHelp = (UBYTE *)"This could be an extended help - here you get nothing :-)\n";

			if(ReadArgs( (UBYTE *)TEMPLATE, (LONG *) &args, rda ) )
			{
				/* Args erfolgreich gelesen */

				ok=TRUE;
			}
			else
			{
				err.DosError(IoErr(), "Error parsing commandline");	/* prints the appropriate err message */
			}
		}
		else
			err.NotifyError("Out of memory error !");
	}
	else
	{
		/* Workbench-Start */

		err.NotifyError("Start only from CLI !");

		ok=FALSE;
	}

	return ok;
}



	/*
	 * Here the testprogram starts, uses some misc features
	 *
	 */


int main(int alen, char *aptr)
{
	if(MyInit(alen,aptr))		// all things went well
	{
		BPTR fh;

		if(fh=Open((STRPTR)"FindDB:find.codes",MODE_OLDFILE))
		{
			int file_len;

			if(file_len=GetFileSize(fh))
			{
				char *file_mem;

				if(file_mem=(char *)AllocVec(file_len+1,MEMF_ANY))
				{
					if(Read(fh,file_mem,file_len)==file_len)
					{
						// Now the file is in Memory

						// terminate with zero

						file_mem[file_len]=0;

						char *WBuf;

						if(WBuf=(char *)AllocVec(1024,MEMF_ANY))
						{
							// We have Memory for WildCard Matching

							char *Dir_String;
							char *Filename_String;

							if(args.exact_match)
							{
								// The easy way
							}
							else
							{
								if(!ParsePatternNoCase((STRPTR)args.string,(STRPTR)WBuf,1024))
									args.exact_match=TRUE;
							}


							// Now do the search

							char *s=file_mem;
							BOOL found=FALSE;
							BOOL stop=FALSE;

							// first search for directories

							cout << "\nDirectories\n-----------\n";

							while(s < file_mem+file_len && (!stop))
							{

								// remeber beginning

								Dir_String=s;


								// search for 0

								while(*s) s++;

								if( (s[-1]=='/') || (s[-1]==':'))
								{
									// We have a Directory

									// s[-1]=0;	/* kill '/' or ':' */

									if(args.exact_match)
									{
										// do pattern matchhing by Hand...

										if(Stricmp((STRPTR)args.string, (STRPTR)Dir_String)==0)
										{
											cout << Dir_String << endl;
											found=TRUE;
										}
									}
									else
									{
										if(MatchPatternNoCase((UBYTE *)WBuf,(UBYTE *)Dir_String))
										{
											cout << Dir_String << endl;
											found=TRUE;
										}
									}

									/* skip zero */
									s++;
								}
								else
								{
									/* skip zero */
									s++;
								}

								// if the user wants to abort the output, he can..

								if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) /* Hit since last check? */
								{
								 	SetSignal(0L,SIGBREAKF_CTRL_C);	/* Clear old status */
									cout << "\n*** BREAK\n" << endl;
									stop=TRUE;
								}
							}


							if(!stop)
							{

								if(!found)
									cout << "- No matches found -\n";


								// search for files

								cout << "\nFiles\n-----\n";

								found=FALSE;
								s=file_mem;
								char *temp;

								while(s < file_mem+file_len && (!stop))
								{

									// remeber beginning

									temp=s;


									// search for 0

									while(*s) s++;

									if( (s[-1]=='/') || (s[-1]==':'))
									{
										// We have a Directory

										Dir_String=temp;

										/* skip zero */
										s++;
									}
									else
									{
										// We have a file

										if(args.exact_match)
										{
											// do pattern matchhing by Hand...

											if(Stricmp((STRPTR)args.string, (STRPTR)temp)==0)
											{
												cout << Dir_String
													 << temp << endl;
												found=TRUE;
											}
										}
										else
										{
											if(MatchPatternNoCase((UBYTE *)WBuf,(UBYTE *)temp))
											{
												cout << Dir_String
													 << temp << endl;
												found=TRUE;
											}
										}

										/* skip zero */
										s++;
									}

									// if the user wants to abort the output, he can..

									if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) /* Hit since last check? */
									{
									 	SetSignal(0L,SIGBREAKF_CTRL_C);	/* Clear old status */
										cout << "\n*** BREAK\n" << endl;
										stop=TRUE;
									}
								}

								if( (!found) && (!stop) )
									cout << "- No matches found -\n";

								cout << endl << flush;
							}

							FreeVec(WBuf);
						}
						else
							err.NotifyError("Out of memory error!");
					}
					else
						err.NotifyError("Read error on FindDB:find.codes!");

					FreeVec(file_mem);
				}
				else
					err.NotifyError("Out of memory error!");
			}
			else
				err.NotifyError("File FindDB:find.codes is empty!");

			Close(fh);
		}
		else
			err.NotifyError("Can't access FindDB:find.codes!");

	}	// MyInit()


	// if an error occurred...

	OutputError();

	return(0);				// exit is called if we fall through
}




	/*
	 * Output error-message if we have one
	 *
	 */


void OutputError(void)
{
	if(err)
	{
		char *err_mem=0;
		char *es;
		LONG err_nr=err.SetErrorNumber(0);

		if(es=err.have_error_string())
		{
			cout <<	es << endl;
		}
		else
		{
			if(err_nr)
			{
				cout <<	"Error-Number: " << err_nr << endl;
			}
		}
	}
}
