[comp.sources.amiga] v89i049: flist - scrollable cli and directory lister v1.2, Part01/03

page@swan.ulowell.edu (Bob Page) (03/16/89)

Submitted-by: alliant!mistress!berry (Steve -Raz- Berry)
Posting-number: Volume 89, Issue 49
Archive-name: workbench/flist12.1

Flist is a scrollable interactive CLI and list environment. I wrote it
because the Dirutils were too inflexible for my tastes, and the CLI doesn't
have a scroll bar. There are tons of features, some of which are:

    * Support for both the Workbench or the CLI.
    * Change directory and parent directory.
    * Delete file or directory.
    * Sort list by name, time, file size, day or pattern.
    * ARP filerequestor for changing directory across devices.
    * Help synopsis via the Help key.
    * Even an AREXX port.

and much, much more.  The NULL: device handler which although not
required, is heavily recommended.

Written by Stephen (Raz) Berry. Comments and suggestions are most welcome.
This is Version 1.2 , Many additions and changes since 1.1.

If you have any comments, additions or bug reports please forward them to
BIX:    razberry
UUCP:   ...alliant!mistress!amiga

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	Flist.doc
#	arpdos.asyncrun
#	arpdos.c
#	display.c
#	dos.c
#	errout.c
#	fl.flex
#	flist.c
#	flist.h
#	flist.icon.c
#	flist.icon.uu
#	help.c
#	iconify.c
#	iconify.h
#	makefile
#	misc.c
# This archive created: Wed Mar 15 12:11:39 1989
cat << \SHAR_EOF > Flist.doc
NAME

    flist - file lister and sorting utility

SYNOPSIS

    flist [directory] [FROM file] [?]

DESCRIPTION

    Flist will display files as given on the command line, or if there
    are no arguments the current directory. Flist allows  commands to 
    be executed as if they were typed at a CLI. The list of files may
    be sorted by name, time, size or by a pattern. Most of flist's commands
    are control sequences as defined below.

    You may also specify the name of a file that contains file names to 
    be displayed by flist.

    Control sequences are indicated by the '^' character preceding an
    uppercase letter. To invoke the command from flist it is not necessary
    to capitilize the letter. You may also use the Menu shortcuts, which
    for the most part follow the same lettering scheme as the control 
    sequences (but check first).

    ^A - Invoke the ARP filerequestor. The ARP filerequestor will appear on
    the flist screen starting at the RAM: directory. All that is required
    is for the user to select a directory for flist to display. By clicking
    on the right mouse button, you can get a list of devices in the system.
    When the directory that is desired is displayed by the requestor, then
    select the OK button. If you want to abort the operation then select
    the CANCEL button.

    ^C - Abort flist. If you want to terminate flist from the keyboard,
    typing control-c will bring up a requestor to make sure that this is
    what you want to do. (HINT: hitting A-v will select the OK button)

    ^D - Change directory. (Refer to the diagram below) To change directory
    place the cursor opposite a 'Dir' entry in flist using the cursor keys
    (input area 6). Typing control-d at this time will change directory 
    to the left (Directory1) of the input area.


    ---------------------------------------------------------------------
    | Current directory   Files = 10                                    |
    ---------------------------------------------------------------------
    | filename1     |                   | date  time    filesize        |
    | filename2     |                   | date  time    filesize        |
    | filename3     |                   | date  time    filesize        |
    | filename4     |                   | date  time    filesize        |
    | filename5     |                   | date  time    filesize        |
    | Directory1    | ^D                | date  time     Dir            |
    | filename7     |                   | date  time    filesize        |
    | filename8     |                   | date  time    filesize        |
    | filename9     |                   | date  time    filesize        |
    | filename10    |                   | date  time    filesize        |
                        ^^input area

and so on...

    ^K - Kill (delete) file. By placing the cursor to the right of the filename
    that is to be deleted (also directories) and typing control-k, the 
    filename will be deleted from the media.
    
    ^L - Restore screen. This command redraws the entire screen. It also
    resets all the internal pointers to the top of the list.

    ^N - Make new directory. A string requestor will appear, prompting
    you to enter the name of the new directory. Hitting return with
    no entry in the requestor will do nothing.

    ^P - Get parent directory. Typing the sequence control-p will force
    flist to go up the file structure one level.

    ^R - Rename file/directory. A string requestor will prompt you to enter
    the new file. The cursor will continue to be displayed to indicate the
    file that is to be changed. Hitting return with no entry in the requestor
    will do nothing.

    ^S - Sort the filenames and directories alphabetically.

    ^Z - Sort the filenames by size. Directories will be listed first.

    ^Y - Sort the filenames by the day created.

    ^T - Sort the filenames and directories by creation TIME.

    ^O - Sort the filenames by pattern. A string requestor will promt you
    to enter the pattern to sort the current list by. Hitting return with
    no entry in the requestor will do nothing. Entering a pattern will
    exclude all entries in the list except those that match the pattern.
    Patterns may be standard AmigaDOS or ARP wildcards.

    ^G - Re-get the current directory. Useful if you move or sort the
    files, and you want Flist to be operating on current information.

    ^U - Erase the contents of the current line and place the cursor at 
    the beginning of the input area.
    
    ^X - Invoke an Flist AREXX macro. A string requestor will prompt you
    to enter the macro name. Hitting return with no entry in the requestor
    will do nothing.

    Help key - Hitting the help key will give you a synopsis of the 
    keyboard control commands. Type any key on the main keyboard (make 
    sure the help window is activated) to get rid of the help window.

    SHIFT-UP - Holding the shift key down and pressing the up arrow key
    will move the list up by 10 lines (if possible).

    SHIFT-DOWN - Holding the shift key down and pressing the down arrow key
    will move the list down by 10 lines (if possible).

    SHIFT-LEFT - Holding the shift key down and pressing the left arrow key
    will move the cursor to the first character on the typed line.

    SHIFT-RIGHT - Holding the shift key down and pressing the right arrow key
    will move the cursor to the last character on the typed line.

    INPUT AREA:

        The input area provides a powerful tool for the lazy typist (me).
        As an example, say you want to copy two files to another directory.
        First type the command 'copy ' on any line, then place the cursor 
        opposite the first file to copy (using the up and down arrow keys)
        and then press the Esc key. The file name will be inserted into the 
        input area. Then to get the second file name, move the cursor again
        to the line opposite the second file name and press the Esc key again.
        Then type the volume or directory path for the files destination and 
        hit return to execute the command. Flist will update the line/screen
        as the cursor moves up or down the display.

    If the command is larger than the input area, then Flist will scroll
    up to 90 characters to fit the input into the display.

AmigaDOS SUPPORT:

    Flist will execute any command that is typed in the input area
    and in the current search path. To execute a command, type it in
    with the correct path information, and hit return. Flist will open
    a window for I/O (for those commands that require output or an inter-
    active stream) and ask for you to hit return when the command has
    finished execution.

    Many of the most usefull operations that can be performed on a directory
    are included as standard functions in Flist. It is adviseable to use
    these features instead of bypassing Flist and executing the command 
    directly. In this way you can always be sure that list of files that are
    displayed represent the true state of the directory. If you perform an
    operation that does change the state of the directory, such as moving
    a file to another directory, typing ^G (re-get directory) will re-initial-
    ize the directory list.

