#include <exec/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <dos.h>

#include <link/io.h>

#include <proto/dlg.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <pragmas/dlg.h>

#include <dlg/msg.h>
#include <dlg/file.h>
#include <dlg/misc.h>
#include <dlg/dlg.h>

#include <DLG/Version.h>

#include <private/Version.h>
#define  ObjRev "1"
const UBYTE version[]="\0$VER: FileGuide " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;


BPTR  sout;
BPTR  fh    =  NULL;
BPTR  of    =  NULL;

struct   Library    *DLGBase  =  NULL;
struct   Msg_Area   *farea    =  NULL;
struct   QuickFile  *qf       =  NULL;


///struct   LangStruct *ls;
//char               **SA;

char wheel[5] = "\|/- ";
char wheelpos;

void  ShutDown(int, char *);
void  Usage(void);
void  startwheel(void);
void  turn(void);
void  stopwheel(void);
void _CXBRK(void);
BOOL  CheckForNewFiles(long,ULONG,ULONG);
BOOL  CheckForSize(long, ULONG, BOOL);
BOOL  CheckForPat(long, char *, BOOL);

/// Main
void main(int argc, char **argv)
{
   BOOL  Odd   =  TRUE;
   BOOL  Quiet =  FALSE;
   BOOL  ShowAll = FALSE;
   BOOL  Magic = FALSE;
   BOOL  ShowMagic = TRUE;
   BOOL  LongYes = FALSE;
   BOOL  Bigger = FALSE;

   char *GuideFile    =  NULL;
   char *IntroFile   =  NULL;
   char *Bar;
   char  t[512];
   char  temp[512];
   char *FPat = NULL;
   char *DPat = NULL;
   char *Range = NULL;
   char  Addr[256];

   int   LongLines = 0;
   int   Width = 75;

   long  Level = 0;
   long  NumAreas = 0;
   long  i;
   long  j = 0;
   long  Days = 0;

   ULONG size = 0;
   ULONG DaySecs = 0;
   ULONG CurSecs = 0;
   ULONG SetSize = 0;
   struct fido *FidoNet = NULL;


   sout = Output();

   DLGBase = OpenLibrary("dlg.library",4L);

   if(!DLGBase)   ShutDown(10,"Could not open dlg.library!");

   //   SA = getlang(NULL);
   //   if(!SA)        ShutDown(10,"Could not read language file!");

   AFPrintf(NULL,sout,"\n\n%s\n\n",DLGLONGNAME);

   if (argc < 2)  Usage();

/// Parse args
   while(--argc > 0)
   {
      char *s;

      s = *++argv;

      if (*s++ == '-')
      {
         while(*s)
         {
            switch(*s++)
            {
               case 'o':
               case 'O':
               if (!--argc)  break;
               GuideFile = *++argv;
               break;

               case 'i':
               case 'I':
               if (!--argc)  break;
               IntroFile = *++argv;
               break;

               case 'q':
               case 'Q':
               Quiet = TRUE;
               break;

               case 'e':
               case 'E':
               ShowAll = TRUE;
               break;

               case 'm':
               case 'M':
               ShowMagic = FALSE;
               break;

               case 'l':
               case 'L':
               if (!--argc)  break;
               Level = atol(*++argv);
               break;

               case 'd':
               case 'D':
               if (!--argc)  break;
               Days = atol(*++argv);
               break;

               case 'f':
               case 'F':
               if (!--argc)  break;
               FPat = *++argv;
               break;

               case 'p':
               case 'P':
               if (!--argc)  break;
               DPat = *++argv;
               break;

               case 'a':
               case 'A':
               if (!--argc)  break;
               Range = *++argv;
               break;

               case 'v':
               case 'V':
                  if (!--argc)  break;
                  LongLines = atoi(*++argv);
                  LongYes = TRUE;
                  break;

               case 'w':
               case 'W':
                  if (!--argc)  break;
                  Width = atoi(*++argv);
                  break;

               case '>':
                  if (!--argc)  break;
                  SetSize = atol(*++argv);
                  Bigger = TRUE;
                  break;

               case '<':
                  if (!--argc)  break;
                  SetSize = atol(*++argv);
                  Bigger = FALSE;
                  break;

               default:
                  Usage();
                  break;
            }
         }
      }
   }

   if(!GuideFile) Usage();
   if((Level < 0) || (Level > 255)) Usage();
   if((Width < 40) || (Width > 132)) Usage();
//-

/// Load FidoNet settings
   FidoNet = calloc(1,sizeof(struct fido));

   if(FidoNet)
   {
      if(-1 == GetFirstStruct("DLGConfig:POrt/fidonet.settings",(char *)FidoNet,sizeof(struct fido)))
         ShutDown(10,"Fidonet settings are not available!");

      ASPrintf(NULL,Addr,"%d.%d.%d.%d",FidoNet->zone,FidoNet->net,FidoNet->node,FidoNet->point);
      free(FidoNet);
   }
   else
      ShutDown(10,"Memory allocation error!");
//-

/// Set up bar divider
   Bar = calloc(Width+1,sizeof(char));

   if(!Bar) ShutDown(10,"Memory allocation error!");

   for(i=0; i < Width; i++)
      Bar[i] = '=';
//-

/// Start file creation
   if(Exists(GuideFile)) DeleteFile(GuideFile);

   of = Open(GuideFile,MODE_READWRITE);

   if(!of) ShutDown(10,"Could not create output file");
   AFPrintf(NULL,of,"@DataBase \"%s File List\"\n",DLGSHORTNAME);
   AFPrintf(NULL,of,"@Node Main \"%s File Listing\"\n",DLGSHORTNAME);

   if(IntroFile)
   {
      fh = Open(IntroFile,MODE_OLDFILE);

      if(!fh)
      {
         Close(of);
         of = NULL;
         ShutDown(10,"Could not create output file");
      }

      while(FGets(fh,t,512))
         AFPrintf(NULL,of,"%s",t);

      Close(fh);
      fh = NULL;
      AFPrintf(NULL,of,"\n\n");
   }


   MDate(t);
   ASPrintf(NULL,temp,"File List Created on %s",t);
   AFPrintf(NULL,of,"%s\n%-*s%s\n",Bar,(Width-strlen(temp))/2," ",temp);
   ASPrintf(NULL,temp,"by %s",DLGSHORTNAME);
   AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(temp))/2," ",temp,Bar);
