/****************************************************************************
 *
 *  FileRequest() - File Name Requester
 *
 *  By Kevin Lee Clague
 *     Randy Finch
 *     Martin Hash
 *
 *  Copyright (C) 1987. 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.
 *
 *  LAST EDITED
 *     Martin Hash			15 Aug 1987
 *
 ***************************************************************************/

#include "df1:Requester.h"

extern struct IntuitionBase *IntuitionBase;

BOOL WaitRequester();
void InitFNR(), SetNewDrawer(), SetNewFile(), ListDir(), AttachList();
void ScrollList(), PotScrollList(), ThrowTrailing();
void ChangeDevice(), ToUpper();
char *strrchr();
struct ViewPort *ViewPortAddress();

#define STRINGSIZE  40
#define PATHNAMELEN 80
#define MIN(a,b)    ((a)<(b)?(a):(b))

struct Requester FileRequester;

UBYTE *FRFullPath;
struct IntuiMessage *message;
struct Window *FRWindow;

struct FileInfoBlock FileInfo;
USHORT FileCount;                     /* Number of files in current dir */
UBYTE  FileListEntry[MAXFILES][40];   /* File (dir) names in current dir */
TEXT   GetUser[PATHNAMELEN];
TEXT   spaces30[] = "                              ";
UBYTE *FileExt;

USHORT FirstFile;

/****************************************************************************
 *                The Gadget String
 ***************************************************************************/
/******************************
 * The File Name Gadget stuff *
 *****************************/
struct IntuiText FileText =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  -46,0,                  /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  "File",                 /* IText */
  NULL                    /* NextText */
  };

UBYTE FileName[STRINGSIZE];
UBYTE Backup[STRINGSIZE];
struct StringInfo FileString = {
    FileName,               /* Buffer */
    Backup,                 /* UndoBuffer */
    0,                       /* BufferPos */
    32,                      /* MaxChars  */
    0,                       /* DispPos */
    0,0,0,0,0,NULL,0,NULL    /* maintained by Intuition */
  };

struct Gadget FileGadget =
  { /* File string */
  NULL,                    /* NextGadget */
  67,113,                  /* LeftEdge, TopEdge */
  185,8,                   /* Width, Height */
  GADGHCOMP,               /* Flags */
  0,                       /* Activation */
  STRGADGET|REQGADGET,     /* GadgetType */
  NULL,                    /* GadgetRender */
  NULL,                    /* SelectRender */
  &FileText,               /* GadgetText */
  0,                       /* MutualExclude */
  (APTR)&FileString,             /* SpecialInfo */
  NULL,                    /* GadgetID */
  NULL                     /* UserData */
  };

/********************************
 * The Drawer Name Gadget stuff *
 *******************************/
struct IntuiText DrawerText =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  -62,0,                  /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  "Drawer:",              /* IText */
  NULL                    /* NextText */
  };

UBYTE DrawerName[PATHNAMELEN];
UBYTE Backup2[PATHNAMELEN];
struct StringInfo DrawerString = {
    DrawerName,             /* Buffer */
    Backup2,                /* UndoBuffer */
    0,                       /* BufferPos */
    PATHNAMELEN,                      /* MaxChars  */
    0,                       /* DispPos*/
    0,0,0,0,0,NULL,0,NULL    /* maintained by Intuition*/
  };

struct Gadget DrawerGadget =
  { /* Drawer string */
  &FileGadget,             /* NextGadget */
  67,98,                   /* LeftEdge, TopEdge */
  185,8,                   /* Width, Height */
  GADGHCOMP,               /* Flags */
  RELVERIFY,               /* Activation */
  STRGADGET|REQGADGET,     /* GadgetType */
  NULL,                    /* GadgetRender */
  NULL,                    /* SelectRender */
  &DrawerText,             /* GadgetText */
  0,                       /* MutualExclude */
  (APTR)&DrawerString,           /* SpecialInfo */
  DRAWERGADGET,            /* GadgetID */
  NULL                     /* UserData */
  };

/****************************************
 * The File list selection Gadget stuff *
 ***************************************/