AREXX SUPPORT:

    To initiate an Flist/AREXX macro program, select 'Execute REXX' from 
    the menu. Or 'Ae' (left or right amiga and 'e') or even ^X (control-x)
    to invoke the string requestor. The string requestor will prompt you 
    to enter the macro name. If you are in the directory containing the 
    supplied 'fl.flex' example, all you need type in the requestor is:

        'fl' and the return key (don't type the single quotes).
        
    You NEVER have to type the extension '.flex' when invoking a macro.

    Flist supports the following commands from the AREXX port. They are:

    'sort s'    - sort alphabetically.
    'sort z'    - sort by size.
    'sort t'    - sort by creation TIME.
    'sort o'    - sort by pattern.
    'sort y'    - sort by day.
    'iconify'   - iconify Flist.
    'end'       - tell Flist to stop listening to AREXX.
    'parent'    - get the parent directory.
    'redraw'    - redraw the screen.
    'reget'     - reget the current directory.
    'request'   - Bring up the ARP filerequestor.
    'makedir'   - make a new directory.
    'changedir "dirname"' - change to "dirname" directory.

    A more extensive command set is planned for the future.

    An Flist/AREXX macro must have the extension '.flex'.

    An Flist/AREXX macro must reside either in the current directory
    or the REXX: logical directory.

    The line 'address "flport"' must preface any flist commands.

    If for some reason Flist is stuck waiting for a command from REXX
    you can type this line (exactly) in another CLI to break the deadlock:

        rx "address 'flport' 'end'"

    See the supplied 'fl.flex' program for an example.

AUTHOR

    A lot of the code in Flist came from the public domain. That is the
    primary reason Flist is PD, it's my way of saying thanks! The various
    authors whose code fragments I borrowed are:
    
    Leo Schwab          -   iconify routines.
    W.G.J. Langeveld    -   PathName routines.
    Carolyn Schnepper   -   code stolen from timerwin.c

    My name is:  Steve (Raz) Berry. 

 I can be reached at:

    The Checkered Ball
    A-7 Sinai Circle
    Chelmsford, Ma. 01824
    c/o Steve (Raz) Berry

    BIX: razberry
    UUCP: ...alliant!mistress!amiga

    This is not a Shareware product. But don't let that stop you from sending
    cash!
SHAR_EOF
cat << \SHAR_EOF > arpdos.asyncrun
/* 
**      This module is the workhorse of Flist.
**      It is here that the commands typed in by the user are:
**
**      a: Scanned for special commands
**      b: replaced for filename expansion
**      c: prepped for ASyncRun
**      d: Run as a Task.
**
*/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/tasks.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <devices/console.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include "libraries/arpbase.h"
#include "flist.h"

struct ZombieMsg zombie;
struct ProcessControlBlock PCB;

/* Some external variables here */

extern struct Window *winptr;
extern int errno;

#define PCB_SETS PRF_SAVEIO|PRF_INTERACTIVE

long DoDOS(str)
char *str;
{
        long ret;

        if (str[0] != 0) {
                ret = spawnproc(str);
                if (!ret)
                        DisplayBeep(NULL);
        }
}

long spawnproc(str)
char *str;
{
        long i, j, ret;
        char command[90], args[90], buf[90];
        struct ZombieMsg *reply;
        struct MsgPort *port;
        struct FileHandle *fh;
                
        port = winptr->UserPort;

        fh = Open("CON:0/0/640/80/Flist at Work",MODE_NEWFILE);
        if (fh == NULL) {
                auto_req(" I can't seem to Open CON:");
                return FALSE;
        }

        zombie.zm_ExecMessage.mn_ReplyPort = port;
        
        PCB.pcb_StackSize = 10000;      /* Maybe this should be bigger? */
        PCB.pcb_Pri = 0;                /* Everybody runs at 0 */
        PCB.pcb_Control = PCB_SETS;
        PCB.pcb_TrapCode = NULL;        /* Use the defaults */
        PCB.pcb_Input = fh;
        PCB.pcb_Output = fh;
        PCB.pcb_LoadedCode = NULL;
        PCB.pcb_LastGasp = &zombie;     /* I want to be told when the 
                                           process dies */
        PCB.pcb_WBProcess = NULL;
        PCB.pcb_Console.pcb_SplatFile = fh;
        PCB.pcb_Console.pcb_ConName = NULL;

        for(i=0;str[i] != ' ' && str[i] != '\0' && i < 89;i++)
                        command[i] = str[i];

        command[i] = 0;

        /* Now if this isn't weird syntax, I don't know what is */

        if (str[i] == '\0') {
                args[0] = '\n';
                args[1] = '\0';
        } else {
                ++i;
                for(j=0;str[j+i] != '\0' && (j-i < 89);j++)
                                args[j] = str[j+i];
                args[j] = '\0';
        }

#ifdef DEBUG
        sprintf(&buf[0],"Sending -%s- to Execute.",str);
        SetWindowTitles(winptr,0L,buf);
#endif
   /*     ret = ASyncRun(&command[0], &args[0], &PCB); */
   
        ret = Execute(str,NULL,fh);
        Delay(30L);
        
        if (!ret){
                sprintf(&buf[0],"*** ERROR *** Execute returns - %d", IoErr());
                SetWindowTitles(winptr,0L,buf);
                DisplayBeep(NULL);
                Close(fh);
                return FALSE;
        } else {
/*                reply = (struct ZombieMsg *)WaitPort(port); */

                /* Wait for the user to terminate the window */

                ret = Read(fh, buf, 1L);
                sprintf(&buf[0]," Task died with return of %d", ret);
                SetWindowTitles(winptr,0L,buf);
                Delay(30); 
                Close(fh);
        }
}SHAR_EOF
cat << \SHAR_EOF > arpdos.c
/* 
        This module is the workhorse of Flist.
        It is here that the commands typed in by the user are:
  
        a: Scanned for special commands
        b: replaced for filename expansion
        c: prepped for ASyncRun
        d: Run as a Task.
  
*/

#include <stdio.h>
#include "flist.h"

/* Some external variables here */

extern struct Window *winptr;
extern int errno;
extern struct FileLock *lock;
extern long mousey;

#define PCB_SETS PRF_SAVEIO|PRF_INTERACTIVE

long DoDOS(str)
char *str;
{
    long ret;

    if (str[0] != 0) {
            ret = spawnproc(str);
            if (!ret)
                    DisplayBeep(NULL);
    }
    return ret;
}

long spawnproc(str)
char *str;
{
        long i, j, ret, ret1, pnt;
        char command[90], args[90], buf[1000], path[1000];
        struct FileHandle *fh;

    /*  In case your wondering, I'm trying to put the window under the 
        mouse. Why? Because I want to make it easy to kill it later! */

        i = (mousey > 119) ? 120: mousey;

        sprintf(buf,"CON:0/%d/640/80/Flist at Work", i);
        fh = Open(buf,MODE_NEWFILE);
        if (fh == NULL) {
                auto_req(" I can't seem to Open CON:");
                return FALSE;
        }

/*  Here be the LARGEST Kluge I have ever run across in AmigaDOS...
    Execute() must be fed the command 'cd current.directory' as part
    of the string, if you expect to be executing out of the current
    directory that is! */

        PathName(lock, path);
        strcpy(buf, "cd \"");
        strcat(buf, path);
        pnt = strlen(buf);
        strcat(buf, "\"\n");
        strcat(buf, str); 

#ifdef DEBUG
        sprintf(path,"Sending -%s- to Execute.",buf);
        SetWindowTitles(winptr,-1L,path);
#endif

        ret = Execute(buf,NULL,fh);
        
        if (!ret){
#ifdef DEBUG 
                sprintf(&buf[0],"*** ERROR *** Execute returns - %ld", IoErr());
                SetWindowTitles(winptr,-1L,buf);
#endif
                DisplayBeep(NULL);
                Close(fh);
                return FALSE;
        } else {

        /* Wait for the user to terminate the window */

                buf[0] = 0x9b;  buf[1] = 0x34;
                buf[2] = 0x30;  buf[3] = 0x3b;
                buf[4] = 0x33;  buf[5] = 0x33;
                buf[6] = 0x6d;  buf[7] = 0x0;
                strcat(buf, " Hit return to continue"); 
                Write(fh, buf, strlen(buf));
                ret1 = Read(fh, buf, 1L);
                Close(fh);
        }
        return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > display.c
/* 
    This module contain all of the routines that interface directly with 
    the display.

    Written by Steve (Raz) Berry.
*/

#include "flist.h"
#include <libraries/arpbase.h>
#include <stdio.h>

UWORD coltbl[8] = {
    0x047, /* background color */
    0xBBB, /* title text, inutuition boarders */
    0xB15, /* gadget, title bar */
    0x09B, /* Auto text */
    0x0a0, /* Auto text */
    0xC97, /* screen text */
    0xfff, /* gadget selected*/
    0x000  /* cursor */
};

static struct Image   cc_img;
static struct PropInfo   cc_prop = {AUTOKNOB | FREEVERT, 0,0, 0,0x1000,0,0,0,0,0,0 };
struct Gadget pg = { NL,RWDTH-28,20,15,170,      /* Scroll Bar   */
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE, PROPGADGET,
    (APTR)&cc_img,NL,NL,NL,(APTR)&cc_prop,FGAD,NL };

struct NewScreen scr = {
    0,0,                /* x,y start */
    640,200,            /* width, height */
    2,                  /* depth */
    2,1,                /* detail, block pens */
    HIRES,              /* view mode */
    WBENCHSCREEN,       /* screen type */
    NULL,               /* font */
    (UBYTE *) "Flist V1.2 - By Steve (Raz) Berry",         /* title */
    NULL,               /* gadgets */
    NULL                /* bitmap pntr */
    };

struct NewWindow mywin = {
    0,0,                        /* x,y start */
    640,200,                    /* width, height */
    2,1,                        /* detail, block pens */
    RAWKEY | REFRESHWINDOW | GADGETDOWN | GADGETUP | MOUSEMOVE | 
                                /* IDCMP flags */
    MOUSEBUTTONS | MENUPICK | REQCLEAR | SELECTDOWN | SELECTUP,
    NORMALFLAGS,                /* window flags */
    NULL, NULL,                 /* pntr gadget, checkmark */
    (UBYTE *) "Flist",          /* title */
    NULL,                   /* screen pointer filled in later (run time) */
    NULL,                   /* bitmap pntr */
    0, 0, 8000, 8000,       /* default x,y, &size */
    CUSTOMSCREEN
    };

/* Globals */

extern long numfiles, remember;
extern long (*finfo[MAXDIR])[4];  /* miscelaneous info -- file size,blocks,dir type etc... */
extern char (*fname[MAXDIR])[FCHARS];     /* file name and comment */
extern char (*comm[MAXDIR])[FCHARS];
extern char (*fstring[MAXDIR])[LEN_DATSTRING];
extern char (*ftime[MAXDIR])[LEN_DATSTRING];
extern struct Image cursor_image;
extern long row,collum,line,first;
extern struct Window *winptr;
extern struct Screen *scrptr;

/* Globals defined here */

struct RastPort *rp;

/* Scrprt - print text to a screen (actually a rastport) */

scrprt(numb,top)
short numb,top;
{
    struct IntuiText itext;
    register long temp,i;

    if (top == remember )
        return;
        
    /* for FAST movements of the screen... use the hardware */
        
    if ((top-remember) == 1 || (top-remember) == -1)
        doBlit(top); 
    else{
        Move(rp,0,0);
        ClearScreen(rp); 
        if (numfiles != 0) {    /* Watch for empty directories! */
            if (line > numfiles)
                temp = numfiles;
            else
                temp = top;

            for(i=0;(i<numb)&&(i<NUMLINES);i++) {
                prtline(temp,i);
                if (temp < numfiles)
                        temp++;
            }
        }
    }
    RefreshGadgets(&pg,winptr,NULL);
    doborder();
    remember = top;
}

struct IntuiText itext = {
        TEXTCOLOR, 0,
        JAM2,
        0,0,                    /* x, y */
        NULL,                   /* font */
        NULL,                   /* &text */
        NULL,                   /* &next */
};

/* Print a line associated with a file to the screen */

/* **** This could be optimized in assembly for speed **** */

prtline(pline,i)
register long pline,i;
{
     char buffer[FCHARS];
     struct BitMap *bmptr;

     if (pline >= numfiles)
        return;
     
     bmptr = &scrptr->BitMap;

     itext.LeftEdge = 0;
     itext.TopEdge = i * LINEH; 
     strcpy(&buffer[0],fname[pline]);
     buffer[13] = 0;
     itext.IText = buffer; 
     PrintIText(rp,&itext,3L,14L); 
     itext.LeftEdge = 368; 
     itext.IText = fstring[pline];
     PrintIText(rp,&itext,3L,14L); 
     itext.LeftEdge = 456; 
     itext.IText = ftime[pline];
     PrintIText(rp,&itext,3L,14L); 

     if (*finfo[pline][0] < 0)
        sprintf(buffer,"%d         ",(*finfo[pline])[2]);
     else
        strcpy(buffer," Dir");

     itext.LeftEdge = 528; 
     buffer[7] = 0;
     itext.IText = buffer; 
     PrintIText(rp,&itext,3L,14L); 
}

doBlit(stop)
long stop;
{
        long inter,i;        
        struct BitMap *bmptr;
        
        inter = stop - remember;
        bmptr = &scrptr->BitMap;

        WaitTOF();
        if (inter > 0)
                ScrollRaster(rp,0L,LINEH,0L,(LONG)TOP+2,600L,189L);
/*                    BltBitMap(bmptr,0L,22L,bmptr,0L,12L,600L,170L,
                      (LONG)0x0c0,(LONG)0x0ff,tempblit); */
        else
                ScrollRaster(rp,0L,-(LINEH),0L,(LONG)TOP+2,600L,189L);
/*                    BltBitMap(bmptr,0L,12L,bmptr,0L,22L,600L,170L,
                    (LONG)0x0c0,(LONG)0x0ff,tempblit); */
        
        if (inter > 0)
                prtline(stop+NLMO,NLMO);
        else
                prtline(stop,0); 
}

/* draw the border around the console display */

doborder()
{
        SetAPen(rp,3);
        Move(rp,LEFT-2,TOP-1);
        Draw(rp,RIGHT,TOP-1);
        Draw(rp,RIGHT,BOT+1);
        Draw(rp,LEFT-2,BOT+1);
        Draw(rp,LEFT-2,TOP-1);
}

/* this function captures the abort from cntrl c */

_abort()
{
    int ret;
    ret = auto_req("User abort!!!");

    if(scrptr->FirstWindow->NextWindow != NULL) 
        auto_req("Kill all other Applications first!");
    else
        if (ret) {
            Cleanup();
            exit(1);
        }
    menu();     /* no abort, go to the menu again! */
}

openstuff()
{
    int i;
    struct ViewPort *vp;

    scrptr = OpenScreen(&scr);
    if (scrptr == NULL) {
        fprintf(stderr,"Couldn't open Screen!\n");
        FreeFlistMem();
        exit(30L);
    }

    mywin.FirstGadget = &pg;   /* prop gadget attached to the window */
    mywin.Screen = scrptr;
    winptr = OpenWindow(&mywin);
    if (winptr == NULL) {
        fprintf(stderr,"Couldn't open Window!\n");
        FreeFlistMem();
        CloseScreen(scrptr);
        exit(40L);
    }

    OpenConsole();
    
    rp = winptr->RPort;
    vp = &scrptr->ViewPort;

/*     LoadRGB4(vp,&coltbl,4L); */

    refresh();
}
SHAR_EOF
cat << \SHAR_EOF > dos.c
/* 
    This module contains routines that do things to AmigaDOS. Things
    such as change directory, or parent directory or delete file etc...
*/

#include "libraries/arpbase.h"
#include "flist.h"

struct Window *make_gadget();
extern void refresh();

extern struct AnchorPath *ap;
extern struct FileLock *startdir, *lock, *olddir;
extern struct Window *winptr;
extern long (*finfo[MAXDIR])[4];  
extern char (*fname[MAXDIR])[FCHARS];
extern char (*comm[MAXDIR])[FCHARS];
extern char (*fstring[MAXDIR])[LEN_DATSTRING];
extern char (*ftime[MAXDIR])[LEN_DATSTRING];
extern long top, row, line, numfiles, lastsort;
extern char titlestr[80];

extern int PathName();
extern struct NewWindow strwin;
extern char strbuf[256];

long rename_file(file)
char *file;
{
    char buf[256];
	struct Window *strptr;

    strbuf[0] = '\0';
    strptr = make_gadget("Enter string to rename to");

    if (strptr == NULL) {
        auto_req("Couldn't open Requestor!");
        return BAD_COMMAND;
    }

    drawcur();

    wait_for_event(strptr);

    blankcur();

#ifdef DEBUG
    sprintf(buf,"string gadget is -%s-",strbuf);
    auto_req(buf);
#endif

    if (strbuf[0] == '\0')
        return NULL;

    if (!Rename(file,strbuf)) {
        auto_req("Couldn't rename file!");
        return 1;
    }

    strcpy(&fname[line][0],strbuf);

    return NULL;
}

long make_dir()
{
    char buf[256];
    long err;
    struct FileLock *newlock;
	struct Window *strptr;

    strbuf[0] = '\0';
    strptr = make_gadget("Enter name of Directory ");

    if (strptr == NULL) {
        auto_req("Couldn't open Requestor!");
        return BAD_COMMAND;
    }

    wait_for_event(strptr);

    if (strbuf[0] == '\0')
        return NULL;

    newlock = CreateDir(strbuf);

    if (newlock == 0) {
        err = IoErr();
        sprintf(buf,"Couldn't Create directory! DOS error %ld",err);
        auto_req(buf);
        return 1;
    } else
        UnLock(newlock);

    getdir();

    return NULL;
}

long changedir(str)
char *str;
{
    char buf[1000], buf1[1000];
    long rc;
    struct FileLock *dummy;

    dummy = lock;
    lock = Lock(str,ACCESS_READ);
    if (lock == NULL){
        lock = dummy;
        sprintf(buf,"Can't Lock directory -%s-!",str);
        auto_req(buf);
        return DIR_LOCKED;
    }

    strcpy(buf,str);
    TackOn(buf, "*");

    rc = FindFirst(buf,ap); /* ARP does all the work getting the directory */

    if (rc == NULL){
        Fillarray();    /* fill the arrays with the names and info */
        top = 0;
        row = 0;    
        line = 0;
    }
    else {
        if (rc != ERROR_NO_MORE_ENTRIES){
            sprintf(buf,"Can't find directory -%s- !",str);
            auto_req(buf);
            return BAD_DIR;
        } else
            numfiles = 0;
    }

    olddir = CurrentDir(lock);
    
    if (dummy != NULL)
        UnLock(dummy);

    return rc;
}

/* Go up one directory, saving all the locks */

parent()
{
    long rc;
    char buf[1000], buf1[1000];
    struct FileLock *dummy;

    if (lock == NULL)   /* if we are at the parent already -> return */
        return;

                        /* Also watch for the root of the current volume */
    PathName(lock, buf);
    if (buf[strlen(buf)-1] == ':')
        return;

    dummy = ParentDir(lock);
    olddir = CurrentDir(dummy);

    if (lock != NULL)
        UnLock(lock);

    lock = dummy;

    rc = FindFirst("*",ap); 

    if (rc == NULL) {
        Fillarray();
        top = 0;
        row = 0;    
        line = 0;
    }
    else 
        auto_req("Can't change to Parent!");
}

/* Delete (Kill) a file */

long kill(str)
char *str;
{
    long rc,i;
    char buf[1000];

    if (strlen(str) == 0 || numfiles == 0)
        return BAD_COMMAND;

    rc = DeleteFile(str);

    if(rc == NULL) {
        sprintf(buf,"Couldn't delete file %s",str);
        auto_req(buf);
        return BAD_COMMAND;
    } else
        numfiles--;
        
    for (i = line; i < numfiles;i++) {
        swap(&finfo[i], &finfo[i+1]);
        swap(&fname[i], &fname[i+1]);
        swap(&comm[i], &comm[i+1]);
        swap(&fstring[i], &fstring[i+1]);
        swap(&ftime[i], &ftime[i+1]);
    }
    
    return rc;
}

/* 
    Re-get the current directory... This is good for when the user renames
    a file and wants to see the change in the list.
*/

getdir()
{
    long rc,i;
    char buf[1000];

    rc = FindFirst("*",ap); 

    if (rc == NULL) {
        Fillarray();    /* fill the arrays with the names and info */
        top = 0;
        row = 0;    
        line = 0;
    }
    else {
        if (rc != ERROR_NO_MORE_ENTRIES){
            sprintf(buf,"Can't find current directory!");
            auto_req(buf);
            return BAD_DIR;
        } else
            numfiles = 0;
    }
}

/* swap two pointers */

swap(ptr1,ptr2)
long *ptr1,*ptr2;
{
    long temp;
    
    temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
}
SHAR_EOF
cat << \SHAR_EOF > errout.c
/* 
    This module was created because of the need for error
    output when flist is 'run' or 'runback'ed.
    Because stderr is no a longer valid DOS filehandle, If flist
    detects an error and try's to output an error message to stderr,
    and we are running as a background task, the ouput to stderr will
    crash the machine. This is not user friendly. My solution is to
    open my own filehandle to stderr as a file in RAM:. While this 
    may not be the best solution, it will work in all cases that the
    ramdrive exists. If the ram: device is not available, then the output
    goes to NIL:.
    
    Drawbacks:
        You can never tell when you are run in the background, so you
        have to ALWAYS send output to this file.

    Written completely - I stole no code before it's time, by
        Stephen (Raz) Berry 1/2/89

*/

#include <stdio.h>

Redirecterror(stderror)
struct FileHandle *stderror;
{
    struct FileHandle *newerror,*newout,*newin;
    
    newerror = freopen("RAM:flist.errors","a",stderr);
    newin = freopen("CON:0/0/1/1/DummyIO","a",stdin);
    newout = freopen("RAM:flist.out","a",stdout);
    
    if (newerror == NULL)
        newerror = freopen("NIL:","a",stderr);

    if (newin == NULL)
        newin = freopen("NIL:","a",stdin);

    if (newout == NULL)
        newout = freopen("NIL:","a",stdout);
}
SHAR_EOF
cat << \SHAR_EOF > fl.flex
/* 
    This is a test rexx macro prog for Flist!

    Here we test message passing between rexx and Flist. 

    NOTE: all commands that exist on their own lines and inclosed in 
    single quotes (optional) are passed to flist.

    Written by Stephen (Raz) Berry
*/

trace off

address "flport"    /* Flist's port name */

norm = '9b34303b33316d'X    /* screen colors for highlights */
rever = '9b34303b33336d'X

if ~open(fd,'CON:0/80/640/30/Rexx_test') then exit(-30)
dummy = writeln(fd,rever || '  Prepare for Iconification!')
address command 'wait 3 sec'
dummy = close(fd)

 'iconify'  /* use Leo's iconify prog to shrink flist to an icon */

if ~open(fd,'CON:0/80/640/40/Rexx_test') then exit(-30)
dummy = writeln(fd,' This is what happens when you send a bad command.')
address command 'wait 3 sec'

 this is crapola  /* show what happens when a bad command is sent */

dummy = writeln(fd,'  Now we will sort the list by their file sizes!')
address command 'wait 3 sec'

 sort z   /* sort the list by size */

dummy = writeln(fd,'Now let us make a trip to the parent of this directory.')
address command 'wait 3 sec'

 parent   /* get the parent dir */

dummy = writeln(fd,'Pretend you have made a change to this directory.')
address command 'wait 2 sec'

dummy = writeln(fd,'Very Good. Now we can make Flist aware of the change.')
address command 'wait 2 sec'

 reget    /* reload the dir */

dummy = writeln(fd,'Now lets show off the pattern sorting ability of Flist.')
address command 'wait 2 sec'

 sort o

dummy = writeln(fd,'Like that? Now we will make a new directory.')
dummy = writeln(fd,'(Or you can hit return on a blank line to cancel)')
address command 'wait 2 sec'

 makedir

dummy = writeln(fd,'Assuming you are executing this macro from the flist')
dummy = writeln(fd,'directory we will change back to it now.')
address command 'wait 2 sec'

 changedir Flist

dummy = writeln(fd,'Now if you like you can use the ARP filerequestor to go')
dummy = writeln(fd,'to any volume your desire!')
address command 'wait 2 sec'

 request

dummy = writeln(fd,rever || '  Thats all Folks!')
address command 'wait 3 sec'
dummy = close(fd)

/* use the quotes here because END is a REXX keyword also */

 'end'      /* this should end the comunication, ...this is real helpful! */

exit
SHAR_EOF
cat << \SHAR_EOF > flist.c
/*
    This program was written by Stephen W. Berry.
 
    The concept is copyrighted by me, but the program listings
    executable and documentation are placed in the Public Domain.
 
    If you find a bug or enhance this program please let me know
    at the following address:
 
        The Checkered Ball
        A-7 Sinai Circle
        Chelmsford, Ma 01824
        c/o Stephen Berry
 
*/

#define DEBUG TRUE

#include <rexx/storage.h>
#include <rexx/rxslib.h>
#include <libraries/arpbase.h>
#include <stdio.h>
#include "flist.h"

struct RxsLib *RexxSysBase = NULL;

/* external routines - system */

extern void CloseLibrary();
struct Screen *OpenScreen();
struct Window *OpenWindow();
struct IntuiMessage *GetMsg();

/* external routines - Arp */

extern void *ArpAlloc();

/* external routines - mine */

extern void menu(),tticon(),OpenConsole(),drawcur(),blankcur();
extern long parse();
extern void FreeFlistMem(),OpenRexxPort(),DeleteRexxPort(),CleanupRexx();
extern long OpenLib(),StartRexxProg();
extern struct RexxMsg *port,*PollRexxPort(),*WaitMsgPort();
extern void Redirecterror();

/* global variables, structures etc... */

extern struct IOStdReq ConsoleReq;
extern struct FileLock *startdir, *rootdir, *lock;
struct Screen *scrptr = NULL;
struct Window *winptr = NULL, *oldwinptr;
struct RexxMsg myrexxport;
extern long numfiles;

extern long (*finfo[MAXDIR])[4];
extern char (*fname[MAXDIR])[FCHARS];
extern char (*comm[MAXDIR])[FCHARS];
extern char (*fstring[MAXDIR])[LEN_DATSTRING];
extern char (*ftime[MAXDIR])[LEN_DATSTRING];
APTR oldcon;

struct Process *myproc;
long remember = -10;
int didRexx = FALSE;

main(argc,argv)
int argc;
char *argv[];
{
    struct IntuiMessage *msg;
    LONG i,rc = NULL;

    /* parse the command line and get the first file */

    if((rc = parse(argc,argv)) != NULL){
        printf("Input error.\n");
        printf("Flist requires the name(s) of files\n");
        printf("Or FROM and the name of a file with names in it.\n");
        printf("Standard DOS and ARP wildcards are accepted.\n");
        FreeFlistMem();
        Delay(20);
        exit(rc);
    }

    openstuff(); /* open the window and screen */

/*    myproc = (struct Process *)DeviceProc("flist"); */
    myproc = (struct Process *)FindTask(0L);
/*    myproc = (myproc != NULL) ? myproc - sizeof(struct Task): 0; */

    if (myproc != NULL){

/* Believe it or not, this stops ALL requestors from appearing! */

        oldwinptr = myproc->pr_WindowPtr;
        myproc->pr_WindowPtr = (struct Window *)(-1L); 

/* This allows a safer environment for flist's run in the background */

        oldcon = myproc->pr_ConsoleTask;
        myproc->pr_ConsoleTask = (struct Task *)DeviceProc("null:");
        myproc->pr_WindowPtr = winptr; 
        if (myproc->pr_ConsoleTask != NULL)
            freopen("NULL:","w+",stderr);
    }

/*  I link with arp.lib so that I don't have to open:
    intuition, graphics and arp libraries. */

    RexxSysBase = OpenLibrary("rexxsyslib.library",(LONG)RXSVERS);

    if (RexxSysBase != NULL) {
        OpenRexxPort("flport",&myrexxport);
        didRexx = TRUE;
    }

    menu();     /* we should never return ! */
}

Cleanup()
{
    int i;

    myproc->pr_WindowPtr = oldwinptr;
    myproc->pr_ConsoleTask = oldcon;
    if(didRexx)
        DeleteRexxPort(&myrexxport);
    if(RexxSysBase != NULL )
        CloseLibrary(RexxSysBase);
    FreeFlistMem();
    if(winptr != NULL)
        CloseDevice(&ConsoleReq);
        CloseWindowSafely(winptr,NULL);
    if(scrptr != NULL )
        CloseScreen(scrptr);
    UnLock(CurrentDir(startdir));       /* go back to the dir we started at */

    for (i=0;i<MAXDIR;i++)              /* free all array memory */
        if (fname[i] != 0) {
            FreeMem(fname[i],FCHARS);
/*            FreeMem(comm[i],FCHARS); */
            FreeMem(finfo[i],16L);
            FreeMem(fstring[i],LEN_DATSTRING);
            FreeMem(ftime[i],LEN_DATSTRING);
            fname[i] = 0;
            finfo[i] = 0;
            fstring[i] = 0;
            ftime[i] = 0;
        }
}
SHAR_EOF
cat << \SHAR_EOF > flist.h
/* 
    These are all the defines for Flist 
*/

/* #define DEBUG */  /*  uncomment this line for debugging */

/* #define KILLEXTRA */ /* changes the way scrolling is done */

#define MAXDIR 1024
#define strcpy _BUILTIN_strcpy
#define NORMALFLAGS WINDOWSIZING|WINDOWDRAG|BORDERLESS|SMART_REFRESH|BACKDROP

#define FATALERROR      20L
#define DIR_LOCKED      1
#define BAD_DIR         2
#define BAD_COMMAND     1
#define OUT_OF_MEMORY   100L
#define CONVERSIONERROR 99L

#define TEXTCOLOR       5 
#define BACKGROUND      4
#define NL      NULL
#define RWDTH   640L
#define FGAD    0x76c0L
#define LEFT    114
#define RIGHT   363
#define TOP     12          /* Top of display */
#define BOT     192         /* Bottom of the display */
#define CHARW   8L          /* The width of each character */
#define LINEH   8L          /* This is the hieght of each line */
#define NUMLINES 22L        /* This is the number of lines in the display */
#define NLMO    21L         /* This stands for Num Lines Minus One */
#define MAXPLANES       3   /**  Max number of bitplanes we will need ***/
#define REDP    3
#define BLKP    2
#define WHTP    1
#define BLUP    0
#define FAST    MEMF_FAST|MEMF_CLEAR

#define LINESIZE        130L
#define INFOSIZE        16000
#define FILESIZE        LEN_DATSTRING*1000
#define COMMSIZE        LEN_DATSTRING*1000
#define STRINGSIZE      LEN_DATSTRING*1000
SHAR_EOF
cat << \SHAR_EOF > flist.icon.c
#include <exec/types.h>
#include <intuition/intuition.h>

UWORD   cursor_img[] = {
        0xffff,0xffff
        0xffff,0xffff
        0xffff,0xffff
        0xffff,0xffff
        0xffff
        };

UWORD               flist.icon_data[] = {

     /* BitPlane #0 */

     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C1F, 0xE783, 0x8001, 0x800F, 0xC000, 
     0x7C0E, 0xE380, 0x0003, 0x800F, 0xC000, 
     0x7C0E, 0x0387, 0x87E7, 0xE00F, 0xC000, 
     0x7C0F, 0x8383, 0x8E03, 0x800F, 0xC000, 
     0x7C0E, 0x0383, 0x87C3, 0x800F, 0xC000, 
     0x7C0E, 0x0383, 0x80E3, 0xE00F, 0xC000, 
     0x7C1F, 0x07C7, 0xCFC1, 0xC00F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x1E00, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0E00, 0x000F, 0xC000, 
     0x7C00, 0x07EE, 0x7FC0, 0x000F, 0xC000, 
     0x7C00, 0x0E0F, 0xFFE0, 0x000F, 0xC000, 
     0x7C00, 0x07CF, 0xFEE0, 0x000F, 0xC000, 
     0x7C00, 0x00E7, 0xEEE0, 0x000F, 0xC000, 
     0x7C00, 0x0FC7, 0xE7C0, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7C00, 0x0000, 0x0000, 0x000F, 0xC000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 

     /* BitPlane #1 */

     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x4000, 0x0000, 0x0000, 0x0000, 0x4000, 
     0x4000, 0x0000, 0x0000, 0x0000, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xE1FF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xF1FF, 0xFFF0, 0x4000, 
     0x43FF, 0xF811, 0x803F, 0xFFF0, 0x4000, 
     0x43FF, 0xF1F0, 0x001F, 0xFFF0, 0x4000, 
     0x43FF, 0xF830, 0x011F, 0xFFF0, 0x4000, 
     0x43FF, 0xFF18, 0x111F, 0xFFF0, 0x4000, 
     0x43FF, 0xF038, 0x183F, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x43FF, 0xFFFF, 0xFFFF, 0xFFF0, 0x4000, 
     0x4000, 0x0000, 0x0000, 0x0000, 0x4000, 
     0x4000, 0x0000, 0x0000, 0x0000, 0x4000, 
     0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC000, 
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000
     };


struct Image               flist.icon_image = {
     0, 0, 67, 35, 2, flist.icon_data, 0x3, 0x0, NULL
     };

struct Image               cursor_image = {
     0, 0, 16, 9, 1, cursor_img, 0x1, 0x0, NULL
     };

SHAR_EOF
cat << \SHAR_EOF > flist.icon.uu

begin 644 flist.icon
M1D]230```M1)3$)-0DU(1````!0`0P`C``````("`0````H+`H``R$--05``(
M```,````T-"P4(#`\(!`1U)!0@````0`(0`10U).1P````@```JJ``$#`T-2P
M3D<````(```*J@`!`P%#4DY'````"```"JH``0``0U).1P````@```JJ``$`D
M`$)/1%D```)+]P#W``!_^O\!P```?_K_`<```'_Z_P'```!`^@`!0```?_K_'
M`<```$#Z``%```!\^P`"#\```$/[_P+P0```?/L``@_```!#^_\"\$``"7P?.
MYX.``8`/P```0_O_`O!```E\#N.```.`#\```$/[_P+P0``)?`X#AX?GX`_`:
M``!#^_\"\$``"7P/@X..`X`/P```0_O_`O!```E\#@.#A\.`#\```$/[_P+PY
M0``)?`X#@X#CX`_```!#^_\"\$``"7P?!\?/P<`/P```0_O_`O!```!\^P`"3
M#\```$/[_P+P0```?/L``@_```!#^_\"\$```'S[``(/P```0_O_`O!```!\H
M_@`%'@``#\```$/^_P7A___P0```?/X`!0X```_```!#_O\%\?__\$``"7P`)
M!^Y_P``/P``)0__X$8`___!```E\``X/_^``#\``"4/_\?``'__P0``)?``';
MS_[@``_```E#__@P`1__\$``"7P``.?NX``/P``)0___&!$?__!```E\``_'C
MY\``#\``"4/_\#@8/__P0```?/L``@_```!#^_\"\$```'S[``(/P```0_O_K
M`O!```!\^P`"#\```$/[_P+P0```?/L``@_```!#^_\"\$```'S[``(/P```H
M0_O_`O!```!\^P`"#\```$/[_P+P0```?/L``@_```!#^_\"\$```'S[``(/E
MP```0_O_`O!```!_^O\!P```0/H``4```'_Z_P'```!`^@`!0```?_K_`<``0
,`'_Z_P'``/<`]P``G
``
end
size 732
SHAR_EOF
cat << \SHAR_EOF > help.c
/* 
    This file contains the Help routine

	To invoke the help routine, hit the Help key!

    Written by Steve (Raz) Berry with help from Carol Schnepper
    (I stole the window spec and the code to wait for a keypress from
    her example program 'Timerwin.c')

*/

