/***************************************************************************
* getfile.c  by: Keith Young                                      12/20/87
*
*   These routines were origionally written by: Charlie Heath of Microsmiths
* (getfile.c on Manx Aztec C examples disk) and were Heavily modified by me
* ( Keith Young ) for use in my ShareWare terminal program: "Access!" and
* then further modified for "portability" and infestation into the public.
* (as FREEWARE).
*  I'll not attemp to list all the modifications made (sounds to much like
* work). Nor will I guarantee that they even work at all (but hey, they work
* for me :-). 
*
*  You may Use these source files, modify 'em, throw 'em away, give 'em away,
* without obligation. JUST DON'T SELL 'EM! (I doubt you'd get much anyway:-)
* 
*   If you do use 'em (in a noncomercial manner), I would appeciate a small
* "mention" in the docs somewhere. (small print, lower left hand corner will
* do )
*  
*  These routines now compile using AZTEC 3.4a using 16 bit ints.(horay!)
* (see included makefile)
*
*   Any bug reports/suggestions/fixes/etc... would be appreciated.
* 
*   I can be reached at:              (703) 297-7639
*
* via    E-MAIL->  GEnie: K.Young
*                 CA-AUG: Keith Young
*           Deep Thought: Keith Young
*             COMPUSERVE: 73170,307
*
* via Snail-Mail-> Keith Young
*                  Rt.2 Box 261
*                  Goodview, Va.   (yes, really :-)
*                           24095
*  
***************************************************************************/

#include <ctype.h>
#include <stdio.h>

#include "standard.h"
#include "safeclose.h"
#include "img.h"
#define FAST register
#define NL 0L

extern UBYTE               *dmore(), *dinit();
extern APTR                *AllocMem();
extern UBYTE               *rindex(), *index();
extern struct FileLock     *Lock();
extern struct InfoData     *Info();
extern struct Window       *OpenWindow();
extern struct IntuiMessage *GetMsg();

static struct FileLock      *pdir = NL;
static struct FileInfoBlock *dir_info;
static struct Window        *eW;      /* Parent Window. Uck   */


 /* this is initialized in "test.c" currently... */
extern struct TextAttr MyFont;/* = { 
   (UBYTE *)"topaz.font",     
   TOPAZ_EIGHTY,
   FS_NORMAL,
   FPF_ROMFONT
 };*/


#define FGAD      0L           /* Offset gadget ID's from here */

#define FCHARS    32L          /* Number of chars allowed in file name   */
#define DIR_SIZ   50L          /* Number of chars in a dir name...   */
#define MAX_STR   DIR_SIZ+2L

#define DENTS     7L           /* Number of entries on screen   */
                               /* It's not as simple as changing 'DENTS'... */
#define DSIZE     FCHARS+1L    /* Size of a directory entry   */
#define DBUFSIZ   4000L        /* Number of bytes to allocate for all ents */

#define BCOL      7L           /* Background color   */
#define FCOL      6L           /* Foreground color   */

#define RHGHT   128L
#define RWDTH   390L
#define ZWDTH   250L           

static UBYTE  def1[DIR_SIZ] = "DF2:\0";  /* user defined directory #1 */
static UBYTE  def2[DIR_SIZ] = "DH0:\0";  /* user defined directory #2 */
static UBYTE  sbuff[20] = "\0";          /* string buffer for "Bytes Free:" */
static UBYTE  ubuf[MAX_STR];             /* Undo buffer   */

static struct dirent {
       struct dirent *next;    /* ptr to next dirent */ 
       BOOL isfile;            /* file or directory ? */
       LONG d_size;            /* file size */
       UBYTE dE[DSIZE+2];      /* file name kept here */
 };
static struct dirent *FirstEntry;
static struct dirent *NextEntry;

static struct dirhead {
       struct dirent *next;
 };
static struct dirhead ListHead;

static ULONG  curent,maxent;
static BOOL   more;
static BOOL   up,dn;            /* toggle flags for quick-scrolling */
static struct Window     *wRq = NL;      /* Requester window   */
static struct RastPort   *wRp;

