/***************************************************************************

                        F I L E - F I N D E R
                       ^^^^^^^^^^^^^^^^^^^^^^^

                        by  Federico Giannici



Inizio  27/10/88           Attuale 01/12/89                 V 1.5


Routine generalizzata di richiesta del nome di un file.


filefinder( data )
    struct  ffdata *data;          Struttura dati da usare (vedi definizione)


Necessita apertura librerie:
    Intuition.library   (da 1.2 in poi)
    Graphics.library


***************************************************************************/


#include    "general.h"
#include    "MyRoutines/FileFinder.h"


#define FFMAXLEN    FFPATHLEN

#define FFLINELEN   33
#define FFLINENUM   8

#define FFCOLORA    2
#define FFCOLORA2   0
#define FFCOLORB    1
#define FFCOLORO    3
#define FFCOLORS    0
#define FFCOLORDF0  1
#define FFCOLORDF1  2
#define FFCOLORDF2  3

#define FFWTOP      9
#define FFWWIDTH    312
#define FFWHEIGHT   (180+FFWTOP)

#define FFDFNOVALID (-1)

#define FFMIN(a,b)  ((a)<(b)?(a):(b))
#define FFTOUP(c)   ( c>='a' && c<='z' ? c-('a'-'A') : c )


/*****   Le mie proto   *****/
void    ffshowall( void );
void    ffsetprop( void );
void    ffchangepath( void );
void    ffunlock( void );
void    ffoutdiskfree( ULONG );
void    fffinddevices( void );
LONG    ffopenwindow( void );
LONG    ffaddline( void );
LONG    ffaddshow( LONG );
LONG    ffstrcmpu( UBYTE *, UBYTE * );



UBYTE	novalidpath[]="Not A Valid Path!";
#define	NOVALIDPATHLEN	17

UBYTE   ffundobuff[ FFMAXLEN+1 ];

struct  TextAttr    fffont=
    {
    "topaz.font",
    8,
    0, 0
    };


struct  Image   ffig24;
struct  PropInfo    ffpg24=
    {
    FREEVERT | PROPBORDERLESS | AUTOKNOB,
    0,
    0,
    0,
    0xFFFF,
    NULL,
    NULL,
    NULL, NULL,
    NULL,
    NULL
    };
struct  Gadget  ffg24=
    {
    NULL,
    282, 80+FFWTOP,
    18, 52,
    GADGHCOMP | GADGIMAGE,
    GADGIMMEDIATE,
    PROPGADGET,
    ( APTR )&ffig24,
    NULL,
    NULL,
    NULL,
    ( APTR )&ffpg24,
    24,
    NULL
    };

SHORT   ffdbg23c[ 4*2 ]=
    {
    10, 9,
    17, 2,
    3, 2,
    10, 9
    };
SHORT   ffdbg22c[ 4*2 ]=
    {
    10, 2,
    17, 9,
    3, 9,
    10, 2
    };
SHORT   ffdbg22[ 5*2 ]=
    {
    -1, 0,
    21, 0,
    21, 11,
    -1, 11,
    -1, 0
    };
struct  Border  ffbg23d=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg23c,
    NULL
    };
struct  Border  ffbg23c=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg23c,
    &ffbg23d
    };
struct  Border  ffbg23b=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg22,
    &ffbg23c
    };
struct  Border  ffbg23=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg22,
    &ffbg23b
    };
struct  Gadget  ffg23=
    {
    &ffg24,
    280, 132+FFWTOP,
    22, 12,
    GADGHCOMP,
    RELVERIFY | GADGIMMEDIATE,
    BOOLGADGET,
    ( APTR )&ffbg23,
    NULL,
    NULL,
    NULL,
    NULL,
    23,
    NULL
    };

struct  Border  ffbg22d=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg22c,
    NULL
    };
struct  Border  ffbg22c=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg22c,
    &ffbg22d
    };
struct  Border  ffbg22b=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg22,
    &ffbg22c
    };
struct  Border  ffbg22=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg22,
    &ffbg22b
    };