//-

/// Magic File Names
   if(ShowMagic)
   {
      if(Exists("DLGConfig:Misc/DLGFreq.cfg"))
      {
         fh = Open("DLGConfig:Misc/DLGFreq.cfg", MODE_OLDFILE);

         if (fh != NULL)
         {
            char TEMPS[512];

///         Looping ...
            while (FGets(fh, TEMPS, 512))
            {
               char               *par[20];
               char               *d;

               StripSpaces(TEMPS);

               if (strlen(TEMPS) <= 1)
                  continue;

               if (!Strnicmp(TEMPS, ";", 1))
                  continue;

               d = strdup(TEMPS);

               ArgParse(TEMPS, par, 19);

///            MAGIC
               if (!Stricmp(par[0], "MAGIC"))
               {
                  ASPrintf(NULL,t,"** M A G I C   F I L E   N A M E S **");
                  AFPrintf(NULL,of,"\n%-*s@{\" %s \" Link \"Magic\"}\n\n\n",((Width-strlen(t))/2)-2," ",t);
                  Magic = TRUE;
                  break;
               }
//-

            }
//-

            Close(fh);
            fh = NULL;
         }
      }
   }
//-

/// Open file area index and read it in
   if(FileSize("File:Area.BBS",&size) == -1)
      ShutDown(10,"No areas defined");

   if(size == 0)
      ShutDown(10,"No areas defined");

   NumAreas = size/sizeof(struct Msg_Area);

   if(!Quiet) AFPrintf(NULL,sout,"%ld file areas to read.\n",NumAreas);

   farea = calloc(1,size);

   if(!farea)
      ShutDown(10,"Memory allocation error!");

   if(-1 == GetFirstStruct("File:Area.bbs",(char *)farea,size))
      ShutDown(11,"Could not read FILE:Area.BBS");