static struct IntuiText saydir = {1,2,JAM2,0,1,&MyFont,(UBYTE *)"(dir) ",NL};

/**************************************************************************
 * the following IntuiText is paired together as text + shadowtext...
 * (there are better ways to do this)
 **************************************************************************/

static struct IntuiText partext[2] = {
           {0,0,JAM1, 7,2,&MyFont,(UBYTE *)"PARENT",&partext[1]},
           {5,0,JAM1, 5,1,&MyFont,(UBYTE *)"PARENT",NL}
           };

static struct IntuiText bytext[2] = {
           {0,0,JAM1,210,RHGHT-16,&MyFont, NL,&bytext[1]},
           {4,0,JAM1,208,RHGHT-17,&MyFont, NL,NL}
           };

static struct IntuiText freeTxt[2] = {
           {0,0,JAM1,120,RHGHT-16,&MyFont,(UBYTE *)"Bytes Free:",&freeTxt[1]},
           {5,0,JAM1,118,RHGHT-17,&MyFont,(UBYTE *)"Bytes Free:",NL}
           };

static struct IntuiText otxt[2] = {
           {0,0,JAM1,20,RHGHT-32,&MyFont,(UBYTE *)"File",&otxt[1] },
           {5,0,JAM1,18,RHGHT-33,&MyFont,(UBYTE *)"File",&freeTxt[0] }
           };

static struct IntuiText dtxt[2] = {
           {0,0,JAM1,20,14,&MyFont,(UBYTE *)"Drawer",&dtxt[1]},
           {5,0,JAM1,18,13,&MyFont,(UBYTE *)"Drawer",&otxt[0]}
           };

static struct IntuiText rsize[DENTS] = {      /* File size list */
   {5,2,JAM2,213,1,&MyFont,NL, NL},
   {5,2,JAM2,213,1,&MyFont,NL, NL},
   {5,2,JAM2,213,1,&MyFont,NL, NL}, 
   {5,2,JAM2,213,1,&MyFont,NL, NL},
   {5,2,JAM2,213,1,&MyFont,NL, NL},
   {5,2,JAM2,213,1,&MyFont,NL, NL},
   {5,2,JAM2,213,1,&MyFont,NL, NL}
};
static struct IntuiText rname[DENTS+6] = {    /* File name list */
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,2,JAM2,48,1,&MyFont,NL, NL}, 
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,2,JAM2,48,1,&MyFont,NL, NL},
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"DH0:",NL}, /* device/dir name list */
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"DF2:",NL},
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"DF1:",NL},
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"DF0:",NL},
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"VD0:",NL},
   {0,0,JAM1,5,16,&MyFont,(UBYTE *)"RAM:",NL}
 };

/* Border for Drawer ... */

static SHORT oXY1[] = {
   -1,-1,
   193,-1,
   193,8,
   -1,8,
   -1,-1
 };
static struct Border thebd1 = {
   0,0,
   6,0,JAM1,
   5,oXY1,
   NL
 };

/* Border for file name ... */

static SHORT oXY2[] = {
   -1,-1,
   209,-1,
   209,8,
   -1,8,
   -1,-1
 };
static struct Border thebd2 = {
   0,0,
   6,0,JAM1,
   5,oXY2,
   NL
 };

static struct Image myknob;
static struct PropInfo   cc_prop = {
     AUTOKNOB | FREEVERT,         /* flags */
     0,0,                         /* HPot, VPot */
     0,0x10000,                   /* HBody,VBody */
     0,0,0,0,0,0
 };
static struct Gadget gprop = {
     NULL,                           /* Next gadget   */
     RWDTH-120,23,                   /* Left, Top     */
     20,70,                          /* Scroll Bar    */
     GADGHIMAGE | GADGIMAGE ,        /* Flags         */
     GADGIMMEDIATE | FOLLOWMOUSE,    /* Activation    */
     PROPGADGET,                     /* Type          */
     (APTR)&myknob,                  /* Render        */
     NL,                             /* Select Render */
     NL,NL,                          /* Text, Exclude */
     (APTR)&cc_prop,                 /* Special Info  */
     FGAD+13,                        /* GadgetID      */
     NL                              /* UserData      */
 };