#include "flist.h"
#include <stdio.h>

extern struct Screen *scrptr;

struct   NewWindow helpwin = {
   40,0,                                  /* LeftEdge and TopEdge */
   500, 200,                              /* Width and Height */
   -1, -1,                                /* DetailPen and BlockPen */
   CLOSEWINDOW|VANILLAKEY,                /* IDCMP Flags */
   WINDOWDEPTH|WINDOWDRAG|WINDOWCLOSE     /* Flags */
   |SMART_REFRESH|ACTIVATE,
   NULL, NULL,                            /* Gadget and Image pointers */
   "Help",                                /* Title string */
   NULL,                                  /* Screen ptr null (this screen) */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   320, 200,                              /* MaxWidth and MaxHeight */
   WBENCHSCREEN                           /* Type of window */
   };

/* Here is the text to be output */

char *text[] = {
		"",
		"Key        Command Description",
		"---        ------- -----------",
		"^A         bring up the ARP Filerequestor.",
        "^C         abort Flist.",
        "^D         change to current Directory.",
        "^G         re-Get the current directory.",
        "^K         delete (Kill) current file.",
        "^L         Repaint and restore screen.",
        "^N         Make directory",
        "^P         get Parent directory.",
        "^R         Rename current file or directory",
        "^S         sort list by Names.",
        "^T         sort list by Time.",
        "^Z         sort list by Size.",
        "^O         sort by Pattern (ARP wildcards).",
        "^U         Erase line.",
        "^X         Execute REXX macro.",
        " Hitting the Esc key will insert the current filename into",
        " the command line.",
        "   Hit any key or the close gadget to continue."
        };