struct  Gadget  ffg22=
    {
    &ffg23,
    280, 68+FFWTOP,
    22, 12,
    GADGHCOMP,
    RELVERIFY | GADGIMMEDIATE,
    BOOLGADGET,
    ( APTR )&ffbg22,
    NULL,
    NULL,
    NULL,
    NULL,
    22,
    NULL
    };

struct  StringInfo  ffsg21=
    {
    NULL,
    ffundobuff,
    0,
    FFFILELEN+1,
    0,
    NULL,
    NULL,
    NULL,
    NULL, NULL,
    NULL,
    NULL,
    NULL,
    };
struct  IntuiText   fftg21=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    -40-2, 0,
    &fffont,
    "File:",
    NULL
    };
struct  Gadget  ffg21=
    {
    &ffg22,
    51+2, 146+1+FFWTOP,
    248, 10,
    GADGHCOMP,
    RELVERIFY,
    STRGADGET,
    NULL,
    NULL,
    &fftg21,
    NULL,
    ( APTR )&ffsg21,
    21,
    NULL
    };

struct  StringInfo  ffsg20=
    {
    NULL,
    ffundobuff,
    0,
    FFPATHLEN+1,
    0,
    NULL,
    NULL,
    NULL,
    NULL, NULL,
    NULL,
    NULL,
    NULL,
    };
struct  IntuiText   fftg20=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    -40-2, 0,
    &fffont,
    "Path:",
    NULL
    };
struct  Gadget  ffg20=
    {
    &ffg21,
    51+2, 56+1+FFWTOP,
    248, 10,
    GADGHCOMP,
    RELVERIFY,
    STRGADGET,
    NULL,
    NULL,
    &fftg20,
    NULL,
    ( APTR )&ffsg20,
    20,
    NULL
    };

struct  StringInfo  ffsg19=
    {
    NULL,
    ffundobuff,
    0,
    FFSUFFIXLEN+1,
    0,
    NULL,
    NULL,
    NULL,
    NULL, NULL,
    NULL,
    NULL,
    NULL,
    };
struct  IntuiText   fftg19=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    -56-2, 0,
    &fffont,
    "Suffix:",
    NULL
    };
struct  Gadget  ffg19=
    {
    &ffg20,
    235+2, 44+1+FFWTOP,
    64, 10,
    GADGHCOMP,
    RELVERIFY,
    STRGADGET,
    NULL,
    NULL,
    &fftg19,
    NULL,
    ( APTR )&ffsg19,
    19,
    NULL
    };

SHORT   ffdbg11[ 5*2 ]=
    {
    -4, -2,
    264+2, -2,
    264+2, 73,
    -4, 73,
    -4, -2
    };
struct  Border  ffbg11b=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg11,
    NULL
    };
struct  Border  ffbg11=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg11,
    &ffbg11b
    };

struct  Gadget  ffg18=
    {
    &ffg19,
    13, 70+7*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    18,
    NULL
    };

struct  Gadget  ffg17=
    {
    &ffg18,
    13, 70+6*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    17,
    NULL
    };

struct  Gadget  ffg16=
    {
    &ffg17,
    13, 70+5*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    16,
    NULL
    };

struct  Gadget  ffg15=
    {
    &ffg16,
    13, 70+4*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    15,
    NULL
    };

struct  Gadget  ffg14=
    {
    &ffg15,
    13, 70+3*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    14,
    NULL
    };

struct  Gadget  ffg13=
    {
    &ffg14,
    13, 70+2*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    13,
    NULL
    };

struct  Gadget  ffg12=
    {
    &ffg13,
    13, 70+1*9+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    12,
    NULL
    };

struct  Gadget  ffg11=
    {
    &ffg12,
    13, 70+FFWTOP,
    264, 9,
    GADGHCOMP,
    GADGIMMEDIATE | RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg11,
    NULL,
    NULL,
    NULL,
    NULL,
    11,
    NULL
    };

SHORT   ffdbg7[ 9*2 ]=
    {
    9, 12,
    69, 12,
    78, 8,
    78, 4,
    69, 0,
    9, 0,
    0, 4,
    0, 8,
    9, 12
    };

