/* Main-Header File inserted by GenCodeC */
/* Libraries */
#include <libraries/mui.h>
#include <libraries/gadtools.h> /* for BARLABEL in MenuItem */

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

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

/* Increase stack size */
LONG __stack=8192;
/* GenCodeC header end */

/* Include generated by GenCodeC */
#include "FinderV3GUI.c"

/* Misc Includes */

/* Declarations for libraries (inserted by GenCodeC) */
struct Library * IntuitionBase;
struct Library * MUIMasterBase;

struct Library ASLBase;

/* Global declarations */

BOOL debug = FALSE;

LONG active;
struct ObjApp * App = NULL;	/* Object */
char *drawer_str, *pattern_str, search_str[256];
#define MAXFILELEN 256
char *finished = "\033bOperation successful";
char search_banner[256], num_banner[256];
int files_found = 0;

/* Search options */
BOOL *recurse_bool = FALSE, *case_bool = FALSE;

/* ASL declarations */
struct TagItem frtags[] = 
   {
   ASL_Hail,      (ULONG)"Choose file to save list to...",
   ASL_Height,    400,
   ASL_Width,     320,
   ASL_LeftEdge,  0,
   ASL_TopEdge,   0,
   ASL_OKText,    (ULONG)"Ok",
   ASL_CancelText,(ULONG)"Cancel",
   ASL_File,      (ULONG)"Finder.list",
   ASL_Dir,       (ULONG)"RAM:",
   TAG_DONE
   };

/* Function prototypes */
void GUIFind(void);
BOOL SearchDir(char *directory, char *pattern);
void Save_List(void);

/* Init() function */
void init( void )
{
	if (!(IntuitionBase = OpenLibrary("intuition.library",37)))
	{
		printf("Can't Open Intuition Library\n");
		exit(20);
	}
	if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)))
	{
		printf("Can't Open MUIMaster Library\n");
		CloseLibrary(IntuitionBase);
		exit(20);
	}
}
/* GenCodeC init() end */

/* End() function */
void end( void )
{
	CloseLibrary(MUIMasterBase);
	CloseLibrary(IntuitionBase);
	exit(0);
}
/* GenCodeC end() end */

/*
** App message callback hook. Note that the object given here
** is the object that called the hook, i.e. the one that got
** the icon(s) dropped on it.
*/

SAVEDS ASM LONG AppMsgFunc(REG(a2) APTR obj, REG(a1) struct AppMessage **x)
{
struct WBArg *ap;
struct AppMessage *amsg = *x;
int i;
static char buf[256];
char *b = buf;

for ( ap = amsg->am_ArgList, i = 0 ; i < amsg->am_NumArgs ; i++, ap++ )
   {

   NameFromLock(ap->wa_Lock, buf, sizeof(buf));
   AddPart(buf, ap->wa_Name, sizeof(buf));

   /* We need to strip away down to the trailing / if this is a file */
   do {
      if (buf[strlen(buf) - 1] != '/')
         {
         buf[strlen(buf) - 1] = '\0';
         }
      } while (buf[strlen(buf) - 1] != '/');

   }

set(App->STR_DrawerPopup, MUIA_String_Contents, b);

return(0);
}

/* Main Function inserted by GenCodeC */
int main(int argc, char *argv[])
{

	BOOL	running = TRUE;
	ULONG	signal;
   static const struct Hook AppMsgHook = { { NULL,NULL },(VOID *)AppMsgFunc,NULL,NULL };

	/* Program initialisation : generated by GenCodeC */
	init();

	/* Create Object : generated by GenCodeC */
	if (!(App = CreateApp()))
	{
		printf("Can't Create App\n");
		end();
	}

   /* App hook stuff */
   DoMethod(App->STR_DrawerPopup, MUIM_Notify, MUIA_AppMessage, MUIV_EveryTime,
      App->STR_DrawerPopup, 3, MUIM_CallHook, &AppMsgHook, MUIV_TriggerValue);

   set(App->App, MUIA_Application_DropObject, App->STR_DrawerPopup);

	while (running)
	{
		switch (DoMethod(App->App, MUIM_Application_Input, &signal))
		{
			case MUIV_Application_ReturnID_Quit:
            get(App->DrawerPopup, MUIA_Popasl_Active, &active);
            if (active)
               MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Please close the ASL File Requester\nbefore exiting");
            else
   				running = FALSE;
		   break;

			/* Insert your code between the "case" statement and comment "end of case ..." */

         case FindPressed:
            GUIFind();
         break;
         /* end of case Find */

			case SaveList:
            Save_List();
         break;
			/* end of case SaveList */

			case PrintList:
            MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Sorry, this feature has not been implemented yet");
         break;
			/* end of case PrintList */

			/* End computing of IDCMP */

			default:
   		break;
		}
		if (running && signal) Wait(signal);
	}
	DisposeApp(App);
	end();
}