UBYTE PickNames[8][STRINGSIZE];
struct IntuiText FileList[] =
  {
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[0][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[1][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[2][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[3][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[4][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[5][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[6][0],       /* IText */
    NULL                    /* NextText */
    },
    {
    0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
    0,0,                    /* LeftEdge,TopEdge */
    NULL,                   /* ITextFont */
    &PickNames[7][0],       /* IText */
    NULL                    /* NextText */
    }
  };

struct Gadget FileListGadget[] =
  {
    { /* File name selection 0 */
    &FileListGadget[1],      /* NextGadget */
    5,14,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[0],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE0GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 1 */
    &FileListGadget[2],      /* NextGadget */
    5,24,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[1],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE1GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 2 */
    &FileListGadget[3],      /* NextGadget */
    5,34,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[2],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE2GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 3 */
    &FileListGadget[4],      /* NextGadget */
    5,44,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[3],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE3GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 4 */
    &FileListGadget[5],      /* NextGadget */
    5,54,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[4],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE4GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 5 */
    &FileListGadget[6],      /* NextGadget */
    5,64,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[5],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE5GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 6 */
    &FileListGadget[7],      /* NextGadget */
    5,74,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[6],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE6GADGET,             /* GadgetID */
    NULL                     /* UserData */
    },
    { /* File name selection 7 */
    &DrawerGadget,           /* NextGadget */
    5,84,                    /* LeftEdge, TopEdge */
    240,8,                   /* Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY,               /* Activation */
    BOOLGADGET|REQGADGET,    /* GadgetType */
    NULL,                    /* GadgetRender */
    NULL,                    /* SelectRender */
    &FileList[7],            /* GadgetText */
    0,                       /* MutualExclude */
    NULL,                    /* SpecialInfo */
    FILE7GADGET,             /* GadgetID */
    NULL                     /* UserData */
    }
  };
/********************************
 * The Load Button gadget stuff *
 *******************************/
SHORT ButtonPoints1[] =
  {
  -2, 11,
  66, 11,
  66, -1
  };
struct Border ButtonBorder1 =
  {
  0,0,
  0,1,JAM1,
  3,
  &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, BackPen, DrawMode */
  0,0,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  NULL,                   /* IText */
  NULL                    /* NextText */
  };

struct Gadget LoadGadget =
  { /* Load button */
  &FileListGadget[0],      /* NextGadget */
  14,148,                  /* LeftEdge, TopEdge */
  64,8,                    /* Width, Height */
  GADGHCOMP,               /* Flags */
  GADGIMMEDIATE|ENDGADGET, /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &ButtonBorder0,   /* GadgetRender */
  NULL,                    /* SelectRender */
  &LoadText,               /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  LOADGADGET,              /* GadgetID */
  NULL                     /* UserData */
  };

/**********************************
 * The Cancel Button gadget stuff *
 *********************************/
struct IntuiText CancelText =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  0,0,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  " Cancel",               /* IText */
  NULL                    /* NextText */
  };

struct Gadget CancelGadget =
  { /* Cancel button */
  &LoadGadget,             /* NextGadget */
  187,148,                 /* LeftEdge, TopEdge */
  64,8,                    /* Width, Height */
  GADGHCOMP,               /* Flags */
  GADGIMMEDIATE|ENDGADGET, /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &ButtonBorder0,   /* GadgetRender */
  NULL,                    /* SelectRender */
  &CancelText,             /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  CANCELGADGET,            /* GadgetID */
  NULL                     /* UserData */
  };


/******************************************
 * The DF0:, DF1:, and User Button Gadget *
 ******************************************/

struct IntuiText DF0Text =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  0,0,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  "DF0:",                 /* IText */
  NULL                    /* NextText */
  };

struct IntuiText DF1Text =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  0,0,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  "DF1:",                 /* IText */
  NULL                    /* NextText */
  };

struct IntuiText UserText =
  {
  0,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  0,0,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  "HD:     ",             /* IText */
  NULL                    /* NextText */
  };

struct Gadget DFGadget[] =
  {
  {
  &CancelGadget,           /* NextGadget */
  14,130,                  /* LeftEdge, TopEdge */
  64,8,                    /* Width, Height */
  GADGHNONE,               /* Flags */
  RELVERIFY,               /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &ButtonBorder0,   /* GadgetRender */
  NULL,                    /* SelectRender */
  &DF0Text,                /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  DF0GADGET,               /* GadgetID */
  NULL                     /* UserData */
  },
  {
  &DFGadget[0],            /* NextGadget */
  101,130,                 /* LeftEdge, TopEdge */
  64,8,                    /* Width, Height */
  GADGHNONE,               /* Flags */
  RELVERIFY,               /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &ButtonBorder0,   /* GadgetRender */
  NULL,                    /* SelectRender */
  &DF1Text,                /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  DF1GADGET,               /* GadgetID */
  NULL                     /* UserData */
  },
  {
  &DFGadget[1],            /* NextGadget */
  187,130,                 /* LeftEdge, TopEdge */
  64,8,                    /* Width, Height */
  GADGHNONE,               /* Flags */
  RELVERIFY,               /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &ButtonBorder0,   /* GadgetRender */
  NULL,                    /* SelectRender */
  &UserText,               /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  USERGADGET,              /* GadgetID */
  NULL                     /* UserData */
  } };


/***********************************************
 * 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 */
  &DFGadget[2],            /* NextGadget */
  247,13,                  /* LeftEdge, TopEdge */
  12,15,                   /* Width, Height */
  GADGIMAGE|GADGHNONE,     /* Flags */
  GADGIMMEDIATE,           /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &UpArrow,         /* GadgetRender */
  NULL,                    /* SelectRender */
  NULL,                    /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  UPGADGET,                /* GadgetID */
  NULL                     /* UserData */
  };
/*************************************************
 * 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,               /* NextGadget */
  247,79,                  /* LeftEdge, TopEdge */
  12,15,                   /* Width, Height */
  GADGIMAGE|GADGHNONE,     /* Flags */
  GADGIMMEDIATE,           /* Activation */
  BOOLGADGET|REQGADGET,    /* GadgetType */
  (APTR) &DownArrow,       /* GadgetRender */
  NULL,                    /* SelectRender */
  NULL,                    /* GadgetText */
  0,                       /* MutualExclude */
  NULL,                    /* SpecialInfo */
  DOWNGADGET,              /* GadgetID */
  NULL                     /* UserData */
  };

