/*
* parse routines for flist...
*
* uses arp functions.
*
*/

#include <libraries/arpbase.h>
#include <stdio.h>
#include "flist.h"

/* Global stuff for ARP */

char *CLI_Template = ",FROM/K";
char *CLI_Help = "Type filename(s) or FROM and a file with name of files";

/* global flist stuff */

struct AnchorPath *ap = NULL;

long (*finfo[MAXDIR])[4];  /* miscelaneous info -- file size,blocks,dir type etc... */
char (*fname[MAXDIR])[FCHARS];     /* file name and comment */
char (*comm[MAXDIR])[FCHARS];
char (*fstring[MAXDIR])[LEN_DATSTRING];
char (*ftime[MAXDIR])[LEN_DATSTRING];

struct FileLock *startdir = NULL, *lock = NULL, *olddir = NULL;

long numfiles,getcurrentdir();

long parse(argc,argv)
long argc;
char *argv[];
{
    long i,rc = -99;
    
    for (i=0;i<MAXDIR;i++)  /* zero out the memory arrays */
        fname[i] = 0;

    ap = (struct AnchorPath *)ArpAllocMem(sizeof(struct AnchorPath),FAST);

    if(ap == NULL)
        return OUT_OF_MEMORY;

    ap->ap_BreakBits = SIGBREAKB_CTRL_C;
    ap->ap_Length = 0;

    if((argv[1] != 0) && (argc > 0)){
        if(!getcurrentdir(argv[1]))
            return -98;
        strcat(argv[1],"*");
        rc = FindFirst(argv[1],ap);
        if(rc == NULL)
            rc = Fillarray();
    }
    else{ 
        if ((argc > 1) && (argv[2] != NULL))
            rc = other_input(argv[2]);
        else{
            if(argc == 0)  
                rc = Wbargs();   /* do we have Workbench? */
            else{
                if(!getcurrentdir(""))
                        return -98;
                rc = FindFirst("*",ap); /* user only typed 'flist' */
                if(rc == NULL)          /* so we are going to give him the */
                    rc = Fillarray();   /* current directory */
            }
        }
    }
    return rc;    /* return code should always be sent */
}

FreeFlistMem()
{
    if(ap != NULL )
        FreeAnchorChain(ap);
}

/* Stuff all the filenames and pertinent information into */
/* the flist arrays */

long Fillarray()
{
    long rc = NULL;
    struct DateTime dt;
    int i;

    numfiles = 0;

    dt.dat_Format = FORMAT_DOS;
    dt.dat_StrDay = NULL;
    dt.dat_Flags = DTB_SUBST;

    while(rc != ERROR_NO_MORE_ENTRIES){

        if(get_array_mem(numfiles) == OUT_OF_MEMORY)
                return OUT_OF_MEMORY;
                
        strcpy(fname[numfiles],&ap->ap_Info.fib_FileName);
        strcpy(comm[numfiles],&ap->ap_Info.fib_Comment); 
        dt.dat_Stamp = ap->ap_Info.fib_Date;
        dt.dat_StrDate = fstring[numfiles];
        dt.dat_StrTime = ftime[numfiles];

        (*finfo[numfiles])[0] = ap->ap_Info.fib_DirEntryType;
        (*finfo[numfiles])[1] = ap->ap_Info.fib_Protection;
        (*finfo[numfiles])[2] = ap->ap_Info.fib_Size;
        (*finfo[numfiles])[3] = ap->ap_Info.fib_NumBlocks;

        if((rc = StamptoStr(&dt)) != NULL)
                break;

        rc = FindNext(ap);

        if( ++numfiles > MAXDIR || rc != NULL)
            break;
    }

    for (i=numfiles;i<MAXDIR;i++)   /* free all array memory not being used */
        if (fname[i] != 0) {
            FreeMem(fname[i],FCHARS);
/*            FreeMem(comm[i],FCHARS); */
            FreeMem(finfo[i],16L);
            FreeMem(fstring[i],LEN_DATSTRING);
            FreeMem(ftime[i],LEN_DATSTRING);
            fname[i] = 0;
            finfo[i] = 0;
            fstring[i] = 0;
            ftime[i] = 0;
        }

    if(rc == ERROR_NO_MORE_ENTRIES)
        return NULL;
    return rc;
}

/* The user has not supplied any filenames or input for the File */
/* template. Here we check for the optional FROM keyword. */