Help()
{
    int i;
	struct Window *helptr;
	struct RastPort *hrp;

    helptr = OpenWindow(&helpwin);
    if (helptr == NULL) 
        auto_req("Couldn't open Window!");
    else {
  	    hrp = helptr->RPort;
    	Move(hrp,10L,20L);

    	for (i=0;i<21;i++){
    	    Text(hrp,text[i],strlen(text[i]));
    	    Move(hrp,10,i+20+8*i);
    	}

        wait_for_event(helptr);
    }
}
SHAR_EOF
cat << \SHAR_EOF > iconify.c
/*  :ts=8 bk=0
 *
 * iconify.c:	You asked for it, you got it.
 *
 * Copyright 1987 by Leo L. Schwab.
 * Permission is hereby granted for use in any and all programs, both
 * Public Domain and commercial in nature, provided this Copyright notice
 * is left intact.  Purveyors of programs, at their option, may wish observe
 * the following conditions (in the spirit of hackerdom):
 *	1: You send me a free, registered copy of the program that uses the
 *	   iconify feature,
 *	2: If you're feeling really nice, a mention in the program's
 *	   documentation of my name would be neat.
 *
 *			 		8712.10		(415) 456-3960
 */
#include <exec/types.h>
#include <devices/timer.h>
#include <intuition/intuition.h>
#include "icon/iconify.h"