//-

/// Banner for new file list (days)
   if(Days)
   {
      AFPrintf(NULL,of,"\n%s\n",Bar);
      ASPrintf(NULL,t,"New files uploaded in the last %ld days",Days);
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);
      DaySecs = Days * 24 * 60 * 60;
      CurSecs = AmigaTime();
   }
//-

/// Banner for size matching
   if(SetSize)
   {
      AFPrintf(NULL,of,"\n%s\n",Bar);
      ASPrintf(NULL,t,"Files %s than %ld bytes",Bigger?"Larger":"Smaller",SetSize);
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);
   }
//-

/// Banner for file pattern matching
   if(FPat)
   {
      AFPrintf(NULL,of,"\n%s\n",Bar);
      ASPrintf(NULL,t,"Files with filenames matching pattern [ %s ]",FPat);
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);
   }
//-

/// Banner for file/desc pattern matching
   if(DPat)
   {
      AFPrintf(NULL,of,"\n%s\n",Bar);
      ASPrintf(NULL,t,"Files with filenames or descriptions matching pattern [ %s ]",DPat);
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);
   }
//-

   if(!Quiet) AFPrintf(NULL,sout,"PASS 1 .... \n\n");

/// Cycle through file areas looking for valid areas
   for(i = 0; i < NumAreas; i++)
   {
      char t[512];
      ULONG qsize = 0;

      chkabort();

      if(!Quiet)
         AFPrintf(NULL,sout,"File area %ld: %s ... ",farea[i].Number,farea[i].Name);

///   Skip areas not in range
      if(Range)
      {
         if(!CheckRange(farea[i].Number,Range,999999))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"Not in specified range, skipping\n");
            farea[i].Number = 0;
            continue;
         }
      }
//-

///   Skip areas not freqable
      if(!ShowAll)
      {
         if(!(farea[i].Flag & FREQ_AREA))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"Not freqable, skipping\n");
            farea[i].Number = 0;
            continue;
         }
      }
//-

///   Skip non auto-access areas except for sysop
      if((Level) && !(farea[i].Flag & AUTO_ACCESS_AREA))
      {
         if(Level != 255)
         {
            if(!Quiet)
            AFPrintf(NULL,sout,"No auto-access, skipping\n");
            farea[i].Number = 0;
            continue;
         }
      }
//-

///   Skip areas out of level boundaries
      if(Level)
      {
         if((farea[i].llevel > Level) || (farea[i].ulevel < Level))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"Level out of bounds, skipping\n");
            farea[i].Number = 0;
            continue;
         }
      }
//-

///   Skip areas with no new files if we are making new file list
      if(Days)
      {
         if(!CheckForNewFiles(farea[i].Number,DaySecs,CurSecs))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"No new files, skipping\n");
            farea[i].Number = 0;
            continue;
         }

      }
//-

///   Skip areas with no appropriate files if we're only listing by size
      if(SetSize)
      {
         if(!CheckForSize(farea[i].Number,SetSize,Bigger))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"No files matching size parameters, skipping\n");
            farea[i].Number = 0;
            continue;
         }

      }
//-

///   Skip areas with no appropriate file pattern
      if(FPat)
      {
         if(!CheckForPat(farea[i].Number,FPat,FALSE))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"No files matching filename pattern, skipping\n");
            farea[i].Number = 0;
            continue;
         }
      }
//-

///   Skip areas with no appropriate file/desc pattern
      if(DPat)
      {
         if(!CheckForPat(farea[i].Number,DPat,TRUE))
         {
            if(!Quiet)
               AFPrintf(NULL,sout,"No files matching filename or description pattern, skipping\n");
            farea[i].Number = 0;
            continue;
         }

      }
//-

      ASPrintf(NULL,t,"FILE:%ld/file.dat",farea[i].Number);

///   Skip if no file.dat or if 0 files are present
      if(FileSize(t,&qsize) == -1)
      {
         if(!Quiet) AFPrintf(NULL,sout,"No files\n");
         farea[i].Number = 0;
         continue;
      }

      if(qsize < sizeof(struct QuickFile))
      {
         if(!Quiet) AFPrintf(NULL,sout,"No files\n");
         farea[i].Number = 0;
         continue;
      }
