#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>

#define INTUITION      0x00000001
#define GRAPHICS      0x00000002
#define WINDOW         0x00000004
#define INITDIRLOCKOK      0x00000008
#define ESC         0x1b
#define RAMSHOW "ram:SHOW"
#define FBSIZE  (long)(sizeof (struct FileInfoBlock))
#define MAXFILE      100
#define MAXFNAME   13
#define MAXCHAR      30
#define MAXCD      255

#define SLIDE_GADGET   0
#define ERR_GADGET   3
#define CURDIR_GADGET   4
#define CPDIR_GADGET   5
#define DF0_GADGET   6
#define DF1_GADGET   7
#define DF2_GADGET   8
#define HD0_GADGET   9
#define RAM_GADGET   10
#define SWAP_GADGET   11
#define ALL_GADGET   12
#define CLEAR_GADGET   13
#define COPY_GADGET   14
#define RENAME_GADGET   15
#define DELETE_GADGET   16
#define PARENT_GADGET   17
#define GETDIR_GADGET   18
#define MAKEDIR_GADGET  19
#define DELETEDIR_GADGET 20
#define ROOT_GADGET     21
#define TYPE_GADGET   22
#define PRINT_GADGET   23
#define SINFO_GADGET   24
#define DINFO_GADGET   25
#define BYTE_GADGET   26
#define EXECUTE_GADGET   27
#define SHOW_GADGET   28
#define BUT_FIRST DF0_GADGET
#define FIRST_GADGET   But_gad[22]
#define KILL_SHOW   But_gad[22]
#define BUT_LAST   SHOW_GADGET
#define WinIDCMP  CLOSEWINDOW | REFRESHWINDOW | GADGETUP | MOUSEBUTTONS

extern struct FileHandle  *Open();
extern APTR AllocMem();
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct IntuiMessage *message;
struct RastPort *rp;
struct Window *w;

/*Errore Gadget stringa gadget*/
USHORT str_pairs2[] = { 0,0,  639,0,  639,9,  0,9, 0,0,};
struct Border str_border2 =
{
   -1,-1,/*AngoloSinistro, AngoloAlto*/
   1,1,JAM1,/*FrontPen, BackPen, Drawmode*/
   5,   /*Numero di Pair*/
   (APTR) &str_pairs2,  /*XY, Puntatore al pair XY*/
   NULL,
};

/*Errore display*/
char err_buf[MAXCD+1];
struct StringInfo err_str =
{ &err_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };

struct Gadget Err_gad =
{
   NULL, /*ultimo nel list di gadget*/
   10,120,
   628,9,
   GADGHCOMP, GADGIMMEDIATE | RELVERIFY | STRINGCENTER,
   STRGADGET,
   (APTR) &str_border2,
   NULL,
   NULL,  /*puntatore Intuitext*/
   0,&err_str,
   ERR_GADGET,
   NULL,
};

/*Destinazione sorgente stringa gadgets*/
USHORT str_pairs[] = { 0,0,  280,0,  280,9,  0,9, 0,0,};
struct Border str_border =
{
   -1,-1,/*AngoloSinistro, AngoloAlto*/
   1,1,JAM1,/*FrontPen, BackPen, Drawmode*/
   5,   /*Numero di Pair*/
   (APTR) &str_pairs,  /*XY, Puntatore al pair XY*/
   NULL,
};
struct IntuiText Curdir_text = {1,0,JAM1,283,0,NULL,"S",NULL,};
char cd_buf[MAXCD+1];
struct StringInfo Curdir_str =
{ &cd_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };
struct Gadget Curdir_gad =
{
   &Err_gad,
   345,100,
   278,9,
   GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
   STRGADGET,
   (APTR) &str_border,
   NULL,
   &Curdir_text,
   0,
   &Curdir_str,
   CURDIR_GADGET,
   NULL,
};

/*Destinazione definizioni*/
char cp_buf[MAXCD+1];
struct IntuiText Cpdir_text = {1,0,JAM1,283,0,NULL,"D",NULL,};
struct StringInfo Cpdir_str =
{ &cp_buf, NULL, 0, MAXCD+1,  0, 0, 0, 0, 2,0, NULL, 0, NULL, };

struct Gadget Cpdir_gad =
{
   &Curdir_gad,
   345,110,
   278,9,
   GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
   STRGADGET,
   (APTR) &str_border,
   NULL,
   &Cpdir_text,
   0,
   &Cpdir_str,
   CPDIR_GADGET,
   NULL,
};