/*
 * It is recommended that the tick rate not be made too rapid to avoid
 * bogging down the system.
 */
#define	TICKS_PER_SECOND	10

/*
 * Some programmers may not wish to have the added functionality of the
 * ICON_FUNCTION feature.  If you're such a programmer, you may comment out
 * the following #define, which will eliminate the code to handle function
 * calls, and make iconify() even smaller.
 */
#define	USE_FUNCTIONS

/*
 * Jim Mackraz suggested making icons easily identifiable by outside
 * programs, so this constant gets stuffed into the UserData field.
 */
#define	ICON	0x49434f4eL		/*  'ICON'  */


extern void	*OpenWindow(), *GetMsg(), *CreatePort(), *CreateExtIO(),
		*CheckIO();
extern long	OpenDevice(), DoubleClick();


static struct Gadget gadget = {
	NULL,
	0, 0, 0, 0,
	NULL,				/*  Set later  */
	GADGIMMEDIATE,
	WDRAGGING,			/*  Observe the Magic!  */
	NULL,				/*  Set later  */
	NULL, NULL, NULL, NULL,
	0, 0
};

static struct NewWindow windef = {
	0, 0, 0, 0,			/*  Set later  */
	-1, -1,
	GADGETDOWN,
	BORDERLESS | SMART_REFRESH | NOCAREREFRESH,
	&gadget,
	NULL, NULL, NULL, NULL,		/*  Lotsa these  */
	0, 0, 0, 0,
	WBENCHSCREEN
};