/***************************************************
 * 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,             /* NextGadget */
  247,28,                  /* LeftEdge, TopEdge */
  14,50,                   /* Width, Height */
  GADGHNONE,               /* Flags */
  RELVERIFY,               /* Activation */
  PROPGADGET|REQGADGET,    /* GadgetType */
  (APTR) &KnobImage,       /* GadgetRender */
  NULL,                    /* SelectRender */
  NULL,                    /* GadgetText */
  0,                       /* MutualExclude */
  (APTR)&KnobInfo,               /* SpecialInfo */
  POTGADGET,               /* GadgetID */
  NULL                     /* UserData */
  };
/***************************************************************************
*                  Other Requester structures                              *
***************************************************************************/
struct IntuiText HeadingText =
  {
  2,1, JAM2,              /* FrontPen, BackPen, DrawMode */
  4,3,                    /* LeftEdge,TopEdge */
  NULL,                   /* ITextFont */
  NULL,                   /* IText */
  NULL                    /* NextText */
  };

SHORT Requester0Points[] = {
  2,1,
  261,1,
  261,162,
  2,162,
  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,window,FileExtension)
  UBYTE *FileType;
  UBYTE *Action;
  UBYTE *FullName;
  struct Window *window;
  UBYTE *FileExtension;
{
  char *StrPtr;
  BOOL   RetCode;
  struct ViewPort *viewport;
  struct ColorMap *colormap;
  int color0, color1, color2, comp0, comp1, count;

  window->Flags |= RMBTRAP;
  FRFullPath = FullName;
  FRWindow = window;
  FileExt = FileExtension;
  HeadingText.IText = FileType; /* Center requester title */
  HeadingText.LeftEdge = (256-IntuiTextLength(&HeadingText))/2;
  LoadText.IText = Action;

  InitFNR();

  if (StrPtr = strrchr( FRFullPath, '/' )) {	/* separate path */
     strcpy( FileString.Buffer, StrPtr+1 );
     *StrPtr = '\0';
  }
  else if (StrPtr = strrchr( FRFullPath, ':' )) {
     strcpy( FileString.Buffer, StrPtr+1 );
     *(StrPtr+1) = '\0';
  }
  else {
     *FileString.Buffer   = '\0';
     *DrawerString.Buffer = '\0';
     *FRFullPath = '\0';
  }
  strcpy( DrawerString.Buffer, FRFullPath );

  ListDir( FRFullPath );

  viewport = ViewPortAddress( window );
  colormap = viewport->ColorMap;
  count = 1<<(viewport->RasInfo->BitMap->Depth);
  color0 = GetRGB4( colormap, 0 );
  color1 = GetRGB4( colormap, 1 );
  color2 = GetRGB4( colormap, 2 );
  comp1 = GetRGB4( colormap, count-2 );
  comp0 = GetRGB4( colormap, count-1 );

  SetRGB4( viewport, 0, 0, 0, 0 );
  SetRGB4( viewport, 1, 15, 15, 15 );
  SetRGB4( viewport, 2, 15, 0, 0 );
  SetRGB4( viewport, count-2, 0, 0, 0 );
  SetRGB4( viewport, count-1, 15, 15, 15 );

  /* Put new user device in device gadget */
  strcpy(GetUser, FRFullPath);
  if (StrPtr = strrchr(GetUser, ':'))
     {
     *(StrPtr+1) = '\0';
     ToUpper(GetUser);
     if (strcmp(GetUser,DF0Text.IText) != 0 && strcmp(GetUser,DF1Text.IText) != 0 && strlen(GetUser) <= 8)
        strcpy(UserText.IText, GetUser);
     }
  Request(&FileRequester,FRWindow);
  RetCode = WaitRequester();         /* do everything till Cancel or Load */

  SetRGB4( viewport, 0, (color0>>8)&0xF, (color0>>4)&0xF, color0&0xF );
  SetRGB4( viewport, 1, (color1>>8)&0xF, (color1>>4)&0xF, color1&0xF );
  SetRGB4( viewport, 2, (color2>>8)&0xF, (color2>>4)&0xF, color2&0xF );
  SetRGB4( viewport, count-2, (comp1>>8)&0xF, (comp1>>4)&0xF, comp1&0xF );
  SetRGB4( viewport, count-1, (comp0>>8)&0xF, (comp0>>4)&0xF, comp0&0xF );
  window->Flags &= (0xFFFFFFFF^RMBTRAP);

  ThrowTrailing( FileString.Buffer );
  if (strlen( FileString.Buffer ) > 0 && RetCode) {
     if (FRFullPath[strlen(FRFullPath)-1] != ':')
        strcat( FRFullPath, "/" );
     strcat( FRFullPath, FileString.Buffer );
     return TRUE;
  }
  return FALSE;
} /* LoadRequest */