static struct Gadget scr_dn = {
   &gprop,
   RWDTH-119,RHGHT-35,
   20,10,                    /* scroll dn   */
   GADGHNONE,      
   GADGIMMEDIATE,      
   BOOLGADGET,
   NL,NL,  
   NL,
   NL,NL,           
   FGAD+22,
   NL
 };                
static struct Gadget scr_up = {
   &scr_dn,
   RWDTH-119,13,
   20,10,                    /* scroll up   */
   GADGHNONE,      
   GADGIMMEDIATE,      
   BOOLGADGET,
   NL,NL,  
   NL,
   NL,NL,           
   FGAD+21,
   NL
 };                

static struct Gadget par = {
   &scr_up,
   306,13,
   58,10,                    /* PARENT   */
   GADGHCOMP,      
   RELVERIFY,      
   BOOLGADGET,
   NL,NL,  
   &partext[0],
   NL,NL,           
   FGAD+20,
   NL
 };                
static struct StringInfo gsdef2 = {
    NL,
    NL,
    NL,
    DIR_SIZ,
    NL,NL,NL,NL,NL,NL,NL,NL,NL
 };
static struct Gadget gdef2 = { /* string gadget for user defined directory */
   &par,
   RWDTH-47,95,
   32,10,                             /* string #2 */
   GADGHCOMP, RELVERIFY, STRGADGET,
   NL,NL, NL, /*txt*/
   NL, (APTR)&gsdef2,
   FGAD+19,
   NL
 };

static struct StringInfo gsdef1 = {
    NL,
    NL,
    NL,
    DIR_SIZ,
    NL,NL,NL,NL,NL,NL,NL,NL,NL
 };
static struct Gadget gdef1 = { /* string gadget for user defined directory */
   &gdef2,
   RWDTH-87,95,
   32,10,                               /* string #1 */
   GADGHCOMP, RELVERIFY, STRGADGET,
   NL,NL, NL, 
   NL, (APTR)&gsdef1,
   FGAD+18,
   NL
 };

static struct StringInfo gsfil = {
   NL,
   ubuf,
   NL,
   DSIZE,
   NL,NL,NL,NL,NL,NL,NL,NL,NL
};
static struct Gadget gfil = {
   &gdef1,
   60,RHGHT-33,
   RWDTH-178,10,                      /* File name gadget */
   GADGHCOMP, RELVERIFY, STRGADGET,
   (APTR)&thebd2,
   NL, NL,/*txt*/
   NL, (APTR)&gsfil,
   FGAD+17,
   NL
 };

static struct StringInfo gsdir = {
    NL,
    ubuf,
    NL,
    DIR_SIZ,
    NL,NL,NL,NL,NL,NL,NL,NL,NL
 };
static struct Gadget gdir = {
   &gfil,
   76,13,
   RWDTH-193,10,                     /* Directory gadget */
   GADGHCOMP, RELVERIFY, STRGADGET,
   (APTR)&thebd1,
   NL, NL,/*txt*/
   NL, (APTR)&gsdir,
   FGAD+16,
   NL
 };

static struct Gadget gok = {
   &gdir,
   15,RHGHT-19,
   58,12,                    /* OTAY   */
   GADGIMAGE | GADGHIMAGE,      
   RELVERIFY, BOOLGADGET,
   (APTR)&okupImage,
   (APTR)&okdnImage,  
   NL, NL,NL,           
   FGAD+15,
   NL
 };                
static struct Gadget gcan = {
     &gok,
     RWDTH-81,RHGHT-19,
     58,12,                 /* CANCEL */
     GADGIMAGE | GADGHIMAGE,
     RELVERIFY, BOOLGADGET,
     (APTR)&canupImage,
     (APTR)&candnImage,
     NL, NL,NL,
     FGAD+14,
     NL
 };