/*File che Seleziona le Dichiarazioni dei Gadget*/
struct Image slide_img;
struct PropInfo slide_prop;
struct Gadget Slide_gad =
{
   &Cpdir_gad,  /*Prossimo gadget*/
   322,12,     /*Angolo Sinistro, Alto*/
   20,108,     /*Larghezza Altezza*/
   GADGHNONE,   /*Flags*/
   GADGIMMEDIATE | RELVERIFY,
   PROPGADGET,  /*Gadget type*/
   (APTR)&slide_img,   /*definizione Bordo*/
   NULL, /*Seleziona il render*/
   NULL,     /*Gadget testo*/
   0,     /*Esclusione reciproca*/
   (APTR) &slide_prop, /*Info Speciali - specificazione proporzionale*/
   SLIDE_GADGET,
   NULL,
};

/*ID del Gadget tasto*/

struct IntuiText But_text[] =
{
   3,2,JAM2,0,0,NULL,"  DF0:  ",NULL,
   3,2,JAM2,0,0,NULL,"  DF1:  ",NULL,
   3,2,JAM2,0,0,NULL,"  DF2:  ",NULL,
   3,2,JAM2,0,0,NULL,"  DH0:  ",NULL,
   3,2,JAM2,0,0,NULL,"  RAM:  ",NULL,
   3,2,JAM2,0,0,NULL,"  SWAP  ",NULL,
   3,2,JAM2,0,0,NULL,"  ALL   ",NULL,
   3,2,JAM2,0,0,NULL," CLEAR  ",NULL,
   3,2,JAM2,0,0,NULL,"  COPY  ",NULL,
   3,2,JAM2,0,0,NULL," RENAME ",NULL,
   3,2,JAM2,0,0,NULL," DELETE ",NULL,
   3,2,JAM2,0,0,NULL," PARENT ",NULL,
   3,2,JAM2,0,0,NULL," GETDIR ",NULL,
   3,2,JAM2,0,0,NULL,"MAKEDIR ",NULL,
   3,2,JAM2,0,0,NULL," DELDIR ",NULL,
   3,2,JAM2,0,0,NULL,"  ROOT  ",NULL,
   3,2,JAM2,0,0,NULL,"  TYPE  ",NULL,
   3,2,JAM2,0,0,NULL," PRINT  ",NULL,
   3,2,JAM2,0,0,NULL," SINFO  ",NULL,
   3,2,JAM2,0,0,NULL," DINFO  ",NULL,
   3,2,JAM2,0,0,NULL,"  BYTE  ",NULL,
   3,2,JAM2,0,0,NULL,"  EXEC  ",NULL,
   3,2,JAM2,0,0,NULL,"  SHOW  ",NULL,
};

struct Gadget But_gad[] =
{
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DF0_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DF1_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DF2_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,HD0_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,RAM_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,SWAP_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,ALL_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,CLEAR_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,COPY_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,RENAME_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DELETE_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,PARENT_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,GETDIR_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,MAKEDIR_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DELETEDIR_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,ROOT_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,TYPE_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,PRINT_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,SINFO_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,DINFO_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,BYTE_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,EXECUTE_GADGET,NULL,
   NULL,5,174,64,8,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,BOOLGADGET,
   NULL,NULL,NULL,NULL,NULL,SHOW_GADGET,NULL,
};

/*DEFINIZIONE DEL BORDO PER LA SELEZIONE AREA FILE*/
USHORT Fil_pairs[] = { 10,13,  321,13,  321,120, 10,120, 10,13,};
struct Border Fil_border =
{
   -1,-1,    /*AngoloSinistro, AngoloAlto*/
   1,0,JAM1,    /*FrontPen, BackPen, Drawmode*/
   5,        /*Numero di Pair*/
   (APTR) Fil_pairs,   /*XY, Puntatore al pair XY*/
   NULL,    /*Piu' bordi*/
};


struct NewWindow nw =
{
   0,11,
   640,130,
   0,1,       /*Detail, block pens*/
   WinIDCMP,    /*IDCMP flags*/
   WINDOWSIZING | WINDOWDEPTH | WINDOWDRAG | REPORTMOUSE | WINDOWCLOSE
   | ACTIVATE | RMBTRAP | SMART_REFRESH,
   &FIRST_GADGET, /*Primo gadget nel list*/
   NULL,    /*Segno di controllo dell'utente*/
   "DirUtil III",
   NULL,  
   NULL,    /*Puntatore alla superbitmap*/
   100,40,640,125,  /*Ora dimensionabile*/
   WBENCHSCREEN,
};

/*La seguente struttura viene usata per mantenere le entrate alla directory*/
struct DirTable
{
   char  dt_fname[MAXCHAR];/*nome File*/
   short dt_select; /*Seleziona flag*/
   short dt_dir;   /*Directory flag*/
   long  dt_size;   /*Dimensioni File*/
};