//-

      if(Odd)
      {
         AFPrintf(NULL,of,"@{\"%-*.*s\" Link \"Area%ld\"}  ",(Width/2)-2,(Width/2)-2,farea[i].Name,farea[i].Number);
         Odd = FALSE;
      }
      else
      {
         AFPrintf(NULL,of,"@{\"%-*.*s\" Link \"Area%ld\"}\n",(Width/2)-2,(Width/2)-2,farea[i].Name,farea[i].Number);
         Odd = TRUE;
      }

      if(!Quiet) AFPrintf(NULL,sout,"\n");
   }
//-

if(Odd)
   AFPrintf(NULL,of,"%s\n@EndNode\n",Bar);
else
   AFPrintf(NULL,of,"\n%s\n@EndNode\n",Bar);

/// Magic File Names
   if(ShowMagic && Magic)
   {
      AFPrintf(NULL,of,"@Node \"Magic\" \"Magic File Names\"\n");
      ASPrintf(NULL,t,"** M A G I C   F I L E   N A M E S **");
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);
      AFPrintf(NULL,of,"MAGIC FILE NAME    DESCRIPTION\n%s\n",Bar);

      fh = Open("DLGConfig:Misc/DLGFreq.cfg", MODE_OLDFILE);

      if (fh != NULL)
      {
         char TEMPS[512];

///   Looping ...
         while (FGets(fh, TEMPS, 512))
         {
            char               *par[20];
            char               *d;

            StripSpaces(TEMPS);

            if (strlen(TEMPS) <= 1)
               continue;

            if (!Strnicmp(TEMPS, ";", 1))
               continue;

            d = strdup(TEMPS);

            ArgParse(TEMPS, par, 19);

///      MAGIC
            if (!Stricmp(par[0], "MAGIC"))
            {
               char  *Desc = NULL;

               Desc = strdup(d);

               if (strchr(Desc, ';'))
               {
                  Desc = strtok(d, ";");
                  Desc = strdup(strtok(NULL, "\n"));
               }
               else
               {
                  *Desc = NULL;
               }

               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"} %-*.*s\n",par[1],Addr,par[1],Width-20,Width-20,Desc);
            }
//-

         }
//-

         Close(fh);
         fh = NULL;

         AFPrintf(NULL,of,"%s\n@EndNode\n",Bar);
      }
   }
//-

   if(!Quiet) AFPrintf(NULL,sout,"\n\nPASS 2 .... \n\n");