static struct Window		*win;

#ifdef USE_FUNCTIONS
static struct timerequest	*tr;
static struct MsgPort		*reply;
#endif


iconify (left, top, width, height, screen, ptr, type)
UWORD *left, *top, width, height;
struct Screen *screen;
APTR ptr;
int type;
{
	register struct IntuiMessage	*msg;
	long				secs = 0, mics = 0,
					cs, cm,
					class,
					sigmask;

	windef.LeftEdge		= *left;
	windef.TopEdge		= *top;
	windef.Width		= width;
	windef.Height		= height;
	windef.Type = (windef.Screen = screen) ? CUSTOMSCREEN : WBENCHSCREEN;

	gadget.Flags		= GADGHCOMP | GRELWIDTH | GRELHEIGHT;

	switch (type & 3) {
	case ICON_IMAGE:
		gadget.Flags		|= GADGIMAGE;
	case ICON_BORDER:
		gadget.GadgetRender	= ptr;
		break;

	case ICON_FUNCTION:
#ifdef USE_FUNCTIONS
		gadget.GadgetRender	= NULL;
#else
		return (0);
#endif
		break;

	default:
		return (0);
	}

	if (!openstuff ())
		return (0);
	sigmask = 1L << win -> UserPort -> mp_SigBit;

#ifdef USE_FUNCTIONS
	if (type == ICON_FUNCTION) {
		sigmask |= 1L << reply -> mp_SigBit;
		tr -> tr_node.io_Command= TR_ADDREQUEST;
		tr -> tr_time.tv_secs	= 0;
		tr -> tr_time.tv_micro	= (1000000L / TICKS_PER_SECOND);
		SendIO (tr);
		/*
		 * Make initialization call to user's function.
		 * Isn't typecasting wonderful?  :-|
		 */
		(* ((void (*)()) ptr)) (win, (WORD) 1);
	}
#endif

	while (1) {
		Wait (sigmask);

#ifdef USE_FUNCTIONS
		if (GetMsg (reply)) {
			/*
			 * Call user's function to do something to the icon.
			 */
			(* ((void (*)()) ptr)) (win, (WORD) 0);
			tr -> tr_time.tv_secs	= 0;
			tr -> tr_time.tv_micro	=
			 (1000000L / TICKS_PER_SECOND);
			SendIO (tr);
		}
#endif

		if (msg = GetMsg (win -> UserPort)) {
			class = msg -> Class;
			cs = msg -> Seconds;
			cm = msg -> Micros;
			ReplyMsg (msg);

			if (class == GADGETDOWN) {
				if (DoubleClick (secs, mics, cs, cm))
					break;
				secs = cs;  mics = cm;
			}
		}
	}

#ifdef USE_FUNCTIONS
	if (type == ICON_FUNCTION) {
		AbortIO (tr);
		WaitIO (tr);
	}
#endif

	*left = win -> LeftEdge;
	*top = win -> TopEdge;
	closestuff ();
	return (1);
}