struct DirTable dirtable[MAXFILE+1];
struct FileLock *fl;
struct InfoData *InfoData;
struct FileLock *InitialCurrentDirLock;
struct FileLock *CurrentDirLock;
struct FileLock *RAMSHOWLOCK;
struct FileHandle *window = NULL; /*manipolazione file per scrittura e stampa*/
struct FileHandle *workfp = NULL; /*manipolazione file per il file da visualizzare*/
long bytes;
int files;
int cmp_dt();
int ac;
int numdir;
int cur_index;
int NILFD = 0;
unsigned int mask = 0;
char curdir[MAXCD+1],requestedcd[MAXCD+1];
char command[300];
unsigned char buf[512];
void   Print_to_printer(), cleanup(), copy(), new_dir(),
   sel_file(), par_dir(), Print_to_screen();
struct FileLock *oldlock;

main(argc,argv)
char *argv[];
{
   struct Gadget *gad_ptr;
   struct IntuiText *text_ptr;
   ULONG MessageClass;
   USHORT code;
   register i;
   ac = argc;

   if(!(NILFD = Open("nil:",MODE_OLDFILE))) {
      if (ac = 2) puts("Can't open NIL:\n");
      exit();
   }
   if((ac == 0) || (ac == 2)){
      copy("SYS:C/SHOW","ram:");
      RAMSHOWLOCK = Lock(RAMSHOW,ACCESS_READ);
   }

   *cp_buf = 0;
   strcpy(curdir,"ram:");
   strcpy(requestedcd,curdir);
   if(!(CurrentDirLock = Lock(curdir,ACCESS_READ))) {
      if (ac == 2) puts("Could not lock RAMdisk!\n");
      close_things(); exit();
   }
   mask |= INITDIRLOCKOK;
   InitialCurrentDirLock = CurrentDir(CurrentDirLock);

   /*Inizializzazione Gadget*/
   slide_prop.Flags = FREEVERT | AUTOKNOB;
   slide_prop.VertBody = 0;
   slide_prop.VertPot = 0x8000;

   /*Setup del tasto dei gadgets*/
   for (i=0;i<(BUT_LAST-BUT_FIRST)+1;i++) {
      gad_ptr = &But_gad[i];
      text_ptr = &But_text[i];

      gad_ptr->LeftEdge = ((i%4) * 71) + 343;
      gad_ptr->TopEdge = ((i/4) * 12) + 12;

      if(i)
         gad_ptr->NextGadget = &But_gad[i-1];
      else
         gad_ptr->NextGadget = &Slide_gad;
      gad_ptr->GadgetText = text_ptr;
      text_ptr->LeftEdge = 0;
      text_ptr->TopEdge = 0;
   }

GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0); 

mask |= GRAPHICS;

IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0);

mask |= INTUITION;

if (!(w = (struct Window *) OpenWindow(&nw) )) {
   if (ac == 2) puts("Could not open window\n");
   close_things();   exit();
}
mask |= WINDOW;

   rp = w->RPort;
   DrawBorder(rp,&Fil_border,0,0);

   getdir(curdir);
   new_dir();

   display_error("O.K.",0);
   RefreshGadgets(&FIRST_GADGET,w,NULL);
   if(!RAMSHOWLOCK) OffGadget(&KILL_SHOW,w,NULL);

   for (;;) {
      WaitPort(w->UserPort); 
      message = (struct IntuiMessage *) GetMsg(w->UserPort);
      MessageClass = message->Class;
      code = message->Code;
      ReplyMsg(message);
      switch (MessageClass) {
         case GADGETUP:
         case GADGETDOWN:
            display_error("O.K.",0);
            do_gadgets(message,w);
            break;

         case REFRESHWINDOW:
            BeginRefresh(w); EndRefresh(w);
            dis_files(cur_index);
            DrawBorder(rp,&Fil_border,0,0);
            break;

         case CLOSEWINDOW:
            close_things(); exit();
            break;

         case MOUSEBUTTONS:
            if (code == SELECTDOWN) sel_file();
            break;
         default:
            break;
      } /*fine switch*/
   } /*fine for*/
}

Info2(dir)
char *dir;
{
InfoData = AllocMem(sizeof(struct InfoData),0);
fl = Lock(dir,ACCESS_READ);
Info(fl,InfoData);
sprintf(command,"%d Usable Bytes Free",((InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed - 2) <= 0) ? 0 : ((InfoData->id_NumBlocks - InfoData->id_NumBlocksUsed - 2) * InfoData->id_BytesPerBlock));
display_error(command,0);
FreeMem(InfoData,sizeof(struct InfoData));
UnLock(fl);
}