SHORT   ffdbg9[ 9*2 ]=
    {
    11, 0,
    75, 0,
    86, 5,
    86, 11,
    75, 16,
    11, 16,
    0, 11,
    0, 5,
    11, 0
    };

struct  Border  ffbg9d=
    {
    5, 2,
    FFCOLORA, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg7,
    NULL
    };
struct  Border  ffbg9c=
    {
    4, 2,
    FFCOLORA, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg7,
    &ffbg9d
    };
struct  Border  ffbg9b=
    {
    1, 0,
    FFCOLORO, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg9,
    &ffbg9c
    };
struct  Border  ffbg9=
    {
    0, 0,
    FFCOLORO, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg9,
    &ffbg9b
    };

struct  IntuiText   fftg10=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    20, 5,
    &fffont,
    "CANCEL",
    NULL
    };
struct  Gadget  ffg10=
    {
    &ffg11,
    204-4, 159+FFWTOP,
    88, 17,
    GADGHCOMP,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg9,
    NULL,
    &fftg10,
    NULL,
    NULL,
    10,
    NULL
    };

struct  IntuiText   fftg9b=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    36, 5,
    &fffont,
    "OK",
    NULL
    };
struct  IntuiText   fftg9=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    35, 5,
    &fffont,
    "OK",
    &fftg9b
    };
struct  Gadget  ffg9=
    {
    &ffg10,
    26-4, 159+FFWTOP,
    88, 17,
    GADGHCOMP,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg9,
    NULL,
    &fftg9,
    NULL,
    NULL,
    9,
    NULL
    };

struct  Border  ffbg7e=
    {
    3, 1,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg7,
    NULL
    };
struct  Border  ffbg7d=
    {
    2, 1,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg7,
    &ffbg7e
    };    
struct  Border  ffbg7c=
    {
    1, 1,
    FFCOLORA, FFCOLORB,
    JAM1,
    4,
    (SHORT *)&ffdbg7,
    &ffbg7d
    };
struct  Border  ffbg7b=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg7,
    &ffbg7c
    };    
struct  Border  ffbg7=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    9,
    (SHORT *)&ffdbg7,
    &ffbg7b
    };

struct  IntuiText   fftg8=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    18, 3,
    &fffont,
    "Parent",
    NULL
    };
struct  Gadget  ffg8=
    {
    &ffg9,
    204, 24+FFWTOP,
    82, 14,
    GADGHCOMP,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg7,
    NULL,
    &fftg8,
    NULL,
    NULL,
    8,
    NULL
    };

struct  IntuiText   fftg7=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    26, 3,
    &fffont,
    "Read",
    NULL
    };
struct  Gadget  ffg7=
    {
    &ffg8,
    26, 24+FFWTOP,
    82, 14,
    GADGHCOMP,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg7,
    NULL,
    &fftg7,
    NULL,
    NULL,
    7,
    NULL
    };

SHORT   ffdbg1[ 5*2 ]=
    {
    0, 0,
    47, 0,
    47, 15,
    0, 15,
    0, 0
    };
struct  Border  ffbg1=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdbg1,
    NULL
    };

struct  IntuiText   fftg6=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "RAD:",
    NULL
    };
struct  Gadget  ffg6=
    {
    &ffg7,
    12+5*48, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg6,
    NULL,
    NULL,
    6,
    NULL
    };

struct  IntuiText   fftg5=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "RAM:",
    NULL
    };
struct  Gadget  ffg5=
    {
    &ffg6,
    12+4*48, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg5,
    NULL,
    NULL,
    5,
    NULL
    };

struct  IntuiText   fftg4=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "DH0:",
    NULL
    };
struct  Gadget  ffg4=
    {
    &ffg5,
    12+3*48, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg4,
    NULL,
    NULL,
    4,
    NULL
    };

struct  IntuiText   fftg3=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "DF2:",
    NULL
    };
struct  Gadget  ffg3=
    {
    &ffg4,
    12+2*48, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg3,
    NULL,
    NULL,
    3,
    NULL
    };