/*
** void GUIFind()
**
** This function sorts out actually finding (wow!)
**
*/
void GUIFind()
{

char *ptr = search_banner;
char *num_ptr = num_banner;

/* Error buffer */
LONG error_buf;

/* Clear the current list*/
DoMethod(App->FileList, MUIM_List_Clear);
files_found = 0;

/* Put the application to sleep while we find */
set(App->MainWin, MUIA_Window_Sleep, TRUE);

/* Get the contents of the MUI string objects and search options*/
get(App->STR_DrawerPopup, MUIA_String_Contents, &drawer_str);
get(App->PatternStr, MUIA_String_Contents, &pattern_str);
get(App->casecheck, MUIA_Selected, &case_bool);
get(App->recursecheck, MUIA_Selected, &recurse_bool);

if (debug)
   {
   if (case_bool != FALSE)
      printf("Case sensetive\n");

   if (recurse_bool)
      printf("Recursive\n");

   printf("Debug1: Dir: %s, Pattern %s\n", drawer_str, pattern_str);
   }

if (strlen(drawer_str) == 0 || strlen(pattern_str) == 0)
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: You \033bmust\033n supply a drawer and a pattern");

   set(App->MainWin, MUIA_Window_Sleep, FALSE);

   return;
   }

/* Prepare our search */
if (case_bool)
   error_buf = ParsePattern(pattern_str, search_str, MAXFILELEN);
else
   error_buf = ParsePatternNoCase(pattern_str, search_str, MAXFILELEN);

   if (error_buf == -1)
      {
      /* The Parse has failed */
      MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: A serious internal error has occured,\npossibly a buffer overflow");
      set(App->MainWin, MUIA_Window_Sleep, FALSE);
      return;
      }

/* Put up a banner saying what we are doing */
sprintf(search_banner, "\033bFiles matching '%s' in '%s'", pattern_str, drawer_str);

/*DoMethod(App->FileList, MUIM_List_Insert, &ptr, 1, MUIV_List_Insert_Bottom);*/
set(App->FileList, MUIA_List_Title, ptr);

/* Call the searcher function */
if (!(SearchDir(drawer_str, search_str)))
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Search failed.");
   set(App->MainWin, MUIA_Window_Sleep, FALSE);

   return;
   }

/* Put up the file counter */
sprintf(num_banner, "-- %i files found", files_found);
DoMethod(App->FileList, MUIM_List_Insert, &num_ptr, 1, MUIV_List_Insert_Bottom);

/* Search has finished, put up the completion banner */
DoMethod(App->FileList, MUIM_List_Insert, &finished, 1, MUIV_List_Insert_Bottom);
set(App->FileList, MUIA_List_Active, MUIV_List_Active_Bottom);

/* Unbusy the window */
set(App->MainWin, MUIA_Window_Sleep, FALSE);

return;

}

/*
** BOOL SearchDir(char *directory, char *pattern)
**
** This is the function which actually accesses the disk to find the files
**  and compares their names with the pattern supplied.
**
*/
BOOL SearchDir(char *directory, char *pattern)
{

__aligned struct FileInfoBlock   fib;

BPTR lk = NULL;
char full_path[255];

char *fpath = full_path;

/* Lock initial directory and store the FileInfoBlock */
if (!(lk = Lock(directory, ACCESS_READ)))
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to lock directory");
   if (lk) UnLock(lk);
   return FALSE;
   }
if (!(Examine(lk, &fib)))
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to access FileInfoBlock");
   if (lk) UnLock(lk);
   return FALSE;
   }

/* Scan directory */
while (ExNext(lk, &fib))
   {
   if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
      {
      MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Ctrl-C received, stopping search");
      UnLock(lk);
      return FALSE;
      }

   /* Build the full path with our ExNext file */
   strcpy(full_path, directory);
   AddPart(full_path, fib.fib_FileName, 255);

   /* Identify this file (is it a directory?) */
   if (fib.fib_DirEntryType > 0)
      {
      /* We have a directory, recursively scan it (if we want to)  */
      if (recurse_bool)
         {
         if (!(SearchDir(full_path, pattern)))
            {
            UnLock(lk);
            return FALSE;
            }
         }
      }
   else
      {
      /* We have a file, match it with our pattern */
      if (!case_bool)
         {
         if (MatchPatternNoCase(pattern, fib.fib_FileName))
            {
            if (debug) printf("We have a match on file '%s'\n", fib.fib_FileName);
            DoMethod(App->FileList, MUIM_List_Insert, &fpath, 1, MUIV_List_Insert_Bottom);
            set(App->FileList, MUIA_List_Active, MUIV_List_Active_Bottom);
            files_found++;
            }
         }
      if (case_bool)
         {
         if (MatchPattern(pattern, fib.fib_FileName))
            {
            if (debug) printf("We have a match on file '%s'\n", fib.fib_FileName);
            DoMethod(App->FileList, MUIM_List_Insert, &fpath, 1, MUIV_List_Insert_Bottom);
            set(App->FileList, MUIA_List_Active, MUIV_List_Active_Bottom);
            files_found++;
            }
         }
      }
   }

   UnLock(lk);