do_gadgets(mes,win)
struct IntuiMessage *mes;
struct Window *win;
{
   struct FileLock *MakeDirLock;
   struct Gadget *igad;
   int gadgid;       /*Codice ID per l'identificazione del gadget*/
   register i;

   igad = (struct Gadget *) mes->IAddress;
   gadgid = igad->GadgetID;
   switch (gadgid) {
      case CURDIR_GADGET:
         ModifyIDCMP(w,0);
         nullterm(cd_buf,MAXCD);
         Curdir_str.NumChars = strlen(cd_buf);
         Curdir_str.BufferPos = strlen(cd_buf);
         getdir(cd_buf);
         new_dir();
         ModifyIDCMP(w,WinIDCMP);
         break;
      case ERR_GADGET:
         nullterm(err_buf,MAXCD);
         err_str.NumChars = strlen(err_buf);
         err_str.BufferPos = strlen(err_buf);
         break;
      case CPDIR_GADGET:
         nullterm(cp_buf,MAXCD);
         Cpdir_str.NumChars = strlen(cp_buf);
         Cpdir_str.BufferPos = strlen(cp_buf);
         break;
      case SLIDE_GADGET:
         rdis_files();
         break;
      case ROOT_GADGET:
      case PARENT_GADGET:
         par_dir(gadgid);
         break;
      case SHOW_GADGET:
         display_error("Now showing selected pictures",0);
      case DELETE_GADGET:
      case COPY_GADGET:
      case RENAME_GADGET:
      case TYPE_GADGET:
      case PRINT_GADGET:
      case EXECUTE_GADGET:
      case DELETEDIR_GADGET:
         action_on_selected(gadgid);
         break;
      case SWAP_GADGET:
         strcpy(command,cd_buf);
         strcpy(cd_buf,cp_buf);
         strcpy(cp_buf,command);
         Cpdir_str.NumChars = strlen(cp_buf);
         Cpdir_str.BufferPos = strlen(cp_buf);
         RefreshGadgets(&Cpdir_gad,w,NULL);
         getdir(cd_buf);
         new_dir();
         break;
       case SINFO_GADGET:
         Info2(cd_buf);
         break;
      case DINFO_GADGET:
         Info2(cp_buf);
         break;
      case BYTE_GADGET:
         bytes = 0;
         files = 0;
         for (i=0;i<numdir;i++)
         if ((dirtable[i].dt_select == 1) && (!(dirtable[i].dt_dir))) {
            bytes = bytes + dirtable[i].dt_size;
            files++;
         };
         sprintf(command,"%d Bytes in %d Files",bytes,files);
         display_error(command,0);
         break;
      case MAKEDIR_GADGET:
         if(MakeDirLock = Lock(cp_buf,ACCESS_READ)) {
            UnLock(MakeDirLock);
            display_error("DIRECTORY / FILE ALREADY EXISTS " ,IoErr());
            break;
         } 
         if (!(MakeDirLock = CreateDir(cp_buf))) {
            display_error("CreateDir FAILED ",IoErr());
            break;
         }
         UnLock(MakeDirLock);
         getdir(curdir); new_dir(); break;
      case DF0_GADGET:
         getdir("df0:"); new_dir(); break;
      case DF1_GADGET:
         getdir("df1:"); new_dir(); break;
      case DF2_GADGET:
         getdir("df2:"); new_dir(); break;
      case RAM_GADGET:
         getdir("ram:"); new_dir(); break;
      case HD0_GADGET:
         getdir("dh0:"); new_dir(); break;
      case GETDIR_GADGET: 
         getdir(requestedcd);
         new_dir();
         break;
      case CLEAR_GADGET:
         for (i=0;i<numdir;i++)
         dirtable[i].dt_select = 0;
         dis_files(cur_index);
         break;
      case ALL_GADGET:
         for (i=0;i<numdir;i++)
         if (!dirtable[i].dt_dir) dirtable[i].dt_select = 1;
         dis_files(cur_index);
         break;
      default:
         break;
   }
}