static
openstuff ()
{
	if (!(win = OpenWindow (&windef)))
		return (0);
	win -> UserData = (BYTE *) ICON;
		
#ifdef USE_FUNCTIONS
	if (!(reply = CreatePort (NULL, NULL)) ||
	    !(tr = CreateExtIO (reply, (long) sizeof (*tr))) ||
	    OpenDevice (TIMERNAME, UNIT_VBLANK, tr, 0L)) {
		closestuff ();
		return (0);
	}
#endif

	return (1);
}

static
closestuff ()
{
#ifdef USE_FUNCTIONS
	if (tr) {
		if (tr -> tr_node.io_Device)
			CloseDevice (tr);
		DeleteExtIO (tr, (long) sizeof (*tr));
	}
	if (reply)		DeletePort (reply);
#endif

	if (win)		CloseWindow (win);
}
SHAR_EOF
cat << \SHAR_EOF > iconify.h
/*  :ts=8 bk=0
 *
 * iconify.h:	Should be used by all programs intending to use iconify.c.
 *
 * Copyright 1987 by Leo L. Schwab.
 * Permission is hereby granted for use in any and all programs, both
 * Public Domain and commercial in nature, provided this Copyright notice
 * is left intact.  Purveyors of programs, at their option, may wish observe
 * the following conditions (in the spirit of hackerdom):
 *	1: You send me a free, registered copy of the program that uses the
 *	   iconify feature,
 *	2: If you're feeling really nice, a mention in the program's
 *	   documentation of my name would be neat.
 *
 *			 		8712.10		(415) 456-3960
 */