/*
 *  Init the file name requester
 */
void InitFNR()
{
  InitRequester(&FileRequester);
  FileRequester.LeftEdge  = 6;
  FileRequester.TopEdge   = 12;
  FileRequester.Width     = 264;
  FileRequester.Height    = 164;
  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(FRWindow->UserPort)) == 0L)
      {
      Wait(1L<<FRWindow->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 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(FRFullPath,DrawerString.Buffer);
                  SetNewFile(&FileGadget,"");
                  ListDir(DrawerString.Buffer);
                  break;
             case CHOICECLASS:             /* set the name in string gads */
                  SetNewFile( &FileGadget, gadget->GadgetText->IText );
                  break;
             case DEVICECLASS:             /* Device change */
                  ChangeDevice(gadget);
             }
      }
    }
  return((BOOL)(choice==LOAD));
} /* WaitRequester */

/*
 *  SetNewDrawer - Used Mouse to pick directory from selection list gadgets.
 */
void SetNewDrawer(Gadget,Text)
  struct Gadget *Gadget;
  UBYTE  *Text;
{
  SetNewFile(&FileGadget,"");          /* clear file name string */
  SetNewFile(Gadget,Text);             /* set new drawer into gadget */
  ListDir(FRFullPath);                 /* List new files into Sel List */
} /* SetNewDrawer */