getdir(DirToGet) 
char *DirToGet;
{
   struct FileLock *filelock;
   struct FileInfoBlock *fb;
   char EffectiveDir[MAXCD+1];

   if (!(*DirToGet)) strcpy(EffectiveDir,":");
   else strcpy(EffectiveDir,DirToGet);

   /*Se non possiamo aprire la dir richiesta, non cambia*/
TRYAGAIN:
   if (!(filelock = Lock(EffectiveDir,ACCESS_READ))) {
      strcpy(EffectiveDir,curdir);
      display_error("CAN'T LOCK REQUESTED DIRECTORY ",IoErr());
      if(!(filelock = Lock(EffectiveDir,ACCESS_READ))) {
         display_error("CAN'T LOCK CURRENT DIR. SWITCHING TO RAM: ",IoErr());
         strcpy(EffectiveDir,"ram:");
         goto TRYAGAIN;
      }
   }
   /*Colloca il blocco info del file*/
   fb = AllocMem(FBSIZE,MEMF_CLEAR | MEMF_PUBLIC);
   if (!Examine(filelock,fb)) {
      FreeMem(fb,FBSIZE);
      UnLock(filelock);
      display_error("CAN'T READ INFO BLOCK. SWITCHING TO RAM: ",IoErr());
      strcpy(EffectiveDir,"ram:");
      goto TRYAGAIN;
   }
   if(fb->fib_DirEntryType < 0) {  /*E' UN FILE- NON UNA DIRECTORY*/
      strcpy(EffectiveDir,curdir);/*Dimentica la richiesta, usa la corrente*/
      FreeMem(fb,FBSIZE);
      UnLock(filelock);
      display_error("DIRECTORY REQUESTED WAS REGULAR FILE - NO CHANGES ",IoErr());
      goto TRYAGAIN;
   }

   /*Copia la stringa della directory nella struttura gadget*/
   strcpy(cd_buf,EffectiveDir);
   Curdir_str.NumChars = strlen(EffectiveDir);
   Curdir_str.BufferPos = strlen(EffectiveDir);
   strcpy(curdir,EffectiveDir);
   strcpy(requestedcd,EffectiveDir);
   RefreshGadgets(&Cpdir_gad,w,NULL);

   numdir = 0;
   cur_index = 0;

   /*Loop attraverso ciascun file della directory*/
   while (ExNext(filelock,fb)) {
      if (fb->fib_DirEntryType < 0) dirtable[numdir].dt_dir = 0;
      else dirtable[numdir].dt_dir = -1;
      dirtable[numdir].dt_select = 0;
      dirtable[numdir].dt_size = fb->fib_Size;
      strcpy(dirtable[numdir].dt_fname,fb->fib_FileName);
      nullterm(dirtable[numdir].dt_fname,MAXCHAR);

      if (++numdir == MAXFILE) break;
   }

   qsort(dirtable,numdir,(sizeof (struct DirTable)),cmp_dt); 
   FreeMem(fb,FBSIZE);
   UnLock(CurrentDirLock); /*Rilascia il vecchio CD lock */
   UnLock(filelock);    /*Rilascia il nuovo lock richiesta*/
   CurrentDirLock = Lock(EffectiveDir);
   CurrentDir(CurrentDirLock);
}

rdis_files()
{
 USHORT Vpot;
   int numd;
   int pos;

   if (numdir > MAXFNAME) {
   Vpot = slide_prop.VertPot;
      Vpot >>= 1;
      Vpot &= 0x7fff;
      numd = numdir - MAXFNAME;
      pos = ((float) Vpot / (float) 0x7fff) * numd;
      cur_index = pos;
      dis_files(pos);
   }
}

void new_dir()
{
   USHORT Vbody;

   if (numdir <= MAXFNAME) 
      Vbody = 0xffff;
   else {
      Vbody = ((float) 0x7fff)/(((float) numdir)/((float) MAXFNAME));
      Vbody <<= 1;
   }
   cur_index = 0;
   ModifyProp(&Slide_gad,w,NULL,slide_prop.Flags,0,0,0,Vbody);
   dis_files(0);
   return;
}

void cleanup()
{
register i;
register temp;
temp = numdir;
for (i=0;i<numdir;i++)    
if (dirtable[i].dt_select == 2) {
   strcpy(dirtable[i].dt_fname,"zzzzzzzzzzzzzzz");
   temp--; 
};
if (numdir != temp) qsort(dirtable,numdir,(sizeof (struct DirTable)),cmp_dt); 
numdir = temp;
} 

dis_files(pos)
int pos;
{
   register i;

   for (i=0;i<MAXFNAME;i++) dis_name(i+pos,i);
}