static struct Gadget gram = {
   &gcan,
   RWDTH-90 ,26,
   30,13,                     /* RAM */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   &rname[12], NL,NL,
   FGAD+12,
   NL
 };
static struct Gadget gvd0 = {
   &gram,
   RWDTH-50,26,
   30,13,                      /* VD0 */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   &rname[11], NL,NL,
   FGAD+11,
   NL
 };
static struct Gadget gdf0 = {
   &gvd0,
   RWDTH-90 ,52,
   30,13,                         /* DF0 */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   &rname[10], NL,NL,
   FGAD+10,
   NL
 };
static struct Gadget gdf1 = {
   &gdf0,
   RWDTH-50 ,52,
   30,13,                        /* DF1 */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   &rname[9], NL,NL,
   FGAD+9,
   NL
 };
static struct Gadget gdf2 = {
   &gdf1,
   RWDTH-90 ,78,
   30,13,                     /* DF2 */ /* (user #1) */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   NL, NL,NL,
   FGAD+8,
   NL
 };
static struct Gadget gdh0 = {
   &gdf2,
   RWDTH-50 ,78,
   30,13,                    /* DH0 */ /* (user #2) */
   GADGIMAGE | GADGHIMAGE,
   RELVERIFY, BOOLGADGET,
   (APTR)&disk1Image,
   (APTR)&disk2Image,
   NL, NL,NL,
   FGAD+7,
   NL
 };

static struct Gadget og7 = {
   &gdh0,
   20,83, ZWDTH,10,                      /* Gadgets For   */
   GADGHCOMP, RELVERIFY, BOOLGADGET,     /* Directory entries   */
   NL,NL, &rname[6],
   NL,NL,
   FGAD+6,
   NL
 };
static struct Gadget og6 = {
   &og7,
   20,73, ZWDTH,10,  
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[5],
   NL,NL,
   FGAD+5,
   NL
 };
static struct Gadget og5 = {
   &og6,
   20,63, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[4],
   NL,NL,
   FGAD+4,
   NL
 };
static struct Gadget og4 = {
   &og5,
   20,53, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[3],
   NL,NL,
   FGAD+3,
   NL
 };
static struct Gadget og3 = {
   &og4,
   20,43, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[2],
   NL,NL,
   FGAD+2,
   NL
 };
static struct Gadget og2 = {
   &og3,
   20,33, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[1],
   NL,NL,
   FGAD+1,
   NL
 };
static struct Gadget og1 = {
   &og2,
   20,23, ZWDTH,10,   
   GADGHCOMP, RELVERIFY, BOOLGADGET, 
   NL,NL, &rname[0],
   NL,NL,
   FGAD,
   NL
 };

/* Open a requester "Window" */

static struct NewWindow NewFiles = {
   120, 40,
   RWDTH,RHGHT,
   BCOL,FCOL,
   NL, /* Fill in AFTER opening ... */
   SMART_REFRESH | ACTIVATE | WINDOWDRAG,
   &og1,
   NL,(UBYTE *)"File Requester",NL,NL,
   RWDTH,RHGHT,RWDTH,RHGHT,
   WBENCHSCREEN  /* change this after call */
 };

extern struct IntuitionBase  *IntuitionBase;

/*******************************************************************
*  get_fname(window,screen,hail,ddef,ddir);
*
*   Displays a window/requester that
* gets a file name for device,directory,default file, extension
*
*   Calling args:
* window:   Window making the request
* screen:   Screen, if NULL assummed workbench
* hail:   Text prompt at top of requester
* ddef:   Input default file-name. Has NO DIRECTORY OR EXTENSION.
* ddir:   Directory of file, may be null
*/

/* Set a file-requester (actually a window) with title 'hail' */