struct  IntuiText   fftg2=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "DF1:",
    NULL
    };
struct  Gadget  ffg2=
    {
    &ffg3,
    12+1*48, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg2,
    NULL,
    NULL,
    2,
    NULL
    };

struct  IntuiText   fftg1=
    {
    FFCOLORA, FFCOLORB,
    JAM1,
    8, 4,
    &fffont,
    "DF0:",
    NULL
    };
struct  Gadget  ffg1=
    {
    &ffg2,
    12, 5+FFWTOP,
    48, 16,
    GADGHCOMP | GADGDISABLED,
    RELVERIFY,
    BOOLGADGET,
    ( APTR )&ffbg1,
    NULL,
    &fftg1,
    NULL,
    NULL,
    1,
    NULL
    };


SHORT   ffdb0[ 5*2 ]=
    {
    0, 0,
    17*8+3+3, 0,
    17*8+3+3, 12,
    0, 12,
    0, 0
    };
struct  Border  ffb0b=
    {
    1, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdb0,
    NULL
    };
struct  Border  ffb0=
    {
    0, 0,
    FFCOLORA, FFCOLORB,
    JAM1,
    5,
    (SHORT *)&ffdb0,
    &ffb0b
    };



struct  NewWindow   ffnewwindow=
    {
    NULL, NULL,
    FFWWIDTH, FFWHEIGHT,
    FFCOLORA, FFCOLORB,
    GADGETUP | GADGETDOWN,
    WINDOWDRAG | SMART_REFRESH |  ACTIVATE | RMBTRAP ,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    0, 0,
    0, 0,
    CUSTOMSCREEN
    };

BYTE    ffshow[ FFMAXLINE ][ FFLINELEN+1 ];

LONG    ffshown, ffshowtop, fflasttop;
LONG    ffdiskfree;
LONG    fflock;
SHORT   ffreadstatus;

extern struct DosLibrary *DOSBase;

struct  Window      *ffwindow;
struct  RastPort    *ffrp;
struct  FileInfoBlock   *fffib;
struct  InfoData    *ffid;
struct  ffdata      *ffdatag;

SHORT   lastpos=-1;     /*   non sarebbe necessario   */


/****************   MAIN ENTRY POINT   *****************/
LONG filefinder( data )
    struct  ffdata  *data;
{
    LONG    errore;
    struct  IntuiMessage    *message;
    ULONG   class;
    ULONG   secs, millisecs;
    ULONG   lsecs, lmillisecs;
    BOOL    doubleclick;
    struct  Gadget  *gadget, *hitg;
    USHORT  gid;
    SHORT   pos;
    LONG    ret;
    LONG    i23;
    LONG    readret;
    LONG    i;
    SHORT   dlen;
    

    ffdatag=data;
    ffwindow=NULL;
    fflock=NULL;
    lsecs=lmillisecs=0;
    hitg=NULL;
    
    fffib=(struct  FileInfoBlock *)AllocMem( sizeof( struct FileInfoBlock ), MEMF_PUBLIC );
    ffid=(struct InfoData *)AllocMem( sizeof( struct InfoData ), MEMF_PUBLIC );
    if( !fffib || !ffid )
        {
        ret=FFERROR;
        goto fine;
        }

    ffsg19.Buffer=data->suffix;
    ffsg20.Buffer=data->path;
    ffsg21.Buffer=data->file;

    errore=ffopenwindow();
    if( errore )
        {
        ret=FFERROR;
        goto fine;
        }

    ffdiskfree=ffshowtop=ffshown=0;
    if( data->valid )
        {
        for( i=0; i<data->shown; ++i )
            ffaddshow( i );
        ffshowtop=data->showtop;
        ffdiskfree=data->diskfree;
        ffreadstatus=0;
        }
    else
        ffreadstatus=1;
    ffsetprop();
    ffoutdiskfree( ffdiskfree );

