#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <fcntl.h>
#include <exec/types.h>
#include <libraries/dosextens.h>

#include <dlg/dlg.h>
#include <dlg/user.h>
#include <dlg/file.h>
#include <dlg/msg.h>
#include <dlg/input.h>

#include <link/io.h>
#include <link/lang.h>

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

#include <pragmas/dlg.h>

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

void  main(int, char **);
void  FindFile(char *, char);
void  PrintFile(short, struct Msg_Area *, char *);
void  GetInput(void);
void _CXBRK(void);

#define STK  RStruct.Command_Stack
#define HOT  UserDat.Hot_Keys

BPTR                sout;
struct Library     *DLGBase = NULL;
struct LangStruct  *ls;
char              **SA;

struct USER_DATA    UserDat = {"", 24, 80, 0, 1, 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
struct Ram_File     RStruct = {"", 0, "", 0, "", 0, 0, 0, "", "", 0, 0, 0, 0, 0, ""};
struct UserInfo     ui      = {&UserDat, &RStruct};
struct Query        q       = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0};

USHORT              pos;
USHORT              file;

struct Batch       *ctag;
struct Batch       *tag_files;

FILE               *fp     = NULL;
struct QuickFile   *QFile  = 0;
struct QuickFile   *CQuick = 0;
ULONG               QSize  = 0;
char                Ext[4] = "";
char                CLI    = FALSE;


void main(int argc, char **argv)

{long zflag;
 char allareas;
 char searchname[80];
 char wstring   [80];

 sout = Output();

 if (!(DLGBase = OpenLibrary(DLGNAME, DLGVERSION)))
    {Write(sout, "\nError: Can't open dlg.library\n\n", 32);
     exit(5);
    }

 if (GetDevName(Ext) == -1)
    {CLI = TRUE;
     rawcon(1);
    }
   else
     if (!ReadUser(&RStruct, &UserDat, Ext))  _CXBRK();

 if (!(SA = getlang(Ext)))  _CXBRK();


 if (!(tag_files = malloc(sizeof(struct Batch) * UserDat.Screen_Len)))
    {AFPrintf(&UserDat, sout, SA[520]);
    _CXBRK();
    }

 q.prompt     = SA[521];
 q.string     = searchname;
 q.length     = 36;
 q.typelength = 254;
 q.flags      = QUERY_UPCASE|QUERY_NOSTACK;
 zflag        = DLGQuery(&q, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!zflag)  _CXBRK();

 allareas = 1;
 if (!CLI)
    {allareas = BoolQuery(SA[522], 1, &ui);
     AFPrintf(&UserDat, sout, "\n\n");
    }

 if (!strchr(searchname, '*')  &&  !strchr(searchname, '?'))
    {strcpy(wstring, "*");
     strcat(wstring, searchname);
     strcat(wstring, "*");
     strcpy(searchname, wstring);
    }

 FindFile(searchname, allareas);
 free(tag_files);
_CXBRK();
}


void FindFile(char *searchname, char areas)

{long  plen;
 long  first;

 ULONG fsize;

 char  sstring   [80];
 char  accessname[80];

 struct Msg_Area  Area;
 struct Msg_Log   Log;


 if (!(fp = fopen("FILE:Area.BBS", "r")))
    {AFPrintf(&UserDat, sout, SA[523]);
     return;
    }

 ctag = tag_files;
 pos  =    0;
 file =    0;
 Clr(UserDat.Ansi_Flag);
 strcpy(sstring, SA[524]);

 AFPrintf(&UserDat, sout, sstring, searchname);
 StartWheel();

 while(fread(&Area, sizeof(Area), 1, fp))
      {if (ReadChar(0)==3)
          {AFPrintf(&UserDat, sout, SA[525]);
          _CXBRK();
          }

       TurnWheel();
       if (!areas  &&  Area.Number != UserDat.Last_File_Area)  continue;

       ASPrintf(NULL, accessname, "File:%d/File.Dat", Area.Number);
       if (!CLI)
           if (!((Area.Flag & AUTO_ACCESS_AREA)  &&  UserDat.User_Level >= Area.llevel  &&  UserDat.User_Level <= Area.ulevel))
              {ASPrintf(NULL, accessname, "FILE:%d/User.File", Area.Number);
               strcpy(Log.Name, RStruct.Name);
               if (GetStruct(accessname, (char *)&Log, sizeof(Log), 36) == -1)  continue;
              }

       first = 1;

       if (FileSize(accessname, &fsize) == -1)  continue;
       if (QSize < fsize)
          {if (QSize)
              {QSize = 0;
               free(QFile);
              }

           if (!(QFile = malloc(fsize)))
              {AFPrintf(&UserDat, sout, "\nError: Can't allocate Quick File\n\n");
               return;
              }

           QSize = fsize;
          }

       CQuick = QFile;
       if (GetFirstStruct(accessname, (char *)CQuick, fsize) == -1)  continue;

       while(TRUE)
            {if (DLGPatternMatch(searchname, CQuick->filename)  ||  DLGPatternMatch(searchname, CQuick->desc))
                {if (first)
                    {if (pos > UserDat.Screen_Len - 3)
                         GetInput();
                       else
                        {plen = strlen(sstring) + strlen(searchname) - 1;
                         Write(sout, "\r", 1);
                         PrintSpace(sout, 0, plen);
                         Write(sout, "\r", 1);
                        }
                     AFPrintf(&UserDat, sout, SA[526], Area.Number, Area.Name);
                     pos++;
                     first = 0;
                    }

                 PrintFile(CQuick->number, &Area, CQuick->desc);
                 if (pos < UserDat.Screen_Len - 1)
                    {AFPrintf(&UserDat, sout, sstring, searchname);
                     StartWheel();
                    }
                }

             CQuick++;
             if (((char *)CQuick - (char *)QFile) >= fsize)
                {if (!first)
                    {plen = strlen(sstring)  + strlen(searchname) - 1;
                     Write(sout, "\r", 1);
                     PrintSpace(sout, 0, plen);
                     Write(sout, "\n", 1);
 
                     AFPrintf(&UserDat, sout, sstring, searchname);
                     StartWheel();
                     pos++;
                    }

                 break;
                }

             if (pos < UserDat.Screen_Len - 1)
                {TurnWheel();
                 if (ReadChar(0)==3)
                    {AFPrintf(&UserDat, sout, SA[525]);
                    _CXBRK();
                    }

                 Chk_Abort();
                 continue;
                }

             GetInput();
             AFPrintf(&UserDat, sout, sstring, searchname);
             StartWheel();
             first = 1;
            }
      }

 if (file)
     GetInput();
   else
    {StopWheel();
     AFPrintf(NULL, sout, "\n\n");
    }

 return;
}


