/*********************************************************************
 *  F I L E R E Q 2 - a continuation of last month's file requester. *
 *                                                                   *
 *                                           Tom Krotchko            *
 *********************************************************************/
#include "exec/types.h"
#include "exec/exec.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/io.h"
#include "exec/memory.h"
#include "exec/ports.h"
#include "graphics/gfxbase.h"
#include "intuition/intuition.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"

struct IntuitionBase *IntuitionBase;
struct IntuiMessage *message;
struct GfxBase *GfxBase;

/* The next three structures are used to access directory information */
extern struct FileLock *Lock();
struct FileLock *pathlock;
struct FileInfoBlock *fib;

/* this structure will contain the file names. Notice that this file
   requester can contain a maximum of 40 names. This number may be
   increased or dynamic memory allocation may be used.                */
struct file_stuff {
  char Name[22];
} fib_info[40];

/* The Intuition Text structures for gadget text */
struct IntuiText IText[10];
struct IntuiText   LoadText = {2,2,JAM1,9,1,NULL,(UBYTE *)"LOAD",NULL};
struct IntuiText CancelText = {2,2,JAM1,1,1,NULL,(UBYTE *)"CANCEL",NULL};

struct Gadget IndexGadget[10];

/* These two strings are to be used by the string gadget as the buffer and 
   the undo buffer (see text for more details)                       */
UBYTE DefString[20]=" ";
UBYTE Undo [20];

/* These two arrays describe the relative x,y position of the borders used
   to render our gadgets. Coord1 is used by the LOAD/CANCEL gadgets, and
   Coord2 is used by the string gadget                                   */
USHORT Coord1[]= {0,0, 52,0,  52,10,  0,10, 0,0};
USHORT Coord2[]= {0,0, 161,0, 161,10, 0,10, 0,0};

struct Border BoolBorder = {
 -1, -1,                   /* left, right position      */
 1,0,                      /* pen colors for rendering  */
 JAM1,                     /* drawing mode              */
 5,                        /* number of x,y pairs       */
 (APTR)&Coord1,            /* pointer to pairs          */
 NULL };                   /* pointer to another border */

struct Border StrBorder = {
 -1, -1,
 1,0,
 JAM1,
 5,
 (APTR)&Coord2,
 NULL };

struct StringInfo Our_StringInfo = {
DefString,                 /* pointer to string buffer */
Undo,                      /* pointer to undo buffer   */
0,                         /* initial cursor position  */
20,                        /* maximum number of chars  */
0,0,                       /* Display Pos - top, left  */
0,                         /* number chars displayed   */
0,0,0,                     /* calculated by Intuition  */
NULL,                      /* pointer to rastport      */
0,                         /* LongInt value            */
NULL };                    /* Alternate key map        */

struct Gadget LoadGadget = {
&IndexGadget[0],           /* pointer to the next gadget   */
20, 130, 51, 11,           /* left, top, width, height     */       
GADGHCOMP,                 /* Flags                        */
GADGIMMEDIATE | RELVERIFY, /* Activation Flags             */
BOOLGADGET,                /* Type of Gadget               */
(APTR)&BoolBorder,         /* Gadget Imagery               */
NULL,                      /* Pointer to SelectRender      */
(APTR)&LoadText,           /* Pointer to GadgetText        */
NULL,                      /* MutualExclusion doesn't work */
NULL,                      /* SpecialInfo                  */
400,                       /* Gadget ID                    */
NULL };                    /* Special Data                 */

struct Gadget CancelGadget = {
&LoadGadget,               /* pointer to the next gadget   */
100, 130, 51, 11,          /* left, top, width, height     */       
GADGHCOMP,                 /* Flags                        */
GADGIMMEDIATE | RELVERIFY, /* Activation Flags             */
BOOLGADGET,                /* Type of Gadget               */
(APTR)&BoolBorder,         /* Gadget Imagery               */
NULL,                      /* Pointer to SelectRender      */
(APTR)&CancelText,         /* Pointer to GadgetText        */
NULL,                      /* MutualExclusion doesn't work */
NULL,                      /* SpecialInfo                  */
300,                       /* Gadget ID                    */
NULL };                    /* Special Data                 */

struct Gadget A_StringGadget = {
&CancelGadget,             /* pointer to the next gadget   */
10, 115, 160, 11,          /* left, top, width, height     */       
GADGHCOMP,                 /* Flags                        */
GADGIMMEDIATE | RELVERIFY, /* Activation Flags             */
STRGADGET,                 /* Type of Gadget               */
(APTR)&StrBorder,          /* Gadget Imagery               */
NULL,                      /* Pointer to SelectRender      */
NULL,                      /* Pointer to GadgetText        */
NULL,                      /* MutualExclusion doesn't work */
(APTR)&Our_StringInfo,     /* SpecialInfo                  */
200,                       /* Gadget ID                    */
NULL };                    /* Special Data                 */