    FOREVER     /* Main Loop */
        {
        if( !ffreadstatus && !hitg )
            WaitPort( ffwindow->UserPort );
        while( message=(struct IntuiMessage *)GetMsg( ffwindow->UserPort ) )
            {
            class=message->Class;
            secs=message->Seconds;
            millisecs=message->Micros;
            gadget=(struct Gadget *)message->IAddress;
            gid=gadget->GadgetID;
            ReplyMsg( (struct Message *)message );

            switch( gid )
                {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                    strcpy( data->path, gadget->GadgetText->IText );
                    ffchangepath();
                    break;
                case 7:
                case 19:
                case 20:
                    ffreadstatus=1;
                    ActivateGadget( &ffg21, ffwindow, NULL);
                    break;
                case 8:
                    dlen=strlen( data->path );
                    for( ; dlen>0; --dlen )
                        if( data->path[ dlen-1 ]==':' ||
                                    data->path[ dlen ]=='/' )
                            break;
                    data->path[ dlen ]='\0';
                    ffchangepath();
                    break;
                case 9:
                case 21:
                    ret=FFOK;
                    goto fine;
                case 10:
                    ret=FFCANCEL;
                    goto fine;
                case 11:
                case 12:
                case 13:
                case 14:
                case 15:
                case 16:
                case 17:
                case 18:
                    if( class==GADGETDOWN )
                        {
                        hitg=gadget;
                        break;
                        }
                    if( ffreadstatus==1 )
                        {
                        DisplayBeep( data->screen );
                        break;
                        }
                    ffunlock();
                    ffreadstatus=0;     /*   ferma la lettura della dir   */
                    if( (pos=ffshowtop+(gid-11))>ffshown-1 ||
                            data->line[ pos ].type==0 )
                        {
                        DisplayBeep( data->screen );
                        break;
                        }
                    if( pos==lastpos && secs-lsecs<2 &&
                            (secs-lsecs)*1000000+millisecs-lmillisecs<600000 )
                        doubleclick=TRUE;
                    else
                        doubleclick=FALSE;
                    lastpos=pos;
                    lsecs=secs;
                    lmillisecs=millisecs;
                    if( data->line[ pos ].type>0 && doubleclick )
                        {
                        dlen=strlen( data->path );
                        if( ffreadstatus==1 ||
                                dlen+strlen( data->line[ pos ].name )+1>FFPATHLEN )
                            {
                            DisplayBeep( data->screen );
                            break;
                            }
                        if( dlen && data->path[ dlen-1 ]!=':' )
                            {
                            data->path[ dlen ]='/';
                            data->path[ ++dlen ]='\0';
                            }
                        strcpy( &(data->path[ dlen ]), data->line[ pos ].name );
                        ffchangepath();
                        }
                    if( data->line[ pos ].type<0 )
                        {
                        strcpy( data->file, data->line[ pos ].name );
                        RefreshGadgets( &ffg21, ffwindow, NULL );
                        ActivateGadget( &ffg21, ffwindow, NULL);
                        if( doubleclick )
                            {
                            ret=FFOK;
                            goto fine;
                            }
                        }
                    break;
                case 22:
                case 23:
                    if( class==GADGETDOWN )
                        {
                        i23=0;
                        do
                            {
                            if( (gid==22 && ffshowtop>0) || (gid==23 && ffshowtop<ffshown-FFLINENUM) )
                                {
                                gid==22 ? ffshowtop-- : ffshowtop++;
                                ffsetprop();
                                }
                            if( !i23 )
                                for( ; i23<15000; i23++ )
                                    if( !(gadget->Flags & SELECTED) )
                                        break;
                            }while( gadget->Flags & SELECTED );
                        }
                    break;
                case 24:
                    do
                        {
                        fflasttop=ffshowtop;
                        ffshowtop=ffshown>FFLINENUM ? ((ULONG)(ffshown-FFLINENUM)*ffpg24.VertPot+(1<<15))>>16 : 0;
                        if( ffshowtop!=fflasttop )
                            ffshowall();
                        }while( ffg24.Flags & SELECTED );
                    break;
                }
            }
        if( hitg )
            if( !(hitg->Flags & SELECTED) )
                {
                hitg=NULL;
                ffshowall();
                }
        if( ffreadstatus==1 )
            {
            ffshown=ffshowtop=0;
            lastpos=-1;     /*   azzera doppio click   */
            ffsetprop();
            data->valid=FALSE;
            ffunlock();
            fflock=Lock( data->path, ACCESS_READ );
            if( fflock )
                {
                Info( fflock, ffid );
                ffoutdiskfree( ((ffid->id_NumBlocks-ffid->id_NumBlocksUsed)*ffid->id_BytesPerBlock)/1024 );
                readret=Examine( fflock, fffib );
                if( readret && fffib->fib_DirEntryType>0 )
                    ffreadstatus=2;
                else
                    ffunlock();        /* Adesso esegui |  */
                }                      /*               |  */
            if( !fflock )              /*             <-   */
                {
                DisplayBeep( data->screen );
                ffoutdiskfree( FFDFNOVALID );
                data->valid=TRUE;
                ffreadstatus=0;
                }
            }
        if( ffreadstatus==2 )
            {
            readret=ExNext( fflock, fffib );
            if( readret )
                ffaddline();
            else
                {
                ffunlock();
                ffreadstatus=0;
                data->valid=TRUE;
                }
            }
        }

fine:
    data->file[ FFFILELEN-strlen(data->suffix) ]='\0';
    strcpy( data->complete, data->path );
    dlen=strlen( data->complete );
    if( dlen && data->path[ dlen-1 ]!=':' )
        {
        data->complete[ dlen ]='/';
        data->complete[ ++dlen ]='\0';
        }
    strcpy( &(data->complete[ dlen ]), data->file );
    strcpy( &(data->complete[ strlen(data->complete) ]), data->suffix );
    data->shown=ffshown;
    data->showtop=ffshowtop;
    data->diskfree=ffdiskfree;

