/****************************************************************************
 *
 *  FileRequest() - File Name Requester
 *
 *  By Kevin Lee Clague
 *     408 Tortolla Way
 *     San Jose, Ca 95033
 *     408-258-9891       work 408-737-5481
 *
 *  Copyright (C) 1986. All rights reserved.
 *
 *  This program is freely distributable as long as this copyright notice
 *  is retained. It intended for personal, non-commercial use.  
 *
 *  This file name requester is modeled after Deluxe Paints file name
 *  requester. The dimensions/locations of all borders, gadgets and text were
 *  arrived at empirically. Besides being a great program, Deluxe Paint is a
 *  trade mark of Electronics Arts.
 *
 *  The knowledge on how to get at the entries in the directories was drawn
 *  from Mike (I'll be melow when I'm dead) Meyer's "Browser".
 *
 ***************************************************************************/

/***************************************************************************
 *
 *  Things to do:
 *    1. Dynamically allocate space for file name strings as they are gotten
 *       from the disk, rather than static allocation of them in arrays.
 *    2. Fence off intuition events while getting file names from disk
 *       directory (and put up the zz sleepy cloud in place of the arrow
 *       mouse cursor.)
 *    3. Be a little more diligent with my use of RefreshGadgets.
 *
 ***************************************************************************/

#include "Requester.h"
 
BOOL IsDir();
BOOL WaitRequester();

struct Requester FileRequester;

UBYTE *FullPath;
struct Window       *window;
struct IntuiMessage *message;

struct FileInfoBlock FileInfo;
USHORT FileCount;                     /* Number of files in current dir */
UBYTE  FileListEntry[MAXFILES][40];   /* File (dir) names in current dir */

USHORT FirstFile;

#define PATHNAMELEN 80

/****************************************************************************
 *                The Gadget String
 ***************************************************************************/
/******************************
 * The File Name Gadget stuff *
 *****************************/
struct IntuiText FileText =
  {
  0,1, JAM2,              /* frontpen, packpen, drawmode */
  -46,0,                  /* left,top */
  NULL,                   /* font */
  "File:",                /* text */
  NULL                    /* next */
  };

UBYTE FileName[40];
UBYTE Backup[40];
struct StringInfo FileString = {
    &FileName,               /* input buffer */
    &Backup,                 /* undo  buffer */
    0,                       /* Buffer position */
    32,                      /* buffer size  */
    0,                       /* disp position*/
    0,0,0,0,0,NULL,0,NULL    /* undo position*/
  };

SHORT DrawerPoints[] = {
    -2, -2,
    185,-2,
    185,10,
    -2, 10,
    -2, -2
    };
struct Border DrawerBorder = {
    0,0,
    0,1,JAM1,
    5,
    &DrawerPoints[0],
    NULL
  };

struct Gadget FileGadget =
  { /* File string */
  NULL,                    /* next gadget */
  67,113,                  /* location    */
  185,8,
  GADGHCOMP,               /* flags       */
  0,                       /* activation  */
  STRGADGET|REQGADGET,     /* type        */
  (APTR) &DrawerBorder,    /* rendering   */
  NULL,                    /* rendering   */
  &FileText,               /* text        */
  0,                       /* mutual exlcude */
  &FileString,             /* string info */
  NULL,                    /* gadget id   */
  NULL                     /* special info*/
  };

/********************************
 * The Drawer Name Gadget stuff *
 *******************************/
struct IntuiText DrawerText = 
  {
  0,1, JAM2,              /* frontpen, packpen, drawmode */
  -62,0,                  /* left,top */
  NULL,                   /* font */
  "Drawer:",              /* text */
  NULL                    /* next */
  };

UBYTE DrawerName[40];
struct StringInfo DrawerString = {
    &DrawerName,             /* input buffer */
    &Backup,                 /* undo  buffer */
    0,                       /* Buffer position */
    32,                      /* buffer size  */
    0,                       /* disp position*/
    0,0,0,0,0,NULL,0,NULL    /* undo position*/
  };