return TRUE;

}

/*
** void Save_List(void)
**
** This function will save the list to a file specified by the user
**
*/
void Save_List( void )
{

/* Variable definitions for the list saving loop */
int i;
FILE *fp = NULL;
LONG result;
char fr_drawer[256];

struct FileRequester *fr;

/* Make sure we actually have a list to save */
if (!drawer_str)
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: There is no list to save");

   return;
   }

/* Let the user choose a file */

if (!(fr = (struct FileRequester *)MUI_AllocAslRequest(ASL_FileRequest, frtags)))
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to allocate the ASL requester");
   if (fr) MUI_FreeAslRequest(fr);

   return;
   }

if (!(MUI_AslRequest(fr, NULL)))
   {
   MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: User cancelled\n\033cList saving aborted");
   if (fr) MUI_FreeAslRequest(fr);

   return;
   }

/* Copy the tags to a AddPart type storage thingy */
strcpy(fr_drawer, fr->rf_Dir);
AddPart(fr_drawer, fr->rf_File, 255);

MUI_FreeAslRequest(fr);

/* Kludge zone!! (almost) */
/* We need to know if the file exists so we know whether or not to pop up an append/overwrite requester */
/* This is done by trying to open the file we want with read flags */
/*  If the file exists, this will fill the FILE pointer */
/*  we can test for this. If the pointer is not NULL, the file exists and we pop up our requester */
/*  Simple! */

if (!(fp = fopen("RAM:Finder.list", "r")))
   {
      /* The open has failed, therefore, the file doesn't exist and we can just get on and write to it */
      /* Now open the file new for writing */
      if (fp) fclose(fp); /* Close the FILE pointer, just in case */

      if (!(fp = fopen("RAM:Finder.list", "w")))
         {
            MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to open the file");
            if (fp) fclose(fp);
            return;
         }

      /* Loop to read the list contents into the file */
      /* First, put the window to sleep */
      set(App->MainWin, MUIA_Window_Sleep, TRUE);

      fprintf(fp, "Search results for drawer '%s' with pattern '%s'\n", drawer_str, pattern_str);

      for ( i = 0 ;; i++ )
         {
            char *name;

            DoMethod(App->FileList, MUIM_List_GetEntry, i , &name);
            if (!name)
               break;

            fprintf(fp, "%s\n", name);
         }

      fclose(fp);
      set(App->MainWin, MUIA_Window_Sleep, FALSE);

      return;

   }
else
   {
      fclose(fp);
      /* The file exists, we now need to decide if we want to overwrite, or append it */

      /* Append/Overwrite requester - return values:              2        1        0 */
      result = MUI_Request(App->App, App->MainWin, 0, NULL, "_Append|_Overwrite|_Cancel", "The file already exists, please choose an operation");

      if (result == 2)
         {
            /* The user wants to overwrite the file */

            /* Open the file for overwriting */
            if (!(fp = fopen("RAM:Finder.list", "w")))
               {
                  MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to open the file");
                  if (fp) fclose(fp);

                  return;
               }

            /* List loop */
            set(App->MainWin, MUIA_Window_Sleep, TRUE);

            fprintf(fp, "Search results for drawer '%s' with pattern '%s'\n", drawer_str, pattern_str);

            for ( i = 0 ;; i++ )
               {
                  char *name;

                  DoMethod(App->FileList, MUIM_List_GetEntry, i , &name);
                  if (!name)
                     break;

                  fprintf(fp, "%s\n", name);
               }

            fclose(fp);
            set(App->MainWin, MUIA_Window_Sleep, FALSE);

            return;

         }
   if (result == 1)
         {
            /* The user wants to append the file */

            /* Open the file for appending */
            if (!(fp = fopen("RAM:Finder.list", "a")))
               {
                  MUI_Request(App->App, App->MainWin, 0, NULL,"Ok","Error: Unable to open the file");
                  if (fp) fclose(fp);

                  return;
               }

            /* List loop */
            set(App->MainWin, MUIA_Window_Sleep, TRUE);

            fprintf(fp, "\nSearch results for drawer '%s' with pattern '%s'\n", drawer_str, pattern_str);

            for ( i = 0 ;; i++ )
               {
                  char *name;

                  DoMethod(App->FileList, MUIM_List_GetEntry, i , &name);
                  if (!name)
                     break;

                  fprintf(fp, "%s\n", name);
               }

            fclose(fp);
            set(App->MainWin, MUIA_Window_Sleep, FALSE);

            return;
            }

         }

return;

}