    ffunlock();
    if( ffwindow )
        CloseWindow( ffwindow );
    if( fffib )
        FreeMem( fffib, sizeof(struct FileInfoBlock) );
    if( ffid )
        FreeMem( ffid, sizeof(struct InfoData) );

    return( ret );
}


/*****   Apre finestra e disegna tutto   *****/
LONG ffopenwindow( void )
{
    struct  TextFont    *font;

    ffnewwindow.LeftEdge=(ffdatag->screen->Width)/2-FFWWIDTH/2;
    ffnewwindow.TopEdge=(ffdatag->screen->Height)/2-FFWHEIGHT/2;
    ffnewwindow.Title=ffdatag->title;
    ffnewwindow.Screen=ffdatag->screen;

    ffwindow=(struct Window *)OpenWindow( &ffnewwindow );
    if( ffwindow==NULL )
        return( 1 );
    ffrp=ffwindow->RPort;

    font=(struct TextFont *)OpenFont( &fffont );
    SetFont( ffrp, font );

    SetBPen( ffrp, FFCOLORB );
    SetAPen( ffrp, FFCOLORA );
    RectFill( ffrp, 2, FFWTOP+1, FFWWIDTH-1-2, FFWHEIGHT-1-1 );
    SetAPen( ffrp, FFCOLORB );
    RectFill( ffrp, 4, FFWTOP+2, FFWWIDTH-1-4, FFWHEIGHT-1-2 );
    SetAPen( ffrp, FFCOLORS );
    RectFill( ffrp, 235, 44+FFWTOP, 64+4+235-1, 10+44+FFWTOP-1 );
    RectFill( ffrp, 51, 56+FFWTOP, 248+4+51-1, 10+56+FFWTOP-1 );
    RectFill( ffrp, 51, 146+FFWTOP, 248+4+51-1, 10+146+FFWTOP-1 );
    SetAPen( ffrp, FFCOLORA );
    RectFill( ffrp, 279, 80+FFWTOP, 302, 131+FFWTOP );
    DrawBorder( ffrp, &ffb0, 9, 41+FFWTOP );

    fffinddevices();

    AddGList( ffwindow, &ffg1, 0, -1, NULL );
    RefreshGadgets( &ffg1, ffwindow, NULL );

    Move( ffrp, 11, 5+FFWTOP );
    Draw( ffrp, 11, 20+FFWTOP );
    Move( ffrp, 12+6*48, 5+FFWTOP );
    Draw( ffrp, 12+6*48, 20+FFWTOP );

    ActivateGadget( &ffg21, ffwindow, NULL);

    return( 0 );
}