#define	ICON_IMAGE	0
#define	ICON_BORDER	1
#define	ICON_FUNCTION	2

/*  Suggested icon size for a standard (640 x 200) WorkBench screen.  */
#define	ICONWIDTH	((UWORD) 50)
#define	ICONHEIGHT	((UWORD) 25)
SHAR_EOF
cat << \SHAR_EOF > makefile
#
#   Makefile for Flist... Please check the flist.h file for 
#   customization.
#
#   Steve (Raz) Berry '88

CFLAGS	= +C +Iinclude:symbols.m -s -n 

OBJECTS	=	parse.o32 rexxport.o32 rexxglue.o menu.o32 arpdos.o32 \
		ttyio.o32 icon/ttyicon.o icon/iconify.o 

OBJECTS1 = pathname.o32 dos.o32 help.o32 display.o32 sort.o32 misc.o32

OTHERS	=	dh:aztec/sys2/lib/detach.o32

.asm.o:
		as -C -D $*.asm

.c.o32:
		cc +l $(CFLAGS) -o $@ $*.c

.c.o:
		cc +l $(CFLAGS) -o $@ icon/$*.c

Flist:	Flist.o32 $(OBJECTS) $(OBJECTS1)
		ln -w +cd -g Flist.o32 $(OBJECTS) $(OBJECTS1) -larp32 -lc32

clean:
        delete $(OBJECTS)
        delete $(OBJECTS1)

backup:
        copy work:Flist Flist_backup:Flist all clone

release:
        copy work:Flist/Flist bin:
        delete Flist_release:flist.zoo
        zoo a RAM:flist work:flist/*
        zoo D RAM:flist *.o32
        zoo a RAM:flist work:flist/icon/*
        zoo a RAM:flist work:flist/null/*
        zoo P RAM:flist
        delete RAM:flist.bak
        copy RAM:flist.zoo Flist_release:
SHAR_EOF
cat << \SHAR_EOF > misc.c
/*
    String gadgets and misc functions.

    Written by: Steve (Raz) Berry
*/

#include "flist.h"

char strbuf[256];
char undo[256];

struct IntuiText AutoText = {
   REDP,     WHTP,
   JAM2,  15,
   5,    NL,
   " Flist ", NULL
};

/** TRUE TEXT **/
struct IntuiText TRUEtext = {
   BLUP,  WHTP,
   JAM2,
   7,                       /* LeftEdge */
   3,                       /* TopEdge  */
   NL,                      /* Default font */
   "OK",                    /* Text */
   NL                       /* No pointer to next text */
};

/** FALSE TEXT **/
struct IntuiText FALSEtext = {
   REDP,  WHTP,
   JAM2,
    7,                       /* LeftEdge */
    3,                       /* TopEdge  */
   NL,                       /* Default font */
   "NO!",                    /* Text */
   NL
};

struct StringInfo strinfo = {
    strbuf,
    undo,
    0,
    200,
    0, 0,
    0, 0,
    0, 0,
    0, 0,
    0
};
    
struct Gadget str = {
    NULL,
    20, 20, 240, 10,
    GADGHCOMP,
    GADGIMMEDIATE|RELVERIFY,
    STRGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    (APTR)&strinfo,
    0, NULL
};

struct  NewWindow strwin = {
   140,70,                                /* LeftEdge and TopEdge */
   300, 40,                               /* Width and Height */
   0, 1,                                  /* DetailPen and BlockPen */
   CLOSEWINDOW|GADGETUP,                  /* IDCMP Flags */
   WINDOWDEPTH|WINDOWDRAG|WINDOWCLOSE     /* Flags */
   |SMART_REFRESH|ACTIVATE,
   &str, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Screen ptr null (this screen) */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   320, 200,                              /* MaxWidth and MaxHeight */
   WBENCHSCREEN                           /* Type of window */
};

/* Make a string gadget in it's own window */

struct Window *make_gadget(title)
char *title;
{
    struct Window *strptr;

    strwin.Title = title;
    strptr = OpenWindow(&strwin);

    if(strptr != NULL) {
        RefreshGadgets(&str, strptr, NULL);
        ActivateGadget(&str, strptr, NULL);
    }
    return strptr;
}

/* Wait for one event from a window, then return */

wait_for_event(win)
struct Window *win;
{
    ULONG imask,signals;
    struct IntuiMessage *imsg;

    imask = 1 << win->UserPort->mp_SigBit;

    signals = Wait(imask);

    if(signals & imask) {
        while(imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
            ReplyMsg(imsg);
    } 
    if (win) {
        while(imsg = (struct IntuiMessage *)GetMsg(win->UserPort))
            ReplyMsg(imsg);
        CloseWindow(win);
    }
}

int auto_req();
/***************************************************************************
                            HANDLE AUTO-REQUESTS
***************************************************************************/
int auto_req (text)
char *text;         /* Pointer to the text */
{
    struct Process *proc;
    int   val, temp;

    AutoText.IText = text;               /* Text pointer          */

    temp = ((CHARW + 1) * strlen(text)) + (4 * CHARW);
    temp = (temp < 150) ? 150: temp;

    proc = (struct Process *)FindTask(NULL);
    val = AutoRequest(proc->pr_WindowPtr, &AutoText, &TRUEtext, &FALSEtext, 
            0L, 0L, (LONG)temp, 60L );
    return val;
}
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.