/// Cycle through file areas and generate AmigaGuide nodes
   for(i = 0; i < NumAreas; i++)
   {
      char t[512];
      long NumFiles = 0;
      ULONG qsize = 0;

      chkabort();

      //    Skip previously nixed on pass 1
      if(farea[i].Number == 0) continue;

      if(!Quiet)
         AFPrintf(NULL,sout,"File area %ld: %s ... ",farea[i].Number,farea[i].Name);

      AFPrintf(NULL,of,"@Node \"Area%ld\" \"File Area %ld -- %s\"\n",farea[i].Number,farea[i].Number,farea[i].Name);
      ASPrintf(NULL,t,"File Area %ld -- %s",farea[i].Number,farea[i].Name);
      AFPrintf(NULL,of,"%-*s%s\n%s\n",(Width-strlen(t))/2," ",t,Bar);

      AFPrintf(NULL,of,"FILE NAME           SIZE  DESCRIPTION\n%s\n",Bar);

///   Load file.dat
      ASPrintf(NULL,t,"FILE:%ld/file.dat",farea[i].Number);

      FileSize(t,&qsize);
      qf = calloc(1,qsize);

      if(!qf)
      {
         AFPrintf(NULL,of,"Could not read file database\n%s\n@EndNode\n",Bar);
         AFPrintf(NULL,sout,"Could not read file database %s\n",t);
         continue;
      }

      if(-1 == GetFirstStruct(t,(char *)qf,qsize))
      {
         AFPrintf(NULL,of,"Could not read file database\n%s\n@EndNode\n",Bar);
         AFPrintf(NULL,sout,"Could not read file database %s\n",t);
         continue;
      }

      NumFiles = qsize / sizeof(struct QuickFile);

      if(!Quiet)
         AFPrintf(NULL,sout,"%ld files to list ... ",NumFiles);
//-

      if(!Quiet) startwheel();

///   Go through file.dat and generate list of files in area
      for(j = 0; j < NumFiles; j++)
      {
         BOOL NTooLong = FALSE;
         BOOL DTooLong = FALSE;
         char *Desc;
         long tsize;
         long z;
         struct File_Header hdr;

         chkabort();

         if(!Quiet) turn();

///      Skip files not new
         if(CurSecs)
         {
            if( (CurSecs - qf[j].date) > DaySecs) continue;
         }
//-

///      Skip files too big or too small
         if(SetSize)
         {
            if(Bigger)
            {
               if(qf[j].size < SetSize) continue;
            }
            else
            {
               if(qf[j].size > SetSize) continue;
            }
         }
//-

///      File pattern matching
         if(FPat)
         {
            if(!DLGPatternMatch(FPat,qf[j].filename)) continue;
         }
//-

///      File/Desc pattern matching
         if(DPat)
         {
            if(!DLGPatternMatch(DPat,qf[j].filename) &&
               !DLGPatternMatch(DPat,qf[j].desc)) continue;
         }
//-

         for(z = 0; z < 60; z++)
         {
            if((qf[j].desc)[z] == 1) (qf[j].desc)[z] = 0;
            if((qf[j].desc)[z] == '\r') (qf[j].desc)[z] = ' ';
            if((qf[j].desc)[z] == '\n') (qf[j].desc)[z] = ' ';
         }

         StripSpaces(qf[j].desc);

         if(strlen(qf[j].desc) <= 1) strcpy(qf[j].desc,"** No Description Available **");

         Desc = strdup(strtok(qf[j].desc,"\r\n\0"));

         if(strlen(qf[j].filename) > 18) NTooLong = TRUE;
         if((strlen(Desc) + 29) > Width) DTooLong = TRUE;

///      Print description
         if(!LongYes)
         {
            if(qf[j].size < 10000)
            {
               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ld  %-*.*s%s\n",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",qf[j].size,Width-29,Width-29,Desc,DTooLong?"...":"");
               continue;
            }

            if((qf[j].size > 10000) && (qf[j].size < 1000000))
            {
               tsize = qf[j].size / 1000;

               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ldK %-*.*s%s\n",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",tsize,Width-29,Width-29,Desc,DTooLong?"...":"");
               continue;
            }

            if(qf[j].size > 1000000)
            {
               tsize = qf[j].size / 1000000;

               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ldM %-*.*s%s\n",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",tsize,Width-29,Width-29,Desc,DTooLong?"...":"");
               continue;
            }
         }
         else
         {
            char    *LDesc = NULL;
            char    *p;
            long     cnt;
            long     Len = 0;
            ULONG    FSize = 0;
            ULONG    DSize = 0;

            ASPrintf(NULL,t,"FILE:%ld/%ld.FD",farea[i].Number,qf[j].number);

            if(-1 == FileSize(t,&FSize)) continue;

            DSize = FSize - sizeof(struct File_Header);

            if(DSize == 0)
            {
               AFPrintf(NULL,of," *** No File Description ***\n");
               continue;
            }

            LDesc = calloc(1,DSize);

            if(!LDesc)
            {
               AFPrintf(NULL,of," *** Could not load description!!! ***\n");
               continue;
            }

            fh = Open(t,MODE_OLDFILE);

            if(!fh)
            {
               AFPrintf(NULL,of," *** Could not read description!!! ***\n");
               free(LDesc);
               LDesc = NULL;
               continue;
            }

            Read(fh,&hdr,sizeof(struct File_Header));
            cnt = Read(fh,LDesc,DSize);
            LDesc[cnt-1] = 0;

            for(cnt = 0; cnt < DSize; cnt++)
            {
               if(LDesc[cnt] == 1) LDesc[cnt] = 0;

               if(LDesc[cnt] != 0)
               {
                  if((LDesc[cnt] == '\r') ||
                     (LDesc[cnt] == '\n') ||
                    !(isprint(LDesc[cnt]))) LDesc[cnt] = ' ';
               }
            }

            StripSpaces(LDesc);

            cnt = 0;

            if(qf[j].size < 10000)
            {
               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ld  ",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",qf[j].size);
            }

            if((qf[j].size > 10000) && (qf[j].size < 1000000))
            {
               tsize = qf[j].size / 1000;

               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ldK ",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",tsize);
            }

            if(qf[j].size > 1000000)
            {
               tsize = qf[j].size / 1000000;
               AFPrintf(NULL,of,"@{\"%-18.18s\" System \"Echo >>Outbound:%s.REQ %s\"}%s %4.4ldM ",qf[j].filename,Addr,qf[j].filename,NTooLong?"*":" ",tsize);
            }

            Len = 26;

            p = strtok(LDesc," ");

            while(p != NULL)
            {
               if((Len + strlen(p)) > Width)
               {
                  cnt++;
                  if((LongLines != 0) && (cnt > LongLines)) break;
                  AFPrintf(NULL,of,"\n");
                  Len = AFPrintf(NULL,of,"                          ");
               }

               Len = Len + strlen(p) + 1;

               AFPrintf(NULL,of,"%s ",p);

               p = strtok(NULL," \0");
            }

            AFPrintf(NULL,of,"\n");

            free(LDesc);
            LDesc = NULL;
            Close(fh);
            fh = NULL;
         }