long other_input(argv)
char *argv[];
{

    FILE *fp;
    char *buffer;
    struct DateTime dt;
    register long rc;
    int i;

    if ((buffer = (char *)ArpAllocMem(LINESIZE,FAST)) == NULL)
        return OUT_OF_MEMORY;

    if ((fp = fopen(argv,"r")) == NULL)
        return -99L;

    if (!getcurrentdir(""))
        return -98L;

    dt.dat_Format = FORMAT_USA;
    dt.dat_StrDay = NULL;
    dt.dat_Flags = DTB_SUBST;

    numfiles = 0;
    while (feof(fp) == NULL){

        if(get_array_mem(numfiles) == OUT_OF_MEMORY)
                return OUT_OF_MEMORY;
                
        fscanf(fp,"%s",buffer);
        rc = FindFirst(buffer,ap);
        if (rc != NULL )
            break;

        strcpy(fname[numfiles],buffer);
        strcpy(comm[numfiles],&ap->ap_Info.fib_Comment); 
        (*finfo[numfiles])[0] = ap->ap_Info.fib_DirEntryType;
        (*finfo[numfiles])[1] = ap->ap_Info.fib_Protection;
        (*finfo[numfiles])[2] = ap->ap_Info.fib_Size;
        (*finfo[numfiles])[3] = ap->ap_Info.fib_NumBlocks;
        dt.dat_Stamp = ap->ap_Info.fib_Date;
        dt.dat_StrDate = fstring[numfiles];
        dt.dat_StrTime = ftime[numfiles];

        if((rc = StamptoStr(&dt)) != NULL)
                break;

        if( ++numfiles > MAXDIR | rc != NULL)
            break;
        }

    if (feof(fp) == NULL){
        if (rc == NULL)
            rc = (LONG)ferror(fp);
    }
    else
        numfiles--;

    for (i=numfiles;i<MAXDIR;i++)   /* free all array memory not being used */
        if (fname[i] != 0) {
            FreeMem(fname[i],FCHARS);
/*            FreeMem(comm[i],FCHARS); */
            FreeMem(finfo[i],16L);
            FreeMem(fstring[i],LEN_DATSTRING);
            FreeMem(ftime[i],LEN_DATSTRING);
            fname[i] = 0;
            finfo[i] = 0;
            fstring[i] = 0;
            ftime[i] = 0;
        }
    fclose(fp);
    return rc;        
}

long get_array_mem(index)
long    index;
{

/* If the memory array already has a block allocated to it return to 
   caller... otherwise allocate one */

    if (fname[index] != 0L)
        return 0L;
    
    fname[index] =      (char *)AllocMem(FCHARS,FAST);
/*    comm[index]  =      (char *)AllocMem(FCHARS,FAST); */
    finfo[index] =      (LONG *)AllocMem(16L,FAST);
    fstring[index] =    (char *)AllocMem(LEN_DATSTRING,FAST);
    ftime[index] =      (char *)AllocMem(LEN_DATSTRING,FAST);

    if( ftime[index] == NULL | fstring[index] == NULL \
    | fname[index] == NULL | /* comm[index] == NULL | */ finfo[index] == NULL )
        return OUT_OF_MEMORY;
    else
        return 0L;
}

/*
** more Arp stuff for Workbench support
*/

BYTE dir[DSIZE], name[FCHARS];

getarp(mask,fib)
ULONG mask;
struct FileInfoBlock *fib;
{

    long rc;
    struct DateTime dt;

    dt.dat_Format = FORMAT_USA;
    dt.dat_StrDay = NULL;
    dt.dat_Flags = DTB_SUBST;

    strcpy(fname[numfiles],&fib->fib_FileName);
    strcpy(comm[numfiles],&fib->fib_Comment); 
    (*finfo[numfiles])[0] = fib->fib_DirEntryType;
    (*finfo[numfiles])[1] = fib->fib_Protection;
    (*finfo[numfiles])[2] = fib->fib_Size;
    (*finfo[numfiles])[3] = fib->fib_NumBlocks;
    dt.dat_Stamp = ap->ap_Info.fib_Date;
    dt.dat_StrDate = fstring[numfiles];
    dt.dat_StrTime = ftime[numfiles];

    if((rc = StamptoStr(&dt)) != NULL)
        return rc;

    numfiles++;

    return 0L;    /* tell Arp to put this entry in the requester */

/* ok, this is the fun part ... cheath told me that there
   is a bug in the handling of the return code. this is the fix. */
#asm
    move.l #0,d0      ; d0 MUST contain the return code 
    move.l d0,4(sp)   ; 4(sp) is the part that gets munged to the 
                      ; correct value 
#endasm
}

struct FileRequester arpfr = {
                                     /* Hailing text */
    (BYTE *)"Select a directory, then click on OK.", 
    NULL,                            /* string to put the final name */
    NULL,                            /* string to put the directory entry */
    NULL,                            /* Window for the files */
    NULL,                            /* what calls getarp? */
    NULL,                            /* reserved */
    NULL,                            /* function to be called */
    NULL                             /* reserved */
};

long Wbargs()   /* use the arp file requester to get the file names */
{
    long dummy;
    char dname[FCHARS];

    strcpy(dir,"RAM:");
    strcpy(dname,"Select directory only.");

    arpfr.fr_Dir = dir;
    arpfr.fr_File = dname;

    dummy = FileRequest(&arpfr);

    if(dummy == NULL)   /* user selects cancel -- so abort */
        return 1;

    olddir = lock;      /* save this for later */

    if(strcmp(dir,"") == 0)
        getcurrentdir("");
    else {
        lock = Lock(dir,ACCESS_READ);
        if(lock == NULL) {
            auto_req("Can't find requested directory.");
            return 1;
        }
    }

    if (startdir == NULL)
        startdir = CurrentDir(lock);
    else
        CurrentDir(lock);

    TackOn(dir,"*");
    dummy = FindFirst(dir,ap);

    if(dummy == NULL)
       dummy = Fillarray();

    return (dummy == NULL || dummy == ERROR_NO_MORE_ENTRIES) ? 0 : 1;
}

long getcurrentdir(str)
char *str;
{
    /* This is the only way I have ever been able to reliably get the
       current directory */
    
    /* Save the Value of the Directory we are in now. */

    if (str[0] == '\0'){
        struct Process *proc = FindTask(NULL);

        lock = DupLock(proc->pr_CurrentDir);
        startdir = CurrentDir(lock);
        return TRUE;
    } else {
        lock = Lock(str);
        startdir = CurrentDir(lock);
        return (startdir == 0) ? FALSE : TRUE;
    }
}