struct Image Gadget_Image;
struct PropInfo Gadget_PropInfo;

struct Gadget A_PropGadget = {
&A_StringGadget,           /* pointer to the next gadget   */
280, 15, 20, 90,           /* left, top, width, height     */       
GADGHCOMP,                 /* Flags                        */
GADGIMMEDIATE | RELVERIFY, /* Activation Flags             */
PROPGADGET,                /* Type of Gadget               */
(APTR)&Gadget_Image,       /* Gadget Imagery               */
NULL,                      /* Pointer to SelectRender      */
NULL,                      /* Pointer to GadgetText        */
NULL,                      /* MutualExclusion doesn't work */
(APTR)&Gadget_PropInfo,    /* SpecialInfo                  */
100,                       /* Gadget ID                    */
NULL };                    /* Special Data                 */
 
struct Window *Window;

struct NewWindow OurWindow = {150,20,310,150,3,2,
 GADGETDOWN | GADGETUP,
 SMART_REFRESH | WINDOWDRAG | ACTIVATE | NOCAREREFRESH | SIZEBRIGHT,
 &A_PropGadget,NULL,(UBYTE *)"List of Files", NULL,NULL,
 310,100,310,100,WBENCHSCREEN};

int success,f_count,First_Ten;
SHORT prop_position;

main() {
   ULONG Signals, MIClass;
   USHORT MIGadID;
   struct Gadget *MIGad;

   /* SetUp will open the various libraries and the window */
   SetUp();

   /* ReadDisplayMore will read the disk for up to 40 entries */
   ReadDisplayMore();

   /* Initialize the proportional gadget */
   SetPropGadget();

   /* Initialize the boolean gadgets */
   SetBoolGadget();

   /* Now display the first 10 files */
   First_Ten = 0;
   DisplayTen(First_Ten);


   for (;;) {
     /* remember to use the Wait function to put our process to sleep */
     /* if the user is not doing anything.                            */
     Signals=Wait(1<<Window->UserPort->mp_SigBit);
  
     while(message = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
         /* Decipher the message received from the IDCMP */
         MIClass = message->Class;
         MIGad   = (struct Gadget *)message->IAddress;
         MIGadID = MIGad->GadgetID;
         ReplyMsg(message);

         switch (MIClass) {
           case GADGETDOWN:
             break;
           case GADGETUP:
             switch (MIGadID) {
                case 100:    /* Proportional Gadget */
                   prop_position = ((ULONG)(f_count - 10) * 
                      Gadget_PropInfo.VertPot + (1L<<15)) >> 16;
                   if(prop_position<0) prop_position = 0;
                   DisplayTen(prop_position);
                   break;
                case 300:    /* Boolean (CANCEL) Gadget */
                   ShutDown();
                   exit(TRUE);
                   break;
                case 400:    /* Boolean (LOAD) Gadget */
                   break;
                default:     /* Boolean filename Gadget */
                   if(MIGadID<11) InsertString(MIGadID);
                   break;
             } /* Gadget Switch */
             break;
           default:
             printf("Serious IDCMP problem.\n");
             break;
         } /* switch */
     } /* while  */
   }   /*  for  */
} 