UBYTE *get_fname(cW,screen,hail,ddef,ddir)
   struct Window *cW;       /* Calling Window   */
   struct Screen *screen;   /* screen .... if null assumed workbench */
   UBYTE      *hail;        /* Hailing prompt   */
   UBYTE      *ddef;        /* Probable file-name   */
   UBYTE      *ddir;        /* Directory in which to search   */
{
   FAST struct IntuiMessage *imes;   /* Wait for message in HERE   */
   FAST struct Gadget       *igad;   /* Get Gadget Mumbo Jumbo   */
   FAST ULONG  i,class;
   FAST TEXT   *pnam,*stomp;
   FAST UBYTE  *retval;              /* return value */
   FAST BOOL   dir_flag;
   FAST BOOL   keepon;
   USHORT      code;
   TEXT        ch;

   if ( ! (eW = cW) )   return(NL);

    gsfil.Buffer = ddef;   /* Set default file name   */
    gsdir.Buffer = ddir;   /* Set default device name   */
   gsdef1.Buffer = def1;   /* Set #1 default drive */
   gsdef2.Buffer = def2;   /* Set #2 default drive */

   up = FALSE;

   for ( i=0; i<DENTS; i++)
   {
      rname[i].IText    = NL;
      rsize[i].IText    = NL;
      rname[i].NextText = NL; 
   };

   NewFiles.Title = hail;
   if ((dir_info = (struct FileInfoBlock *)
          AllocMem((ULONG)sizeof(struct FileInfoBlock),MEMF_CHIP)) == NULL)
       return(NL);

   if (screen)      /* User supplied a screen */
   {
      NewFiles.Type   = CUSTOMSCREEN;
      NewFiles.Screen = screen;
   }

   if ( ! (FirstEntry = (struct dirent *)AllocMem((ULONG)DBUFSIZ,0L)) ||
        ! (wRq = (struct Window *)OpenWindow( &NewFiles )) )
   {
/*      emits_rx("Need more memory to open File-Requester...\n");*/
      if ( FirstEntry )   FreeMem(FirstEntry,(ULONG)DBUFSIZ);
      FreeMem(dir_info,(ULONG)sizeof(struct FileInfoBlock));
      return(NL);
   }

   ActivateGadget(&gfil,wRq,0L);
   wRp = wRq->RPort;

   wRq->UserPort = eW->UserPort;
   ModifyIDCMP(wRq,(ULONG)(MOUSEBUTTONS | GADGETDOWN | GADGETUP | MOUSEMOVE));
   SetAPen(wRp,2L);
   RectFill(wRp,3L,10L,(ULONG)(RWDTH-5),(ULONG)(RHGHT-2));

   PrintIText(wRp,&dtxt,0L,0L);
   DrawImage(wRp,&fmupImage,(long)(RWDTH-118),13L);/* up-dn scroll images */
   DrawImage(wRp,&fmdnImage,(long)(RWDTH-118),(long)(RHGHT-35));
   RefreshGadgets(&og1,wRq,0L); /* re-draw the gadgets after filling in the 
                                    background color */
   /* Set up directory, notify any errors...   */
   if ( pnam = (UBYTE *)dinit(ddir) )   notify(pnam);

   for ( retval= NL, keepon=TRUE; keepon ; )
   {
      while ( ! (imes=(struct IntuiMessage *)GetMsg(wRq->UserPort)) )  
      {
       if (up)
         {
          cc_prop.VertPot -= (cc_prop.VPotRes/ DENTS);
          RefreshGadgets(&gprop,wRq,0L); 
         }
       if (dn)
         {
          cc_prop.VertPot += (cc_prop.VPotRes/ DENTS);
          RefreshGadgets(&gprop,wRq,0L); 
         }
       if ( dir_flag || up || dn)
         {
          i = (maxent-DENTS) * cc_prop.VertPot / MAXBODY;
          if ( i > (maxent-DENTS) )
          i = maxent-DENTS;
          if ( i <0 )   i = 0;
          curent = i;
          cxxx();     /* display filenames/sizes  */
          dir_flag = FALSE;
         }
         if ( more )
         {
          if (pnam = (UBYTE *)dmore())   /* Continue to read the directory */
             notify(pnam);      /* Yucko error   */
          if ( maxent <= DENTS ) dir_flag = TRUE;
         }
         else
          if (!up && !dn)
             WaitPort(wRq->UserPort);
      }
      igad = (struct Gadget *)imes->IAddress;
      class = imes->Class;
      code = imes->Code;
      if(class != MOUSEMOVE && class != GADGETUP && class != GADGETDOWN &&
         class != MOUSEBUTTONS)
      {
       /* Process_Your_other_window_messages_here(imes); */
       WindowToFront(wRq);
       continue;
      }
      ReplyMsg(imes);
      switch (class)
      {
         case MOUSEMOVE:     dir_flag = TRUE; break;
         case MOUSEBUTTONS:  if (code == SELECTUP)
                               {
                                up = FALSE;
                                dn = FALSE;
                               } 
                             break;
         case GADGETUP:
         case GADGETDOWN:
                            if(igad->GadgetID == FGAD+21)
                               {
                                up = TRUE;
                                break;
                               } 
                            if(igad->GadgetID == FGAD+22)
                               {
                                dn = TRUE;
                                break;
                               } 
          switch ( i = igad->GadgetID)
           {
            case FGAD+0:
            case FGAD+1:
            case FGAD+2:
            case FGAD+3:
            case FGAD+4:    /* Replace file or directory name   */
            case FGAD+5:
            case FGAD+6:
            case FGAD+7:
            case FGAD+8:
            case FGAD+9:   
            case FGAD+10:
            case FGAD+11:
            case FGAD+12:
                 pnam = rname[i].IText;
                 if   ( rname[i].NextText == NL && i<DENTS )
                   {
                    RemoveGadget(wRq,&gfil);
                    for (i=0; i<DSIZE; i++)      ddef[i] = *pnam++;
                    AddGadget(wRq,&gfil,21L);
                    RefreshGadgets(&gfil,wRq,0L);
                    ActivateGadget(&gfil,wRq,0L);
                    break;
                   }
                 else
                   {
                    switch (i)
                    {
                     case FGAD+7 : *ddir = NL; pnam = def2;break;
                     case FGAD+8 : *ddir = NL; pnam = def1;break;
                     case FGAD+9 : *ddir = NL; break;
                     case FGAD+10: *ddir = NL; break;
                     case FGAD+11: *ddir = NL; break;
                     case FGAD+12: *ddir = NL; break;
                    }
                    RemoveGadget(wRq,&gdir);
                    rfnam(ddir,pnam);
                    AddGadget(wRq,&gdir,21L);
                    RefreshGadgets(&gdir,wRq,0L);
                    }
            case FGAD+16:             /* dir string gadget */
               ch = ddir[ strlen(ddir)-1 ];
               if(ch != ':' && ch != '/') strcat(ddir,"/");
               if ( pnam = (UBYTE *)dinit(ddir) )
                  notify(pnam);
               ActivateGadget(&gfil,wRq,0L);
            case FGAD+13:
               dir_flag = TRUE;       /* prop gadget */
               break;
            case FGAD+15:             /* Name gadget, OTAY gadget   */
            case FGAD+17:
               retval = ddef;         /* only returns filename, a little code
                                         could add ddir+ddef first */
            case FGAD+14:             /* Cancel gadget   */
               keepon = FALSE;
            case FGAD+18:
            case FGAD+19:break;       /* user definable string gadgets... */
            case FGAD+20:             /* PARENT gadget */
                if (stomp = rindex(ddir,'/'))
                  {
                   *stomp = NULL;
                   if (stomp = rindex(ddir,'/'))
                     { 
                      *stomp = NULL;
                      *(stomp+1) = NULL;
                      strcat(ddir,"/");
                     }
                   else if ( stomp = index(ddir,':')) 
                          *(stomp+1) = NULL;
                   RemoveGadget(wRq,&gdir);
                   AddGadget(wRq,&gdir,-1L);
                   RefreshGadgets(&gdir,wRq,0L);
                   if ( pnam = (UBYTE *)dinit(ddir) )
                     notify(pnam);
                   dir_flag = TRUE;     
                  }
          }
      }
   }
  FreeMem(FirstEntry,(ULONG)DBUFSIZ );
  FreeMem(dir_info,(ULONG)sizeof(struct FileInfoBlock));
  free_pdir();

  CloseWindowSafely(wRq);
  return(retval);
}