/*
 *  SetNewFile - Copy text to gadget and refresh
*/
void SetNewFile(gadget,Text)
  struct Gadget *gadget;
  UBYTE  *Text;
{
  struct StringInfo *strinfo;

  if (strcmp(Text, spaces30) != 0)
    {
    ThrowTrailing(Text);           /* get rid of trailing blanks */
    strinfo = (struct StringInfo *)(gadget->SpecialInfo);
    strcpy(strinfo->Buffer,Text);
    RefreshGadgets(&DownGadget,FRWindow,&FileRequester);
    }
} /* SetNewFile */

/*
 *  ListDir - List the directory into array of string names.
 */
void ListDir(dir)
  char *dir;
{
  struct FileLock *my_lock, *Lock() ;
  char templist[STRINGSIZE];
  WORD i, j;

  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);
         FileCount++;
         ExNext(my_lock, &FileInfo);
      }
      UnLock(my_lock) ;
    }

    for (i = 0; i < FileCount-1; ++i)	/* sort alphabetically */
       for (j = i+1; j < FileCount; ++j)
          if (strcmp( FileListEntry[j], FileListEntry[i] ) < 0) {
             strcpy( templist, FileListEntry[i] );
             strcpy( FileListEntry[i], FileListEntry[j] );
             strcpy( FileListEntry[j], templist );
          }
  }
 
  AttachList(FirstFile);
  if (FileCount > 8)
    ModifyProp(&PotGadget,FRWindow,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,(ULONG)0xffff*8/FileCount);
  else
    ModifyProp(&PotGadget,FRWindow,&FileRequester,AUTOKNOB|FREEVERT|PROPBORDERLESS,0,0,0,0xffff);
} /* ListDir */

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

  for (Gadget = 0; Gadget <= 7 && Gadget+Start < FileCount; Gadget++)
    {
    strcpy(FileList[Gadget].IText,&FileListEntry[Start + Gadget][0]);
    strncat(FileList[Gadget].IText, spaces30, 30-strlen(FileList[Gadget].IText));
    }
  for (; Gadget <= 7; Gadget++)
    strcpy(FileList[Gadget].IText,spaces30);

  RefreshGadgets(&DownGadget,FRWindow,&FileRequester);
} /* AttachList */

/*
 *  ScrollList - Scroll the list up or down 1 file if possible
 */
void 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  = MIN(0xffff,((FirstFile<<16))/(FileCount-8));
  ModifyProp(&PotGadget,FRWindow,&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.
 */
void PotScrollList(gadget)
  struct Gadget *gadget;
{
  switch (gadget->GadgetID & GADGETNUM)
    {
    case POT:
         FirstFile = ((ULONG)(FileCount-8)*KnobInfo.VertPot+(1<<15)) >> 16;
         AttachList(FirstFile);
    }
} /* PotScrollList */

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

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

/*
 * ChangeDevice - Change to device chosen by buttons
*/
void ChangeDevice(gadget)
  struct Gadget *gadget;
  {
  UBYTE *text;

  text = DFGadget[gadget->GadgetID & GADGETNUM].GadgetText->IText;
  strcpy(FRFullPath, text);
  SetNewDrawer(&DrawerGadget, text);
  } /* ChangeDevice */

/*
 * ToUpper - Convert a string to all upper case
*/
void ToUpper(text)
  STRPTR text;
{
  ULONG i;

  for (i=0 ; i < strlen(text) ; i++)
     *(text+i) = toupper(*(text+i));  /* convert character */
}  /* ToUpper */