/********************** CALLED FUNCTIONS ************************/
ReadDisplayMore()
{
   int filled_up;
   char *p;

   /* back all the way out to the current directory */
   pathlock = Lock("",ACCESS_READ);

   if(pathlock==0) {
     printf("\nERROR: Couldn't lock the directory.\n");
     exit(FALSE);
   }
  
   /* allocate the proper amount of memory for a FileInfoBlock  */
   fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),
             MEMF_CLEAR);

   /* ALWAYS CHECK THE RETURN CODE FROM AN AllocMem() !!!! */
   if(fib == 0){
     printf("Couldn't allocate file info block. Exiting.\n");
     exit(FALSE);
   }

   /* Use the Examine at our lock to establish a starting point for our 
      browse through the directory. Once done, use the ExNext to ignore the
      name of the current directory. */
   success = Examine(pathlock,fib);
   success = ExNext(pathlock,fib);

   filled_up=0;
   f_count=0;

   while(filled_up==0){
  
      /* Play games to force the string to be only 20 bytes long      */
      fib->fib_FileName[21]=NULL;

      /* Then copy the file name from the file info block             */
      p = stpcpy(fib_info[f_count].Name,fib->fib_FileName);

      /* Finally, put "(dir)" in gadget to indicate a directory.      
         a Directory entry type of <0 means a file, >0 is a directory */
      if(fib->fib_DirEntryType > 0)  p = stpcpy(p,"  (dir)");

      f_count++;
     
      if(f_count>39) filled_up = 1;

      /* Get the next entry from the disk */                    
      success = ExNext(pathlock,fib);

      /* If it wasn't successful, assume that there are no more entries */
      if(!success) filled_up = 1;
   } /* while */

   /* unlock the path */
   if(pathlock) UnLock(pathlock);

   /* de-allocate the memory for the file info block */
   if(fib) FreeMem(fib,sizeof(struct FileInfoBlock));

} /* end of ReadDisplayTen() */
/****************************************************************/
SetPropGadget()
{
   LONG gad_pos, real_pos;

   gad_pos = RemoveGList(Window,&A_PropGadget,1L);

   Gadget_PropInfo.Flags    = FREEVERT | AUTOKNOB;
   Gadget_PropInfo.VertBody = (ULONG)(10 * 0xFFFF) / f_count; 
   if(f_count<10) Gadget_PropInfo.VertBody = 0xFFFF;
   Gadget_PropInfo.VertPot  = 0x0000;

   real_pos = AddGList(Window,&A_PropGadget,gad_pos,1L,(LONG)NULL);
   RefreshGList(&A_PropGadget,Window,(LONG)NULL,1L);
} /* end of SetPropGadget    */
/****************************************************************/
SetBoolGadget()
{
   int i;

   for(i=0;i<10;i++) {  
      /* Set up the IntuiText structure */
      IText[i].FrontPen=1;
      IText[i].BackPen=0;
      IText[i].DrawMode=JAM2;
      IText[i].LeftEdge=1;        
      IText[i].TopEdge=1;
      IText[i].ITextFont=NULL;
      IText[i].NextText=NULL;

      IndexGadget[i].NextGadget=&IndexGadget[i+1];
      IndexGadget[i].LeftEdge=5;
      IndexGadget[i].TopEdge=i * 9 + 12;
      IndexGadget[i].Width=182;
      IndexGadget[i].Height=9;
      IndexGadget[i].Flags=GADGHCOMP;
      IndexGadget[i].Activation=GADGIMMEDIATE|RELVERIFY;
      IndexGadget[i].GadgetType=BOOLGADGET;
      IndexGadget[i].GadgetRender=NULL;
      IndexGadget[i].SelectRender=NULL;
      IndexGadget[i].GadgetText=(UBYTE *)&IText[i];
      IndexGadget[i].MutualExclude=NULL;
      IndexGadget[i].SpecialInfo=NULL;
      IndexGadget[i].GadgetID=i;
      IndexGadget[i].UserData=NULL;
   }

   /* Force the last gadget to point to NULLS, ending the gadget list */
   IndexGadget[i-1].NextGadget=NULL;
} /* SetBoolGadget */
/****************************************************************/
/* SetUp() - set up intuition                                   */
SetUp()
{
  IntuitionBase=(struct IntuitionBase *) 
    OpenLibrary("intuition.library",0);

  if(IntuitionBase == NULL) {
    printf("Bad IntuitionBase Open.  \n");
    exit(FALSE);
  } 

  GfxBase=(struct GfxBase *) 
    OpenLibrary("graphics.library",0);

  if(GfxBase == NULL) {
    printf("Bad GfxBase Open.  \n");
    exit(FALSE);
  } 

  if((Window=(struct Window *) OpenWindow(&OurWindow)) == NULL) {
    printf("Window Could Not Be Opened.\n");
    exit(FALSE);
  }
} /* SetUp() */
/****************************************************************/
DisplayTen(StartAt)
int StartAt;
{
   LONG gad_pos, real_pos;
   int i,j;
   j=0;

   for(i=StartAt;i<StartAt+10;i++) {
      /* FIRST - blank out the old text */
      gad_pos = RemoveGList(Window,&IndexGadget[j],1L);

      IText[j].IText="                    ";

      real_pos = AddGList(Window,&IndexGadget[j],gad_pos,1L,(LONG)NULL);
      RefreshGList(&IndexGadget[j],Window,(LONG)NULL,1L);

      /* NEXT - put in the new text */
      gad_pos = RemoveGList(Window,&IndexGadget[j],1L);

      if(i<=f_count)
        IText[j].IText=(UBYTE *)&fib_info[i].Name;

      real_pos = AddGList(Window,&IndexGadget[j],gad_pos,1L,(LONG)NULL);
      RefreshGList(&IndexGadget[j],Window,(LONG)NULL,1L);

      j++;
   }

} /* DisplayTen */
/****************************************************************/
InsertString(WhichGadget)
SHORT WhichGadget;
{
  LONG gad_pos, real_pos;

  /* Put in the selected text */
  gad_pos = RemoveGList(Window,&A_StringGadget,1L);
  Our_StringInfo.Buffer=IText[WhichGadget].IText;
  Our_StringInfo.BufferPos = 0;
  Our_StringInfo.NumChars = 0;
  real_pos = AddGList(Window,&A_StringGadget,gad_pos,1L,(LONG)NULL);
  RefreshGList(&A_StringGadget,Window,(LONG)NULL,1L);
} /* InsertString */
/****************************************************************/
ShutDown()
{
 CloseWindow(Window);
 CloseLibrary(IntuitionBase);
}
/****************************************************************/