dis_name(file,pos)
register file;
register pos;
{
static char file_name[MAXCHAR+8];
static struct IntuiText file_text = {2,0,JAM2,15,13,NULL,(UBYTE *)file_name,NULL };

   /*Setta la posizione alta*/
   file_text.TopEdge = (pos*8)+14;

   if (file == -1 || file >= numdir) {
      sprintf(file_name,"%-38.38s","");
      file_text.FrontPen = 2;
      file_text.BackPen = 2;  /*nero*/
   } else {
      if (dirtable[file].dt_dir) {
         sprintf(file_name,"%-30.30s%-8.8s",dirtable[file].dt_fname,"");
         if (dirtable[file].dt_select) {
            file_text.FrontPen = 2; /*Nero e Arancio*/
            file_text.BackPen = 3;
         } else {
            file_text.FrontPen = 3; /*Arancio e Nero*/
            file_text.BackPen = 2;
         }
      } else {
         sprintf(file_name,"%-30.30s %7ld",dirtable[file].dt_fname,
         dirtable[file].dt_size);
         if (dirtable[file].dt_select) {
            file_text.FrontPen = 2; /*Nero su Bianco*/
            file_text.BackPen = 1;
         } else {
            file_text.FrontPen = 1; /*Bianco su Nero*/
            file_text.BackPen = 2;
         }
      }
   }

   /*Visualizza il testo*/
   PrintIText(rp,&file_text,0,0);
}

void sel_file()
{
   int file,i;
   char *ptr;

   if (message->MouseX < 12 || message->MouseX > 318)
      return;
   if (message->MouseY < 16 || message->MouseY >= (MAXFNAME*8+16))
      return;
   file = message->MouseY - 16;
   file /= 8;
   if((!numdir) || (file > MAXFNAME) || ((file+cur_index) > numdir))
      return;

   /*Controlla per vedere se la selezione riguarda una directory o un file */
   /*Per adesso, e' permesso selezionare una diractory alla volta*/
   if (dirtable[file+cur_index].dt_dir) {
      for(i=0;i<numdir;i++)
      if((dirtable[i].dt_dir)&&(i != file+cur_index)) dirtable[i].dt_select = 0;
      ptr = curdir + strlen(curdir) - 1;
      if(dirtable[file+cur_index].dt_select ^= 1) 
         sprintf(requestedcd,"%s%s%s",curdir,((*ptr == ':') ? "":"/"),
         dirtable[file+cur_index].dt_fname);
      else
         strcpy(requestedcd,curdir);
      dis_files(cur_index);
      return;
   }
   dirtable[file+cur_index].dt_select ^= 1;
   dis_name(file+cur_index,file);
}

action_on_selected(gadgid)
int gadgid;
{
   struct IntuiMessage *message;
   register i;
   char filename[MAXCD+MAXCHAR+2];
   char *ptr;
   /*Ad ogni iterazione controlla per dei IntuiMessages che potrebbero
   segnalare l'intenzione dell'utente di fermare l'operazione*/
   ModifyIDCMP(w,GADGETUP | MOUSEBUTTONS);
   for (i=0;i<numdir;i++) {
      if((gadgid != SHOW_GADGET) && (message = (struct IntuiMessage *) GetMsg(w->UserPort))) {
         ReplyMsg(message);
         display_error("OPERATION HALTED",0);
         break; 
      }   
      if (dirtable[i].dt_select) {
         ptr = curdir + strlen(curdir)-1;
         if (*ptr == ':')
            sprintf(filename,"%s%s",curdir,dirtable[i].dt_fname);
         else
            sprintf(filename,"%s/%s",curdir,dirtable[i].dt_fname);

         switch (gadgid) {
            case DELETE_GADGET:
               if(dirtable[i].dt_dir) {
                  display_error("FILE IS A DIRECTORY",0);
                  break;
               }
               if(!(DeleteFile(filename))) {
                  display_error("COULD NOT DELETE REQUESTED FILE ",IoErr());
               } else { dirtable[i].dt_select = 2;};
               break;

            case DELETEDIR_GADGET:
               if(!dirtable[i].dt_dir) {
                  display_error("FILE IS NOT A DIRECTORY",0);
                  break;
               }
               if(!(DeleteFile(filename))) {
                  display_error("COULD NOT DELETE REQUESTED DIRECTORY ",IoErr());
               } else { dirtable[i].dt_select = 2;};
               break;

            case COPY_GADGET:
               copy(filename,cp_buf);
               break;

            case SHOW_GADGET:
               if(RAMSHOWLOCK) {
                  sprintf(command,"%s %s",RAMSHOW,filename);
                  if (ac == 0) Execute(command,0,NILFD);
                  else Execute(command,0,0);
               }
               break;
            case EXECUTE_GADGET:            
               sprintf(command,"%s",filename);
               if (ac == 0) Execute(command,0,NILFD);
               else Execute(command,0,0);
               break;
            case TYPE_GADGET:
               if(!dirtable[i].dt_dir) Print_to_screen(filename);
               break;
            case PRINT_GADGET:
               if(!dirtable[i].dt_dir) Print_to_printer(filename);
               break;
            case RENAME_GADGET:
            /*NOTE: dovete selezionare il file da rinominare*/
               if(!(Rename(filename,cp_buf))) 
               display_error("CANNOT RENAME TO REQUESTED PATH ",IoErr());
               break;
            default:
            break;
         } /*switch*/
if ((gadgid != DELETEDIR_GADGET) && (gadgid != DELETE_GADGET)) dirtable[i].dt_select = 0;
   if(RENAME_GADGET == gadgid) break; /*RENAME FIRST FILE ONLY!*/
      } /*se selezionato*/
   } /*per tutto*/

if(RENAME_GADGET == gadgid) getdir(curdir); else
cleanup();
new_dir(); 
ModifyIDCMP(w,WinIDCMP);
}