//-
      }
//-

      if(!Quiet)
      {
         stopwheel();
         AFPrintf(NULL,sout,"\n");
      }

      if(qf)
      {
         free(qf);
         qf = NULL;
      }

      AFPrintf(NULL,of,"%s\n@EndNode\n",Bar);
   }
//-

   ShutDown(0,NULL);
}
//-

/// ShutDown
void ShutDown(int Error, char *ErrStr)
{
   if(fh) Close(fh);
   if(of) Close(of);

   if(farea) free(farea);
   if(qf)    free(qf);

   if(DLGBase) CloseLibrary(DLGBase);

   if(Error)
   {
      FPuts(sout,"FileGuide: ");
      FPuts(sout,ErrStr);
      FPuts(sout,"\n\n");
   }

   exit(Error);
}
//-

/// Usage
void  Usage(void)
{
   AFPrintf(NULL,sout,"Usage:\n\n");
   AFPrintf(NULL,sout,"\tFileGuide -q -i <introfile> -o <outputfile>\n");
   AFPrintf(NULL,sout,"\t          [-l <level>] [-e] [-d <days>] [-f <file pattern>]\n");
   AFPrintf(NULL,sout,"\t          [-m] [-a <arealist> [-> <size>] [-< <size>]\n\n");
   AFPrintf(NULL,sout,"\t-q            =  Quiet mode\n");
   AFPrintf(NULL,sout,"\t-i <intro>    =  Introductory file header\n");
   AFPrintf(NULL,sout,"\t-o <filename> =  Name of resulting text file list\n");
   AFPrintf(NULL,sout,"\t-l level      =  Access Level to access areas with\n");
   AFPrintf(NULL,sout,"\t-e            =  Show all areas regardless of FREQ status\n");
   AFPrintf(NULL,sout,"\t-d <days>     =  Number of days back to list files\n");
   AFPrintf(NULL,sout,"\t-f <pattern>  =  File pattern to search for\n");
   AFPrintf(NULL,sout,"\t-p <pattern>  =  File/Desc pattern to search for\n");
   AFPrintf(NULL,sout,"\t-m            =  Do not list magic file names\n");
   AFPrintf(NULL,sout,"\t-a <arealist> =  Areas to search in (quoted if spaces used)\n");
   AFPrintf(NULL,sout,"\t-v <lines>    =  Use long descriptions, limit of <lines> lines per\n");
   AFPrintf(NULL,sout,"\t-w <width>    =  Set page width to <width>\n");
   AFPrintf(NULL,sout,"\t-> <size>     =  Look for files bigger than <size>\n");
   AFPrintf(NULL,sout,"\t-< <size>     =  Look for files smaller than <size>\n");
   AFPrintf(NULL,sout,"\n");
   ShutDown(5,"Exiting");
}
//-