/*****   Stampa tutto uno schermo di linee   *****/
void ffshowall( void )
{
    COUNT     i;
    
    for( i=0; i<FFLINENUM; i++ )
        {
        Move( ffrp, 13, 70+i*9+7+FFWTOP );
        SetAPen( ffrp, ffdatag->line[ ffshowtop+i ].type<0 ? FFCOLORA : FFCOLORA2 );
        Text( ffrp, ffshowtop+i<ffshown ? ffshow[ ffshowtop+i ] :
                    "                                 ", FFLINELEN );
        }
}


/*****   Setta il Vert.Body della scroll bar   *****/
void ffsetprop( void )
{
    USHORT  body, pot;

    body=ffshown>FFLINENUM ? (ULONG)(FFLINENUM*0xFFFF)/ffshown : 0xFFFF;
    pot=ffshown>FFLINENUM ? FFMIN( 0xFFFF, ((ffshowtop<<16))/(ffshown-FFLINENUM)) : 0;
    NewModifyProp( &ffg24, ffwindow, NULL, ffpg24.Flags, 0, pot, 0, body, 1 );
    ffshowall();
}


/*****   E` stato modificato il path   *****/
void ffchangepath( void )
{
    ((struct StringInfo *)ffg20.SpecialInfo)->BufferPos=
            ((struct StringInfo *)ffg20.SpecialInfo)->DispPos=
            strlen(ffdatag->path)-30>0 ? strlen(ffdatag->path)-30 : 0 ;
    RefreshGadgets( &ffg20, ffwindow, NULL );
    ActivateGadget( &ffg21, ffwindow, NULL);
    ffreadstatus=1;
}


/*****   Se c'e` un lock lo toglie   *****/
void ffunlock( void )
{
    if( fflock )
        {
        UnLock( fflock );
        fflock=0;
        }
}


/*****   Aggiunge una linea alla lista dei files   *****/
LONG ffaddline( void )
{
    LONG   pos, i;
    SHORT   slen, flen;

    if( ffshown==FFMAXLINE )
        {
        ffdatag->line[ --ffshown ].type=0;
        ffaddshow( ffshown );
        ffshowall();
        ffreadstatus=0;
        ffunlock();
        ffdatag->valid=TRUE;
        return( 0 );
        }

    slen=0;
    if( fffib->fib_DirEntryType<0 && (
            (flen=strlen(fffib->fib_FileName)) < (slen=strlen(ffdatag->suffix)) ||
            ffstrcmpu( &(fffib->fib_FileName[ flen-slen ]), ffdatag->suffix ) ) )
        return( 0 );

    for( pos=0; pos<ffshown; pos++ )
        if( fffib->fib_DirEntryType>0==ffdatag->line[ pos ].type>0 )
            {
            if( ffstrcmpu( fffib->fib_FileName, ffdatag->line[ pos ].name )<0 )
                break;
            }
        else
            if( fffib->fib_DirEntryType>0 )
                break;

    for( i=ffshown; i>pos; i-- )
        ffdatag->line[ i ]=ffdatag->line[ i-1 ];

    strcpy( ffdatag->line[ pos ].name, fffib->fib_FileName );
    ffdatag->line[ pos ].name[ strlen(ffdatag->line[ pos ].name)-slen ]='\0';
    ffdatag->line[ pos ].size=fffib->fib_Size;
    ffdatag->line[ pos ].type=fffib->fib_DirEntryType;
    ffaddshow( pos );

    ffshowtop=ffshown>FFLINENUM ? ((ULONG)((ffshown-1)-FFLINENUM)*ffpg24.VertPot+(1<<15))>>16 : 0;
    ffsetprop();
}


