/* WDIR
        Windowed Directory Command
        by Dave Haynie
        keyed by RRRobinson

        This command is designed to get a simple AmigaDOS
directory and display it in an AmigaDOS Window.  This is
intended as an example of using direct DOS calls.  All I/O
is done via AmigaDOS calls instead of using C standard
functions.  This was compiled successfully under Amiga
Systems 1.1 and 1.2, with the Lattice V3.03 C Compiler.
*/

/*======================================================================*/
/*      INCLUDES                                                        */

#include        <libraries/dosextens.h>
#include        <libraries/dos.h>

/*======================================================================*/
/*      External Declarations                                           */

extern  struct  FileHandle      *Open();        /* Opens a DOS File     */
extern  void    Close();                        /* Closes a DOS File    */
extern  struct  Filehandle      *Output();      /* Standard Output      */
extern  long    Write();                        /* Write a DOS File     */
extern  long    Read();                         /* Read from a DOS File */
extern  struct  FileLock        *Lock();        /* Opens a DOS Lock     */
extern  void    UnLock();                       /* Closes a DOS File    */
extern  BOOL    Examine();                      /* Gets a FIB from a Lock */
extern  BOOL    ExNext();                       /* Gets next FIB in a directory */
extern  long    IoErr();                        /* Specifies an I/O Error */

extern  BOOL    Chk_Abort();                    /* Eplicitly check for ^C */
extern  long    Enable_Abort;                   /* Allows explicit ^C checking */

/*======================================================================*/
/*      Program variables and constants                                 */

#define LL      80                              /* Lines across         */
#define HNUM    4                               /* Names per Line       */
#define VNUM    (8*HNUM)                        /* Names per screen     */

struct  FileHandle      *wind = NULL;           /* AmigaDOS Outout Window */
struct  FileInfoBlock   *fib  = NULL;           /* File Info Block      */
struct  FileLock        *dir  = NULL;           /* Locked AmigaDOS directory */

/*======================================================================*/
/*      Simple prompt for a return.                                     */

UBYTE   go_on(f)
struct  fileHandle      *f;
{
        char dummy;

        Write(f,"\n\2337mType RETURN to Continue\2330m",30L);
        Read(f,&dummy,1L);
        Write(f,"\233H\233J",4L);               /* Home and Clear Window */
        return (UBYTE) (0);
}

/*======================================================================*/
/*      Simple function to open everything cleanly.                     */

BOOL    StartUp(argc,argv)
int     argc;
char    *argv[];
{
        char    *dirname;                       /* Selected AmigaDOS directory */
        char    wname[108];                     /* Window Name          */

/*      First process the command line.  We want exactly one
        directory name specified, but a blank command line
        nicely defaults to the current directory.
        -----------------------------------------------------------     */

        if (argc == 1)
                dirname = "";
        else if (argc == 2 )
                dirname = argv[1];
        else {
                Write(Output(), "Usage: ",7L);
                Write(Output(), argv[0], strlen(argv[0]));
                Write(Output(), " [dirname]\n",11L);
                return FALSE;
        }


/*      Now we'll need a FIB, a File Info Block.  The
        DOS commands require the FIB to be aligned, so
        I AllocMem() it.
        -----------------------------------------------------------     */

        fib = (struct FileInfoBlock *)  AllocMem(sizeof(struct FileInfoBlock), 0);
        if (fib == NULL)
                return FALSE;

/*      We've got a possible directory name so we'll try to get
        a lock on it.  Once locked, we'll need the FIB for the
        directory.
        -----------------------------------------------------------     */

        dir = Lock(dirname, ACCESS_READ);
        if (dir == NULL || !Examine (dir, fib)) {
                Write(Output(), "Invalid Directory ",18L);
                Write(Output(), dirname,strlen(dirname));
                Write(Output(), " requested\n",11L);
                return FALSE;
        }
/*      now we create the file name for a console window and
        open it.  The return code is finally based on the
        success of this operation.
        -----------------------------------------------------------     */

        strcpy(wname, "CON:0/0/640/95/");
        strcat(wname, fib->fib_FileName);
        wind = Open(wname, MODE_OLDFILE);
        return (BOOL) (wind != NULL);
}

/*======================================================================*/
/*      Simple function to Close everything cleanly.                    */

        void    ShutDown()
        {
                if (wind)       Close(wind);
                if (dir)        UnLock(dir);
                if (fib)        FreeMem(fib, sizeof(struct fileInfoBlock));
                Exit (RETURN_ERROR);
        }

/*======================================================================*/
/*      The Main Program.                                               */

main(argc, argv)
int argc;
char *argv[];
{
        long    len;                            /* File name string length  */
        UBYTE   count = 0 ;                     /* Line count           */

/*      Make an attempt to open all the necessary things.
        -----------------------------------------------------------     */

        if (!StartUp(argc,argv))
                ShutDown();

/*      GOOD!, we're open.  Now Loop for files, until ExNext()
        falis AND IoErr() returns the appropriate error
        code, or we break out with ^C.
        -----------------------------------------------------------     */

        Enable_Abort = 0;

        while (ExNext(dir, fib) != 0 || IoErr() != ERROR_NO_MORE_ENTRIES) {

           if (fib->fib_DirEntryType > 0) {     /* If this entry is a Directory */
                Write(wind, "\2333m", 3L);      /* Turn Italics ON      */
           }
           len = strlen(fib->fib_FileName);
           Write(wind, fib->fib_FileName, len);                 /* Display the Entry name       */
           Write(wind, "\2330m                    ", 22-len);   /* Turn Italics OFF and pad remaining space */

           if (++count % HNUM == 0) {           /* If COUNT is an even multiple of HNIM */
                Write(wind, "\n",1L);
                if (count == VNUM) {
                        count = go_on(wind);
                }
           }
           if (Chk_Abort() ) {
                Write(Output(), "**BREAK\n",8L);
                ShutDown();
           }

        }    /* End of While      */


/*      The last on-screen prompt.
        -----------------------------------------------------------     */

        if (count != 0) {
                if (count % HNUM != 0) {
                        Write(wind, "\n",1L);
                }
                go_on(wind);
        }

/*      And we're DONE !
        -----------------------------------------------------------     */

        ShutDown();

}               /* End of MAIN       */