/// Wheel stuff
void startwheel(void)
{
   wheelpos = 0;
   Write(sout," ",1L);
   Write(sout,"\010",1L);
}

void turn(void)
{
   Write(sout,wheel+wheelpos,1L);
   Write(sout,"\010",1L);
   wheelpos++;
   if (wheelpos == 4)  wheelpos=0;
}

void stopwheel(void)
{
   AFPrintf(NULL, sout, " \010");
}
//-

/// _CXBRK
void _CXBRK()
{
   ShutDown(5,"Control-C Detected");
}
//-

/// CheckForNewFiles
BOOL CheckForNewFiles(long Area,ULONG DaySecs,ULONG CurSecs)
{
   char qname[512];
   long q;
   ULONG qsize = 0;
   struct QuickFile *mqf = NULL;

   ASPrintf(NULL,qname,"File:%ld/file.dat",Area);

   if(-1 == FileSize(qname,&qsize))       return(FALSE);
   if(qsize == 0)                         return(FALSE);
   if(qsize < sizeof(struct QuickFile))   return(FALSE);

   mqf = calloc(1,qsize);

   if(!mqf) return(FALSE);

   if(-1 == GetFirstStruct(qname,(char *)mqf,qsize))
   {
      free(mqf);
      return(FALSE);
   }

   for(q = 0; q < (qsize / sizeof(struct QuickFile)); q++)
   {
      if( (CurSecs - mqf[q].date) < DaySecs)
      {
         free(mqf);
         return(TRUE);
      }
   }

   free(mqf);
   return(FALSE);
}
//-

/// CheckForSize
BOOL CheckForSize(long Area,ULONG size,BOOL Bigger)
{
   char qname[512];
   long q;
   ULONG qsize = 0;
   struct QuickFile *mqf = NULL;

   ASPrintf(NULL,qname,"File:%ld/file.dat",Area);

   if(-1 == FileSize(qname,&qsize))       return(FALSE);
   if(qsize == 0)                         return(FALSE);
   if(qsize < sizeof(struct QuickFile))   return(FALSE);

   mqf = calloc(1,qsize);

   if(!mqf) return(FALSE);

   if(-1 == GetFirstStruct(qname,(char *)mqf,qsize))
   {
      free(mqf);
      return(FALSE);
   }

   for(q = 0; q < (qsize / sizeof(struct QuickFile)); q++)
   {
      if(Bigger)
      {
         if(mqf[q].size >= size)
         {
            free(mqf);
            return(TRUE);
         }
      }

      if(!Bigger)
      {
         if(mqf[q].size <= size)
         {
            free(mqf);
            return(TRUE);
         }
      }
   }

   free(mqf);
   return(FALSE);
}
//-

/// CheckForPat
BOOL CheckForPat(long Area,char *Pat,BOOL LongDesc)
{
   char qname[512];
   long q;
   ULONG qsize = 0;
   struct QuickFile *mqf = NULL;

   ASPrintf(NULL,qname,"File:%ld/file.dat",Area);

   if(-1 == FileSize(qname,&qsize))       return(FALSE);
   if(qsize == 0)                         return(FALSE);
   if(qsize < sizeof(struct QuickFile))   return(FALSE);

   mqf = calloc(1,qsize);

   if(!mqf) return(FALSE);

   if(-1 == GetFirstStruct(qname,(char *)mqf,qsize))
   {
      free(mqf);
      return(FALSE);
   }

   for(q = 0; q < (qsize / sizeof(struct QuickFile)); q++)
   {
      if(DLGPatternMatch(Pat,mqf[q].filename))
      {
         free(mqf);
         return(TRUE);
      }

      if(LongDesc)
      {
         if(DLGPatternMatch(Pat,mqf[q].desc))
         {
            free(mqf);
            return(TRUE);
         }
      }
   }

   free(mqf);
   return(FALSE);
}
//-