void PrintFile(short number, struct Msg_Area *area, char *desc)

{long               b;
 SHORT              descwidth;
 char               description[60];

 struct File_Header Header;
 char               fd[40];

 ASPrintf(NULL, fd, "File:%d/%d.fd", area->Number, number);
 if (GetFirstStruct(fd, (char *)&Header, sizeof(Header)) == -1)  return;

 descwidth = UserDat.Screen_Width-31;
 if (descwidth < 20)  descwidth = 20;
 if (descwidth > 56)  descwidth = 56;

 strcpy(description, desc);
 b = 0;
 while((description[b]==' ' ||  description[b]==10  ||  description[b]==13))
        b++;
 if (b)  movmem(&description[b], description, sizeof(description) - b);

 for(b=0; b < descwidth; b++)
     if (description[b]==10 || description[b]==13)
         description[b] = 0;

 description[descwidth]   = '.';
 description[descwidth+1] = '.';
 description[descwidth+2] = '.';
 description[descwidth+3] =  0;

 file++;
 AFPrintf(&UserDat, sout, SA[527], file, Header.Filename, (Header.Size/1024)+1, description);

 strcpy(ctag->filename, Header.Filename);
 GetPath(ctag->path, area->Number, area, Header.Filename);
 ctag->free = 0;
 if (Header.Attribute & NORATIO)  ctag->free |= 1;
 ctag->size = Header.Size;

 ctag++;
 pos++;
 return;
}


void GetInput()

{long fnumber;
 long tnumber;
 long index;
 long plen;

 char prompt [80];
 char tagfile[80];
 char input  [80];
 long zflag;

 ASPrintf(NULL, tagfile, "User:%s/Batch.File", RStruct.Name);
 UnderScore(tagfile);

 while(TRUE)
      {Chk_Abort();
       strcpy(prompt, SA[528]);
       plen  = strlen(prompt);

       q.prompt     = prompt;
       q.string     = input;
       q.length     = UserDat.Screen_Width-plen;
       q.typelength = UserDat.Screen_Width-plen;
       q.flags      = QUERY_UPCASE|QUERY_NOSTACK;
       zflag        = DLGQuery(&q, &ui);

       plen = plen + strlen(input) + 1;
       Write(sout, "\r", 1);
       PrintSpace(sout, 0, plen);
       Write(sout, "\r", 1);

       if (!zflag)
          {ctag = tag_files;
           pos  =    0;
           file =    0;
           Clr(UserDat.Ansi_Flag);
           return;
          }

       if (!strcmp(input, "Q"))  _CXBRK();
       strcpy(prompt, SA[529]);
       plen = 0;

       if (!CLI)
           while(strlen(input))
                {fnumber = atol(input);
                 tnumber = fnumber;

                 for(index=0; input[index] == ' '; index++);
                 for(; index < strlen(input); index++)
                     if (!(input[index] >= '0'  &&  input[index] <='9'))  break;
                 for(; index < strlen(input); index++)
                    {if (input[index] >= '0'  &&  input[index] <='9')     break;
                     if (input[index] == '-')                             break;
                    }
                 movmem(&input[index], input, strlen(input)-index+1);

                 if (input[0] == '-')
                    {tnumber = atol(&input[1]);

                     for(index=1; input[index] == ' '; index++);
                     for(; index < strlen(input); index++)
                         if (!(input[index] >= '0'  &&  input[index] <='9'))  break;
                     for(; index < strlen(input); index++)
                         if (input[index] >= '0'  &&  input[index] <='9')     break;
                     movmem(&input[index], input, strlen(input)-index+1);
                    }

                 if (fnumber > tnumber)  continue;

                 if (!plen)
                    {AFPrintf(&UserDat, sout, prompt);
                     plen = strlen(prompt);
                    }

                 if (fnumber != tnumber)
                     ASPrintf(&UserDat, prompt, SA[530], fnumber, tnumber);
                   else
                     ASPrintf(&UserDat, prompt, SA[531], fnumber);
                 AFPrintf(NULL, sout, prompt);
                 plen = plen + strlen(prompt);

                 while(fnumber <= tnumber)
                      {if (fnumber > file)  break;

                       if (fnumber > 0)
                           AddStruct(tagfile, (char *)(tag_files+fnumber-1), sizeof(struct Batch), 40);

                       fnumber++;
                      }
                }

       Write(sout, "\r", 1);
       PrintSpace(sout, 0, plen);
       Write(sout, "\r", 1);
      }
}


void _CXBRK()

{if (fp)       fclose(fp);
 if (QSize)    free(QFile);
 if (DLGBase)  CloseLibrary(DLGBase);
 if (CLI)      rawcon(0);

 exit(0);
}