static free_pdir()
{
  if ( pdir )
    {
     UnLock(pdir);
     pdir = NL;
    }
}

/*
 *
 * convert 'int.' to right justified 'string' ( for file size display )
 *
 */ 

char  *itos(fred)
LONG  fred;
 {
   static char fredstring[6]; /* 6 chars. allows for up to 999999 Bytes...*/
   int          next = 5;
   
   if (!fred) fredstring[next--] = '0';
      
   while ((fred+9)/10)
      {      
      fredstring[next--] = fred % 10 + 0x30;
      fred /= 10;
      }
   while (next+1) fredstring[next--] = 0x20;/* ASCII <space> for left padding*/
   return(fredstring);
 }

/*****************************************************************
* dinit()
*   Initialize the fib for directory muck.  Null return
* is good, else return is a pointer to an error string 
*/

static UBYTE *dinit(subdir)
 UBYTE *subdir;
{
 extern long AvailMem();
 struct InfoData *info;
 ULONG           bytes = 0L; /*  Bytes Free on Drive:  */

   more = FALSE;
   curent = maxent = 0;
   cc_prop.VertBody = 0xFFFF;
   cc_prop.VertPot = 0; 	   /* start at begining of file list*/
   RefreshGadgets(&gprop,wRq,0L); 

   NextEntry = FirstEntry;      /* Allocate from here   */
   ListHead.next = NL;          /* Clear the boogie     */

   free_pdir();   /* Unlock any old lock... */

   if (! (pdir=(struct FileLock *)Lock(subdir,(ULONG)ACCESS_READ)) )
     return((UBYTE *)"Wrong Diskette?");

   if ( ! Examine(pdir, dir_info) )
     return((UBYTE *)"Wierd Disk Error");

   if ( dir_info->fib_DirEntryType < 0L )
     return((UBYTE *)"Bizzare Alert!!");

   if ( !strcmp(subdir,"RAM:") || !strcmp(subdir,"ram:"))
     {
      Forbid();
      bytes = ( AvailMem(MEMF_CHIP) + AvailMem(MEMF_FAST));
      Permit();
      sprintf(sbuff,"%ld",bytes);
     }
   else
     {
      info = (struct InfoData *)
                    AllocMem((ULONG)sizeof(struct InfoData),0L);
      if (Info(pdir,info))
      bytes = (info->id_NumBlocks - info->id_NumBlocksUsed) * info->id_BytesPerBlock;
      FreeMem(info,(long)sizeof(*info));
      sprintf(sbuff,"%ld",bytes);
     }
   bytext[0].IText = sbuff; /* my shadow and... */
   bytext[1].IText = sbuff; /* I... */
   SetAPen(wRp,2L);
   RectFill(wRp,209L,(ULONG)(RHGHT-17),270L,(ULONG)(RHGHT-9));
   PrintIText(wRp,&bytext[0],0L,0L);

   more = TRUE;
   return(dmore());
}