struct Gadget DrawerGadget =
  { /* Drawer string */
  &FileGadget,             /* next gadget */
  67,98,                   /* location    */
  185,8,
  GADGHCOMP,               /* flags       */
  RELVERIFY,               /* activation  */
  STRGADGET|REQGADGET,     /* type        */
  (APTR) &DrawerBorder,    /* rendering   */
  NULL,                    /* rendering   */
  &DrawerText,             /* text        */
  0,                       /* mutual exlcude */
  &DrawerString,           /* string info */
  DRAWERGADGET,            /* gadget id   */
  NULL                     /* special info*/
  };

/****************************************
 * The File list selection Gadget stuff *
 ***************************************/
UBYTE PickNames[8][40];
struct IntuiText FileList[] =
  {
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[0][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[1][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[2][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[3][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[4][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[5][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[6][0],       /* text */
    NULL                    /* next */
    },
    {
    0,1, JAM2,              /* frontpen, packpen, drawmode */
    0,0,                    /* left,top */
    NULL,                   /* font */
    &PickNames[7][0],       /* text */
    NULL                    /* next */
    }
  };

struct Gadget FileListGadget[] =
  {
    { /* File name selection 0 */
    &FileListGadget[1],      /* next gadget */
    5,14,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[0],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE0GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 1 */
    &FileListGadget[2],      /* next gadget */
    5,24,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[1],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE1GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 2 */
    &FileListGadget[3],      /* next gadget */
    5,34,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[2],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE2GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 3 */
    &FileListGadget[4],      /* next gadget */
    5,44,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[3],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE3GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 4 */
    &FileListGadget[5],      /* next gadget */
    5,54,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[4],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE4GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 5 */
    &FileListGadget[6],      /* next gadget */
    5,64,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[5],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE5GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 6 */
    &FileListGadget[7],      /* next gadget */
    5,74,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[6],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE6GADGET,             /* gadget id   */
    NULL                     /* special info*/
    },
    { /* File name selection 7 */
    &DrawerGadget,           /* next gadget */
    5,84,                    /* location    */
    244,8,
    GADGHNONE,               /* flags       */
    GADGIMMEDIATE,           /* activation  */
    BOOLGADGET|REQGADGET,    /* type        */
    NULL,                    /* rendering   */
    NULL,                    /* rendering   */
    &FileList[7],            /* text        */
    0,                       /* mutual exlcude */
    NULL,                    /* string info */
    FILE7GADGET,             /* gadget id   */
    NULL                     /* special info*/
    }
  };
/********************************
 * The Load Button gadget stuff *
 *******************************/
SHORT ButtonPoints1[] =
  {
  -4, -4,
  66, -4,
  66, 12,
  -4, 12,
  -4, -4
  };
struct Border ButtonBorder1 =
  {
  0,0,
  2,1,JAM1,
  5,
  &ButtonPoints1[0],
  NULL
  };
SHORT ButtonPoints0[] =
  {
  -3, -2,
  65, -2,
  65, 10,
  -3, 10,
  -3, -2
  };
struct Border ButtonBorder0 =
  {
  0,0,
  0,1,JAM1,
  5,
  &ButtonPoints0[0],
  &ButtonBorder1
  };

struct IntuiText LoadText =
  {
  0,1, JAM2,              /* frontpen, packpen, drawmode */
  0,0,                    /* left,top */
  NULL,                   /* font */
  NULL,                   /* text */
  NULL                    /* next */
  };

struct Gadget LoadGadget =
  { /* Load button */
  &FileListGadget[0],      /* next gadget */
  14,130,                  /* location    */
  64,8,
  GADGHCOMP,               /* flags       */
  GADGIMMEDIATE|ENDGADGET, /* activation  */
  BOOLGADGET|REQGADGET,    /* type        */
  (APTR) &ButtonBorder0,   /* rendering   */
  NULL,                    /* rendering   */
  &LoadText,               /* text        */
  0,                       /* mutual exlcude */
  NULL,                    /* string info */
  LOADGADGET,              /* gadget id   */
  NULL                     /* special info*/
  };

/**********************************
 * The Cancel Button gadget stuff *
 *********************************/
struct IntuiText CancelText =
  {
  0,1, JAM2,              /* frontpen, packpen, drawmode */
  0,0,                    /* left,top */
  NULL,                   /* font */
  "Cancel",               /* text */
  NULL                    /* next */
  };

struct Gadget CancelGadget =
  { /* Cancel button */
  &LoadGadget,             /* next gadget */
  187,130,                 /* location    */
  64,8,
  GADGHCOMP,               /* flags       */
  GADGIMMEDIATE|ENDGADGET, /* activation  */
  BOOLGADGET|REQGADGET,    /* type        */
  (APTR) &ButtonBorder0,   /* rendering   */
  NULL,                    /* rendering   */
  &CancelText,             /* text        */
  0,                       /* mutual exlcude */
  NULL,                    /* string info */
  CANCELGADGET,            /* gadget id   */
  NULL                     /* special info*/
  };

/***********************************************
 * The Scroll Selection List up (arrow) gadget *
 **********************************************/
UWORD UpArrowData[15] = {
   0xfffc,
   0xfcfc,
   0xf87c,
   0xf03c,
   0xe01c,
   0xc00c,
   0x8004,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfffc
};

struct Image UpArrow = 
  {
   0,0,
   14,
   14,
   1,
   &UpArrowData[0],
   0x1, 0x0,
   NULL
   };

struct Gadget UpGadget =
  { /* Up a file gadget */
  &CancelGadget,           /* next gadget */
  247,13,                  /* location    */
  12,15,
  GADGIMAGE|GADGHNONE,     /* flags       */
  GADGIMMEDIATE,           /* activation  */
  BOOLGADGET|REQGADGET,    /* type        */
  (APTR) &UpArrow,         /* rendering   */
  NULL,                    /* rendering   */
  NULL,                    /* text        */
  0,                       /* mutual exlcude */
  NULL,                    /* string info */
  UPGADGET,                /* gadget id   */
  NULL                     /* special info*/
  };
/*************************************************
 * The Scroll Selection List down (arrow) gadget *
 ************************************************/
UWORD DownArrowData[15] = {
   0xfffc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0xfcfc,
   0x8004,
   0xc00c,
   0xe01c,
   0xf03c,
   0xf87c,
   0xfcfc,
   0xfffc
};

struct Image DownArrow = 
  {
   0,0,
   14,
   14,
   1,
   &DownArrowData[0],
   0x1, 0x0,
   NULL
   };

struct Gadget DownGadget =
  { /* Down a file gadget */
  &UpGadget,               /* next gadget */
  247,79,                  /* location    */
  12,15,
  GADGIMAGE|GADGHNONE,     /* flags       */
  GADGIMMEDIATE,           /* activation  */
  BOOLGADGET|REQGADGET,    /* type        */
  (APTR) &DownArrow,       /* rendering   */
  NULL,                    /* rendering   */
  NULL,                    /* text        */
  0,                       /* mutual exlcude */
  NULL,                    /* string info */
  DOWNGADGET,              /* gadget id   */
  NULL                     /* special info*/
  };

/***************************************************
 * The Scroll Selection list up down Potentiometer *
 **************************************************/
struct PropInfo KnobInfo =
  {
  AUTOKNOB | FREEVERT | PROPBORDERLESS,
  0,
  0, /* VertPot */
  0,
  0x7fff, /* VertBody */
  0,0,0,0,0,0
  };

struct Image KnobImage =
  {
  0,0,
  0,0,0,
  NULL,
  0,0,
  NULL
  };

struct Gadget PotGadget =
  { /* Potentiometer file gadget */
  &DownGadget,             /* next gadget */
  247,28,                  /* location    */
  14,50,
  GADGHNONE,               /* flags       */
  RELVERIFY,               /* activation  */
  PROPGADGET|REQGADGET,    /* type        */
  (APTR) &KnobImage,       /* rendering   */
  NULL,                    /* rendering   */
  NULL,                    /* text        */
  0,                       /* mutual exlcude */
  &KnobInfo,               /* string info */
  POTGADGET,               /* gadget id   */
  NULL                     /* special info*/
  };
/***************************************************************************
*                  Other Requester structures                              *
***************************************************************************/
struct IntuiText HeadingText =
  {
  2,1, JAM2,              /* frontpen, packpen, drawmode */
  4,3,                    /* left,top */
  NULL,                   /* font */
  NULL,                   /* text */
  NULL                    /* next */
  };

SHORT Requester0Points[] = {
  2,1,
  261,1,
  261,144,
  2,144,
  2,1
  };
struct Border Requester0Border = {
  0,0,
  0,1,JAM1,
  5,
  &Requester0Points[0],
  NULL
  };

SHORT Requester1Points[] = {
  2,12,
  261,12
  };
struct Border Requester1Border = {
  0,0,
  0,1,JAM1,
  2,
  &Requester1Points[0],
  &Requester0Border
  };

SHORT Requester2Points[] = {
  2,93,
  261,93
  };
struct Border Requester2Border = {
  0,0,
  0,1,JAM1,
  2,
  &Requester2Points[0],
  &Requester1Border
  };

SHORT Requester3Points[] = {
  246,12,
  246,93,
  246,78,
  261,78,
  261,27,
  247,27
  };
struct Border Requester3Border = {
  0,0,
  0,1,JAM1,
  6,
  &Requester3Points[0],
  &Requester2Border
  };

/****************************************************************************
 *                     The Code part of the requester
 ***************************************************************************/
BOOL FileRequest(FileType,Action,FullName,ReqWindow)
  UBYTE *FileType;
  UBYTE *Action;
  UBYTE *FullName;
  struct Window *ReqWindow;
{
  UBYTE *StrPtr;
  BOOL   RetCode;

  window = ReqWindow;           /* make pointer to window and name global */
  FullPath = FullName;
  HeadingText.IText = FileType; /* Center requester title */
  HeadingText.LeftEdge = (256-IntuiTextLength(&HeadingText))/2;
  LoadText.IText = Action;

  InitFNR();

  /* Separate the path from the file name. Set the file name in the gadget */
  if (StrPtr = rindex(FullName,'/'))
    {
    strcpy(FileString.Buffer,StrPtr + 1);
    *StrPtr = '\0';
    }
  else
    if (StrPtr = rindex(FullName,':'))
      {
      strcpy(FileString.Buffer,StrPtr + 1);
      *(StrPtr+1) = '\0';
      }
    else
      {
      *FileString.Buffer   = '\0';
      *DrawerString.Buffer = '\0';
      *FullName = '\0';
      }
  /* Separate the last dir in path and put it in drawer gadget */
  if (StrPtr = rindex(FullName,'/'))
    strcpy(DrawerString.Buffer,StrPtr + 1);
  else
    if (StrPtr = rindex(FullName,':'))
      if (*(StrPtr+1))
        strcpy(DrawerString.Buffer,StrPtr + 1);
      else
        strcpy(DrawerString.Buffer,FullName);
    else
      *DrawerString.Buffer = '\0';

  /* Put up the requester and list the dir into it */ 
  Request(&FileRequester,window);
  ListDir(FullName);
  SetNewFile(&FileGadget,FileString.Buffer); /* why do I have to do this? */
  SetNewFile(&DrawerGadget,DrawerString.Buffer);

  RetCode = WaitRequester();         /* do everything till Cancel or Load */

  /* Put file name and path back together */
  if (FullName[strlen(FullName)-1] != ':')
    strcat(FullName,"/");
  strcat(FullName,FileString.Buffer);
  return(RetCode);
} /* LoadRequest */

/*
 *  Init the file name requester
 */
InitFNR()
{
  InitRequester(&FileRequester);
  FileRequester.LeftEdge  = 6;
  FileRequester.TopEdge   = 12;
  FileRequester.Width     = 264;
  FileRequester.Height    = 146;
  FileRequester.ReqGadget = &PotGadget;
  FileRequester.ReqText   = &HeadingText;
  FileRequester.BackFill  = 1;
  FileRequester.Flags     = 0;
  FileRequester.ReqBorder = &Requester3Border;
} /* InitFNR */

/*
 *  WaitRequester - List dirs, scroll, and set drawer and file strings until
 *                  one of the LOAD(SAVE) or CANCEL buttons pushed.
 */
BOOL WaitRequester()
{
  ULONG  class = GADGETDOWN;
  USHORT choice = CANCELGADGET;
  struct Gadget *gadget;

  while (class != REQCLEAR)
    {
    if ((message=(struct IntuiMessage *) GetMsg(window->UserPort)) == 0L)
      {
      Wait(1L<<window->UserPort->mp_SigBit);
      continue;
      }
    class  = message->Class;
    gadget = (struct Gadget *) message->IAddress;
    ReplyMsg(message);
    switch (class)
      {
      case GADGETDOWN:
           switch (gadget->GadgetID >> CLASSBITS)
             {
             case UPDOWNCLASS:
                  ScrollList(gadget);      /* scroll up/down 1 file */
                  break;
             case CHOICECLASS:             /* set the name in string gads */
                  if (IsDir(gadget->GadgetText->IText))
                    SetNewDrawer(&DrawerGadget,gadget->GadgetText->IText);
                  else
                    SetNewFile(&FileGadget,gadget->GadgetText->IText);
                  break;
             case BUTTONCLASS:             /* LOAD or CANCEL */
                  choice = gadget->GadgetID & GADGETNUM;
             }
      case GADGETUP:
           switch (gadget->GadgetID >> CLASSBITS)
             {
             case UPDOWNCLASS:             /* Potentiometer scroll */
                  PotScrollList(gadget);
                  break;
             case STRINGCLASS:             /* They typed drawer name in */
                  ThrowTrailing(DrawerString.Buffer);
                  strcpy(FullPath,DrawerString.Buffer);
                  SetNewFile(&FileGadget,"");
                  ListDir(DrawerString.Buffer);
             }
      }
    }
  return(choice==LOAD);
} /* WaitRequester */

/*
 *  SetNewDrawer - Used Mouse to pick directory from selection list gadgets.
 */ 
SetNewDrawer(Gadget,Text)
  struct Gadget *Gadget;
  UBYTE  *Text;
{
  SetNewFile(&FileGadget,"");              /* clear file name string */
  SetNewFile(Gadget,Text);                 /* set new drawer into gadget */
  if (FullPath[strlen(FullPath)-1] != ':') /* make new path */
    strncat(FullPath,"/",PATHNAMELEN);
  strncat(FullPath,Text,PATHNAMELEN);
  ListDir(FullPath);                       /* List new files into Sel List */
} /* SetNewDrawer */

/*
 *  SetNewFile - Have to remove gadgets change strings and add them */
SetNewFile(Gadget,Text)
  struct Gadget *Gadget;
  UBYTE  *Text;
{
  USHORT Pos, RemoveGadget();

  if (Text[0] != ' ')
    {
    Pos = RemoveGadget(window,Gadget);
    ThrowTrailing(Text);                    /* get rid of trailing blanks */
    strcpy(Gadget->SpecialInfo->Buffer,Text);
    AddGadget(window,Gadget,Pos);
    RefreshGadgets(&DownGadget,window,&FileRequester);
    }
} /* SetNewFile */

/*
 *  ListDir - List the directory into array of string names.
 */
ListDir(dir)
  char *dir;
{
  struct FileLock *my_lock, *Lock() ;

  FileCount = 0;
  FirstFile = 0;

  if ((my_lock = Lock(dir, ACCESS_READ)) != NULL)
    {
    if (Examine(my_lock, &FileInfo))
      {
      ExNext(my_lock, &FileInfo);

      while (IoErr() != ERROR_NO_MORE_ENTRIES && FileCount < MAXFILES)
        {
        strcpy(&FileListEntry[FileCount][0], FileInfo.fib_FileName);
        if (FileInfo.fib_DirEntryType > 0)
          strcat(&FileListEntry[FileCount][0]," (dir)");
        FileCount++;
        ExNext(my_lock, &FileInfo);
        }
      UnLock(my_lock) ;
      }
    }
  AttachList(FirstFile);
  if (FileCount > 8)
    ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,0xffff/(FileCount-6)*8);
  else
    ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,0xffff);
} /* ListDir */

/*
 *  AttachList - Attach list of file (directory) names to Selection gadgets
 */
AttachList(Start)
  USHORT Start;
{
  USHORT Gadget;
  USHORT Pos, RemoveGadget();

  for (Gadget = 0; Gadget <= 7 && Gadget+Start < FileCount; Gadget++)
    {
    Pos = RemoveGadget(window,&FileListGadget[Gadget]);
    strcpy(FileList[Gadget].IText,&FileListEntry[Start + Gadget][0]);
    strncat(FileList[Gadget].IText,"                                ",24-strlen(FileList[Gadget].IText));
    AddGadget(window,&FileListGadget[Gadget],Pos);
    }
  for (; Gadget <= 7; Gadget++)
    {
    Pos = RemoveGadget(window,&FileListGadget[Gadget]);
    strncpy(FileList[Gadget].IText,"                                ",24);
    AddGadget(window,&FileListGadget[Gadget],Pos);
    }
  RefreshGadgets(&DownGadget,window,&FileRequester);
} /* AttachList */

/*
 *  ScrollList - Scroll the list up or down 1 file if possible
 */
ScrollList(gadget)
  struct Gadget *gadget;
{
  ULONG VertPot = 0;

  switch(gadget->GadgetID & GADGETNUM)
    {
    case DOWN:
         if (FileCount > FirstFile + 8)
           ++FirstFile;
         break;
    case UP:
         if (FirstFile > 0)
           --FirstFile;
    }
  if (FileCount > 8)
    VertPot  = 0xffff/(FileCount-6)*FirstFile;
  ModifyProp(&PotGadget,window,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,VertPot,0,KnobInfo.VertBody);
  AttachList(FirstFile);
} /* ScrollList */

/*
 *  PotScrollList - Calculate the file number from Pot value and attach
 *                  names to Selector List gadgets.
 */
PotScrollList(gadget)
  struct Gadget *gadget;
{
  switch (gadget->GadgetID & GADGETNUM)
    {
    case POT:
         FirstFile = (FileCount-6)*KnobInfo.VertPot >> 16;
         AttachList(FirstFile);
    }
} /* PotScrollList */

/*
 *  IsDir - Simple minded routine to find " (dir)" in file name 
 */
BOOL IsDir(Name)
  UBYTE *Name;
{
  UBYTE *Dir;
  if (Dir = rindex(Name,'('))
    if (strcmp(Dir,"(dir)"))
      {
      Dir[0] = '\0';
      ThrowTrailing(Name);
      return(TRUE);
      }
    else
      return(FALSE);
  else
    return(FALSE);
} /* IsDir */

/*
 *  ThrowTrailing - Remove trailing blanks from string
 */
ThrowTrailing(String)
  UBYTE *String;
{
  SHORT I;

  I = strlen(String) - 1;
  while (String[I] == ' ' && I > 0)
    String[I--] = '\0';
} /* ThrowTrailing */