/*****   Aggiunge una linea a show alla posizione pos   *****/
LONG ffaddshow( LONG pos )
{
    COUNT   i;
    BYTE    buff[ 9 ];
    
    if( ffdatag->line[ ffshown ].type==0 )
        {
        strcpy( ffshow[ ffshown++ ], "*******  TOO MANY FILES  ********");
        return( 0 );
        }
    
    for( i=ffshown; i>pos; i-- )
        strcpy( ffshow[ i ], ffshow[ i-1 ] );

    buff[ 0 ]=' ';

    strcpy( ffshow[ pos ], ffdatag->line[ pos ].name );
    for( i=strlen(ffshow[ pos ]); i<FFLINELEN; i++ )
        ffshow[ pos ][ i ]=' ';
    if( ffdatag->line[ pos ].type<0 )
        {
        i=stcu_d( &(buff[ 1 ]), ffdatag->line[ pos ].size );
        strcpy( &(ffshow[ pos ][ FFLINELEN-i-1 ]), buff );
        }
    else
        strcpy( &(ffshow[ pos ][27]), " <Dir>" );
    ffshown++;

}


/*****   Compara due stringe considerate Uppercase   *****/
ffstrcmpu( s, t )
    UBYTE   *s, *t;
{
    while( *s && *t && FFTOUP( *s )==FFTOUP( *t ) )
        {
        ++s;
        ++t;
        }
    return( (LONG)( FFTOUP( *s )-FFTOUP( *t ) ) );
}


/*****   Stampa memoria libera su disco   *****/
void ffoutdiskfree( ULONG k )
{
    BYTE    buff[ 7 ];
    SHORT   i;

    SetAPen( ffrp, FFCOLORDF0 );
    RectFill( ffrp, 11, 42+FFWTOP, 11-1+17*8+4, 42-1+11+FFWTOP );
    SetAPen( ffrp, FFCOLORDF1 );
    SetDrMd( ffrp, JAM1 );

    if( k==FFDFNOVALID )
        {
        Move( ffrp, 13, 50+FFWTOP );
        Text( ffrp, novalidpath, NOVALIDPATHLEN );
        SetAPen( ffrp, FFCOLORDF2 );
        Move( ffrp, 13+2, 50+FFWTOP );
        Text( ffrp, novalidpath, NOVALIDPATHLEN );
        }
    else
        {
        i=stcu_d( buff, k );
        Move( ffrp, 13, 50+FFWTOP );
        Text( ffrp, "Disk free:", 10 );
        Text( ffrp, buff, i );
        SetAPen( ffrp, FFCOLORDF2 );
        Move( ffrp, 13+10*8+2, 50+FFWTOP );
        Text( ffrp, buff, i );
        SetAPen( ffrp, FFCOLORDF1 );
        Text( ffrp, "k", 1 );
        }

    SetDrMd( ffrp, JAM2 );
    ffdiskfree=k;
}


/*****   Cerca i DEVICES realmente esistenti   *****/
void fffinddevices( void )
{
    struct  DeviceList  *dev;
    UBYTE   *name;
    struct  Gadget  *g;
    COUNT   i;

    for( g=&ffg1; g!=&ffg7; g=g->NextGadget )
        g->Flags|=GADGDISABLED;
    dev=(struct DeviceList *)BADDR( (((struct DosInfo *)BADDR( ((struct RootNode *)DOSBase->dl_Root)->rn_Info ))->di_DevInfo) );
    do
        {
        if( dev->dl_Type!=DLT_DEVICE )
            continue;
        name=(UBYTE *)BADDR( (LONG)(dev->dl_Name) );
        if( *(name++)!=3 )
            continue;        /* uso solo devices di 3 lettere */
        for( g=&ffg1; g!=&ffg7; g=g->NextGadget )
            {
            for( i=0; i<3; ++i )
                if( *(name+i)!=*(g->GadgetText->IText+i) )
                    break;
            if( i==3 )
                g->Flags^=GADGDISABLED;
            }
        }while( dev=(struct DeviceList *)BADDR( dev->dl_Next ) );
}



/******************   Fine routines FILE-FINDER   ***************************/