static UBYTE *dmore()
{
  FAST struct dirent   *p_D = NextEntry;
  FAST struct dirent   *ptr = (struct dirent *)&ListHead;
  FAST struct dirent   *plink;
  FAST TEXT            *p_mung;  
  FAST ULONG    i;

   if ( ! more )   return(NL);

   if ( ExNext( pdir, dir_info ) )
   {
      if ( (ULONG)p_D >=
         ((ULONG)FirstEntry + (ULONG)DBUFSIZ - (ULONG)sizeof(struct dirent)) )
        {
         more = FALSE;
         return((UBYTE *)"Directory Truncated!");
        }
         /* Here you can add a file/directory filter   */
         /* filename text string is at &p_D->dE[0]   */

      if ( p_D->isfile = ( dir_info->fib_DirEntryType < 0L ) )
         p_D->d_size = (LONG)(dir_info->fib_Size);

      p_mung = &p_D->dE[0];
      for ( i=0; i<FCHARS; i++)
         if ( ! (*p_mung++ = dir_info->fib_FileName[i]) )   break;

      i = (ULONG)p_mung;
      NextEntry = (struct dirent *)( (i+5L) & ~3L );

      for ( i=maxent++; i>=0; i--)
      {
       if ( ! (plink = ptr->next)  )   break;
       if ( alpha_lower(p_D,plink) )   break;
       ptr = plink;
      }
      p_D->next = plink;
      ptr->next = p_D;

      if(maxent > DENTS)
       {
        cc_prop.VertBody = ((DENTS * 0x10000) / maxent);
        RefreshGadgets(&gprop,wRq,0L); 
       }
      return(NL);
   }
   else return ( IoErr() == ERROR_NO_MORE_ENTRIES) ?
       (UBYTE *)(more = 0L) : (UBYTE *)"Error Reading Directory!!!";
}