void par_dir(gadgid) /*Parent e Root*/
   int gadgid; {
   char *ptr;       /*Con questo, possiamo cambiare la Dir corrente*/

   ModifyIDCMP(w,0);
   ptr = curdir+strlen(curdir)-1;
   if(PARENT_GADGET == gadgid)
      for (;ptr >= curdir;ptr--) {
         if (*ptr == ':') { 
            *(ptr+1) = 0; 
            break;
         }
         if (*ptr == '/') { 
            *ptr = 0;
            break;
         }
      }
   else
      for (;ptr >= curdir;ptr--) 
         if (*ptr == ':') {
            *(ptr+1) = 0;
            break;
         }

   getdir(curdir);
   new_dir();
   ModifyIDCMP(w,WinIDCMP);
   return;
}

/*La funzione seguente compara due entrate di directory*/
cmp_dt(dt1,dt2)
struct DirTable *dt1,*dt2;
{
   char *ptr1,*ptr2;
   register c1,c2;

   for (ptr1=dt1->dt_fname,ptr2=dt2->dt_fname;*ptr1 && *ptr2;ptr1++,ptr2++) {
      c1 = *ptr1;
      c2 = *ptr2;

      c1 &= 0xdf;
      c2 &= 0xdf;

      if (c1 > c2) return (-1);

      if (c1 < c2) return (1);
   }

   if (*ptr1) return (-1);

   if (*ptr2) return (1);

   return (0);
}

void copy(s,pc)
char *s;
char *pc;
{
   struct FileHandle  *copyin;
   struct FileHandle  *copyout;
   int iosize;
   int actual;
   char *copybuf;
   struct FileLock *fl;
   char *ptr;
   char *ptr1;

   if (!(copyin = Open(s,MODE_OLDFILE)))
      return;

   if (!*pc) {
      display_error("NO DESTINATION PATH GIVEN",0);
      return;
   }

   if ((fl = Lock(pc,ACCESS_READ))) {
      UnLock(fl);
      ptr = strlen(pc) + pc - 1;
      for (ptr1=s+strlen(s)-1;ptr1 > s;ptr1--) {
         if (*ptr1 == '/' || *ptr1 == ':')
            break;
      }
      if (*ptr1 == '/' || *ptr1 == ':')
         ptr1++;
      if (*ptr == ':')
         sprintf(command,"%s%s",pc,ptr1);
      else
       sprintf(command,"%s/%s",pc,ptr1);
   } else {
      display_error("ILLEGAL DESTINATION PATH ",IoErr());
      Close(copyin);
      return;
   }

   if (!strcmp(command,s)) {
      display_error("CANNOT COPY FILE TO ITSELF",0);
      Close(copyin);
      return;
   }

   if (!(copyout = Open(command,MODE_NEWFILE))) {
      display_error("COPY CANNOT WRITE TO REQUESTED PATH ",IoErr());
      Close(copyin);
      return;
   } else {
      /*Determina la lunghezza del file*/
      iosize = Seek(copyin,0,OFFSET_BEGINING);
      iosize = 12288;
      /*Colloca la memoria per copiare il buffer*/
      do {
         copybuf = AllocMem(iosize,MEMF_PUBLIC);
         if (copybuf == 0)
            iosize = iosize/2;
      } while (copybuf == 0 & iosize > 512);

      /*Copia il file*/
      do {
         actual = Read(copyin,copybuf,iosize);
         if (Write(copyout,copybuf,actual) != actual)
            break;
      } while (actual == iosize);

      /*Libera la copia buffer*/
      FreeMem(copybuf,iosize);

      /*Chiude i buffer di input e output*/
      Close(copyout);
      Close(copyin);
   }
}

nullterm(str,len) /*Finisce una stringa con un null*/
char *str;
int len;
{
   register i;

   str[len] = 0; 
   for (i=len;len >= 0;len--) {
      if (str[i] != ' ' && str[i])
         break;
      str[i] = 0;
   }
}