/* dedicated alphabetizing function for dmore()   */

static alpha_lower(snew,sold)
   struct dirent *snew,*sold;
{
   FAST struct dirent *pnew = snew;
   FAST TEXT *ps1,*ps2, c,d;

   if ( pnew->isfile == sold->isfile)
     {
      ps1 = &pnew->dE[0];
      ps2 = &sold->dE[0];
      while ( (c=*ps1++) )
         {
          if ( c > (d=*ps2++) )   return(FALSE);
          else if ( c < d )      break;
         }
      return(TRUE);
     }
   return(pnew->isfile);
}   

/* Display directory stuff   */

static cxxx()
{
   FAST ULONG   i,new;
   FAST ULONG   x,y;
   FAST struct dirent *ohboy = (struct dirent *)&ListHead;

   new = curent;
   for ( i=0; i<new; i++)   ohboy = ohboy->next;
   SetBPen(wRp,2L);
   SetDrMd(wRp,JAM2);
   y = 13L;
   for (i=0; i<DENTS; i++)
     {
      x = 20L;
      y += 10;
      rname[i].NextText = 0;
      rname[i].IText = 0;
      rsize[i].IText = (UBYTE *)"      ";
      rname[i].LeftEdge = 0;
      if ( (new+i) < maxent )
        {
         ohboy = ohboy->next;
         rname[i].IText = &ohboy->dE[0];
        if ( ohboy->isfile )
            {                      
             rsize[i].IText = (UBYTE *)itos(ohboy->d_size);
             PrintIText(wRp,&rname[i],20L,y);
            }
         else
            {
             rname[i].LeftEdge = 48;
             PrintIText(wRp,&saydir,20L,y);
             PrintIText(wRp,&rname[i],20L,y);
             rname[i].NextText = &saydir;
            }
        x = wRp->cp_x;
        }
      if ( x < 214 )
        {
         SetAPen(wRp,2L);  
         RectFill(wRp,x,y,215L,(ULONG)(y+8L));
/*         RectFill(wRp,x,(long)(y-6),215L,(long)(y+1));*/
        }        
      PrintIText(wRp,&rsize[i],0L,y);
   }
}


/**************************************************
* rfnam()
*   Combines dir, plus name into dir   */

static rfnam(dir,fil_nam)
   UBYTE *dir,*fil_nam;
   {
   FAST UBYTE   *pdst = dir;
   FAST UBYTE   *psrc = fil_nam;
   FAST UBYTE   c = ':';

   while ( *pdst )
      c = *pdst++;
   if ( c != ':' && c != '/' )   *pdst++ = '/';

   while ( *pdst++ = *psrc++ )
      ;
   }

static struct IntuiText b_txt = {0,1,JAM2, 5,20,NL,NL,    NL};
static struct IntuiText p_txt = {0,1,JAM2, 5,3,NL,(UBYTE *)"OK", NL};

/****************************************************************
* notify(txt)                    
* Prompts for Yes/No response            
*/
static notify(txt)
   UBYTE *txt;
{
   b_txt.IText = txt;
   AutoRequest(wRq,&b_txt,0L,&p_txt,0L,0L,
      (ULONG)(IntuiTextLength(&b_txt)+50L),70L);
}