display_error(errormsg,doserrnum)
char *errormsg;
long doserrnum;
{
   strcpy(err_buf,errormsg);
   if (doserrnum) sprintf(err_buf,"%s (DOS Error %d)",err_buf,doserrnum);
   err_str.NumChars = strlen(err_buf);
   err_str.BufferPos = strlen(err_buf);
   RefreshGadgets(&Err_gad,w,NULL);
}

close_things()
{
   if (mask & WINDOW)
      CloseWindow(w);

   if (mask & GRAPHICS)
      CloseLibrary(GfxBase);

   (void) OpenWorkBench();

   if (mask & INTUITION)
      CloseLibrary(IntuitionBase);

   if(RAMSHOWLOCK) {
      UnLock(RAMSHOWLOCK);
      DeleteFile(RAMSHOW);
   }
      Close(NILFD);

   if(mask & INITDIRLOCKOK) {
      CurrentDir(InitialCurrentDirLock);
      UnLock(CurrentDirLock);
 }
}

qsort( v, n, size, comp)
char *v;
int n;
int size;
int (*comp)();
{
   register gap, i, j, x, cnt;
   char temp, *p1, *p2;

   cnt = 0;
   for (gap=n/2;gap > 0; gap /= 2)
      for (i=gap; i<n; i++)
         for (j = i-gap; j >= 0; j -= gap)
            if ( (*comp) ( (p1=v+j*size), (p2=v+(j+gap)*size) ) < 0) {  
               cnt++;
               /*exchange them*/
               for (x=0; x<size; x++) {
                  temp = *p1;
                  *p1++ = *p2;
                  *p2++ = temp;
               }
            }
   return(cnt);
}
void Print_to_screen(ptr)
char *ptr[];
{

register i, len, len2; /*loop e contatore variabili*/
int linecount = 1; /*conto delle linee visualizate sullo schermo*/
int done = FALSE; /*variabili booleane*/
unsigned char c; /*carattere letto dalla tastiera*/

workfp = Open(ptr,MODE_OLDFILE); 
if(workfp == NULL) done = TRUE;
else{
   window = Open("raw:0/0/640/200/",MODE_NEWFILE);
   if(window == NULL) done = TRUE;
}
strcpy(command,"\x1b[33m<CR>\x1b[2m advances one line, \x1b[33mSpace Bar\x1b[2m");
Write(window,command,strlen(command));
strcpy(command," advances one page, and \x1b[33mESC\x1b[2m aborts.\n\x1b[0m");
Write(window,command,strlen(command));
if (!done)
   do{
      len = Read(workfp,buf,512);
      len2 = 0;
      while (len2<len){
         for (i=len2; buf[i] != 0x0a && i<511; i++)
         if (buf[i] == 0x0c) buf[i] = 0x20;         
         Write(window,&buf[len2],i-len2+1);
         len2 = i + 1;
      if (++linecount >= 22 && buf[i] == 0x0a){
      linecount = 1;
      /*stampa il messaggio nel colore 3*/
      strcpy(command,"\x1b[33mPress SPACE for more...\x1b[0m");
      Write(window,command,strlen(command));
      /*attendere per un tasto*/
      while(Read(window,&c,1),c != ' ')
         if (c == ESC){
         len = 0; /*circuito corto*/
         break;
      }
   /*RETURN scrolla di una riga*/
    else if (c == '\r'){
      linecount = 21;
      break;
   }
   /*cancella il messaggio*/
   strcpy(command, "\r                        \r");
   Write(window,command,strlen(command));
      }
      }
   }while(len == 512);
   /*If not chiude il programma*/
   if (!done){
      strcpy(command,"\r\x1b[33mEnd of File.  Press SPACE\x1b[0m");
      Write(window,command,strlen(command));
   /*Attende la barra spaziatrice per uscire*/
   while(Read(window,&c,1),c != ' ');
   }

   if(workfp) Close(workfp);
   if(window) Close(window);
   return;
}
void Print_to_printer(ptr)
char *ptr[];
{

register len; /*loop e contatore variabili*/
int done = FALSE; /*variabili booleane*/

   workfp = Open(ptr,MODE_OLDFILE); /*Cerca di aprire il file da stampare*/
   if(workfp == NULL) done = TRUE;
   else {
      window = Open("prt:",MODE_NEWFILE);
      if(window == NULL) done = TRUE;
   }
   if (!done)
      do{
         len = Read(workfp,buf,512);
         Write(window,&buf[0],len);
      }while(len == 512);

   if(workfp) Close(workfp);
   if(window) Close(window);
   return;
}
