#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos/dos.h>
#include <dos/datetime.h>
#include <xpk/xpk.h>
#include <clib/xpkmaster_protos.h>
#include <pragmas/xpkmaster_lib.h>
#include <libraries/gadtools.h>
#include <workbench/startup.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <intuition/classusr.h>
#include <intuition/icclass.h>
#include <datatypes/datatypes.h>
#include <datatypes/datatypesclass.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/wb_protos.h>
#include <clib/datatypes_protos.h>
#include <clib/utility_protos.h>
#include <clib/asl_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/locale_protos.h>
#include <clib/alib_protos.h>

#include "list.h"
#include "strutture_define.h"
#include "amytree_func.h"
#include "AMLOCALE.h"
#include "ExtGui.h"
#include "IDatGui.h"



extern APTR       vi;
extern STRPTR leftcar(STRPTR,int);
extern STRPTR _fgets(STRPTR buf , int n, FILE *fp);
extern ERRORE(STRPTR);

extern struct NewGadget NewGad, CerGad;
extern struct Gadget *UserButton5,*UserButton6,*UserButton7,*UserButton8,
                     *UserButton3,*UserButton4, *wingads[];
extern STRPTR  showername, playername, userprg1, userprg2,
               userprg3, userprg4, userprg5, userprg6,
               userprg7, userprg8;
extern struct Gadget *MyGadList, *PrevGad, *Num_Files, *Num_Dirs, *View_String,
                     *ViewButton, *ScrollerVert, *ScrollerOriz, *ApriButton, *ChiudiButton,
                     *InfoButton, *CercaButton, *CerGadList, *CerStr, *CerPrev,
                     *ShowButton,*UserButton1,*UserButton2,*filelist, 
                     *Rec_Lev,*PlayButton,*on_off,*OpenBranch;

extern STRPTR  userprgname1, userprgname2,userprgname3,userprgname4;
extern STRPTR  userprgname5, userprgname6,userprgname7,userprgname8;

extern struct IntuiMessage *imsg;
extern struct Screen *PubScreen;
extern struct Window *w, *vis, *cer;
extern struct Image right,left,down,up,chiusa,aperta,vuota;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct Library *GadToolsBase;
extern struct Library *DOSBase;
extern struct Library *UtilityBase;
extern struct Library *WorkbenchBase,*DataTypesBase,*AslBase,*XpkBase;
extern struct IntuiText itxt;
extern struct TextAttr topaz8;
extern struct TextAttr xen8;
extern struct FileRequester *FileReqLoad;
extern struct FileRequester *FileReqSave;
extern struct FileRequester *FileGenTree;
extern struct FileRequester *FileVis;
extern struct TagItem MyTagsSave[];
extern struct TagItem MyTagsVis[];
extern struct Gadget *View_String, *Num_Dirs;
extern struct TextAttr tfont;
extern struct TagItem VertMapping[];
extern struct TagItem HorizMapping[];
extern struct TagItem *tstate,*tags,*tag;
extern struct LocaleInfo locale;
extern struct Remember *rem_key;
extern struct List lista_exts;

extern short int ndir,maxliv;
extern short int xb,yb,y;
extern short int xw, yw, xoff;
extern short int ox,ox1,oy,oy1,topy,boty;
extern node *result;
extern lista_nodi *ln,*pln,*pn;
extern STRPTR showername, playername, userprg1, userprg2;
extern LONG   recl;
extern char   lof;

extern Object *dto,*pvo,*pho;
extern STRPTR packMethod;
extern LONG PackMode;
extern lst_list *DTPList;

exts *g_entry=NULL;
lst_list *tmp_list;
int  flagsel=-1;
struct Remember *rem_key2=NULL;


LONG  easyreq(STRPTR,STRPTR);
STRPTR GetString(struct LocaleInfo *li, LONG stringNum);
void stampa_wintree1(node *root, node *);
void stampa_wintree2(node *root);
void FlushIBuffer(node *root);
void AggiornaListExt(struct Window *win,struct Gadget *wingads[],lst_list *ExtList);
void stampalistadeb(lst_list *);


void stampa_wintree(node *root,short int d, node *dire)
{
   stampa_wintree1(root,dire);
   if(d){
      SetAPen(w->RPort,2);
      stampa_wintree2(root);
      SetAPen(w->RPort,1);
   }
}                         

void stampa_wintree1(node *root,node *dire){
  if(root){ 
     short int xr=(xc(root)-ox+xb)-1,yr=(yc(root)-oy+yb+4);
     if(visibile(root)){
        if(dire!=root) print_text2(root,0); /* Se il nodo e' nella finestra visibile lo stampa */
        else print_text2(dire,2);
        if(padre(root)){
           short int xp=xr-16,yp=(yc(padre(root))-oy+yb+8);
           switch(root->flag1){
              case 0 : DrawImage(w->RPort,&vuota,xr-9,yr-2); /* In base al flag disegna i box */
//              case 0 : draw(xr-1,yr,xp,yr);
                       break;
              case 1 : DrawImage(w->RPort,&aperta,xr-9,yr-2);
                       break;
              case 2 : DrawImage(w->RPort,&chiusa,xr-9,yr-2);
                       break;
           }
           draw(xr-11,yr,xp,yr); /* linea orizzontale a sinistra dei box */          
	   if(visibile(padre(root))) Draw(w->RPort,xp,yp); /* linea verticale fino al nodo padre */
           else if(visibilex(padre(root))) Draw(w->RPort,xp,19); /* linea fino alla prima riga della finestra se il padre e' visibile in x ma non in y */ 
           if((frasucc(root))&&(!visibile(frasucc(root)))) Draw(w->RPort,xp,178); /*yw+yb);*/
        }         
     }
     else
        if(padre(root))           
           if((yc(padre(root))<oy)&&(yc(root)>=oy1))
              if(visibilex(padre(root))){ 
                short int xp=xr-16;
//                draw(xp,topy,xp,boty); 
                draw(xp,19,xp,178); 
              }
     stampa_wintree1(figlio(root),dire);
     stampa_wintree1(frasucc(root),dire);
  } 
}

void stampa_wintree2(node *root)
{
  if(root){ 
     short int xr=(xc(root)-ox+xb)-1,yr=(yc(root)-oy+yb+4)-1;
     if(visibile(root)){
        if(padre(root)){
           short int xp=xr-16,yp=(yc(padre(root))-oy+yb+8);
//           if(root->flag1==0) {
//              draw(xr-1,yr,xp,yr); }
//           else {
              draw(xr-11,yr,xp,yr); 
// }
	   if(visibile(padre(root))){ draw(xp-1,yr,xp-1,yp); } /* linea verticale fino al nodo padre */
           else if(visibilex(padre(root))){ draw(xp-1,yr,xp-1,19); } /* linea fino alla prima riga della finestra se il padre e' visibile in x ma non in y */ 
           if((frasucc(root)!=NULL)&&(!visibile(frasucc(root)))) {draw(xp-1,yr,xp-1,178);}
        } 
     }        
     else
        if(padre(root))           
           if((yc(padre(root))<oy)&&(yc(root)>=oy1))
              if(visibilex(padre(root))){ 
                short int xp=xr-17;
//                draw(xp,topy,xp,boty); 
                draw(xp,19,xp,178);
              }
     stampa_wintree2(figlio(root));
     stampa_wintree2(frasucc(root));
  } 
}


void gen_coo(node *root)
{
   if(root!=NULL){
      xc(root)=xb+xoff*liv(root); 
      yc(root)=(y+=tfont.ta_YSize);
      gen_coo(figlio(root));
      gen_coo(frasucc(root));
   }
}


void cerca_node(int my, node *nodo){  
  if(nodo!=NULL){
//    if((my>=yc(nodo)+PubScreen->Font->ta_YSize-8)&&(my<=yc(nodo)+PubScreen->Font->ta_YSize-1)) result=nodo;
    if((my>=yc(nodo))&&(my<=yc(nodo)+7)) result=nodo; 
    else{
      cerca_node(my,frasucc(nodo));
      cerca_node(my,figlio(nodo));     
    }
  }  
} 

void max_liv(node *nodo){
  if(nodo!=NULL){
    if(liv(nodo)>=maxliv) maxliv=liv(nodo);
    max_liv(frasucc(nodo));
    max_liv(figlio(nodo));        
  }  
} 

void print_text(struct RastPort *rp, struct IntuiText *intxt,char *str, int pen, int pen2, int xo, int yo, LONG dm)
{
  intxt->IText=str;
  intxt->DrawMode=dm;
  intxt->FrontPen=pen;
  intxt->BackPen=pen2;
  intxt->ITextFont=&tfont; /*&xen8;*/
  PrintIText(rp,intxt,xo,yo);
}

void print_text2(node *root,UBYTE cl){
  short int cx;
  cx=ox1-(xc(root)+(strlen(name(root))*8));
  if(cx<0){
     STRPTR str=NULL;
     str=leftcar(name(root),strlen(name(root))+(cx/8));
     print_text(WIN(w),str,1,cl,xc(root)-ox+xb,yc(root)-oy+yb,JAM2);
//     print_text(WIN(w),str,2,cl,xc(root)-ox+xb-1,yc(root)-oy+yb-1,0);
     if(str) free(str);
  }
  else{
     print_text(WIN(w),name(root),1,cl,xc(root)-ox+xb,yc(root)-oy+yb,JAM2);
//     print_text(WIN(w),name(root),2,cl,xc(root)-ox+xb-1,yc(root)-oy+yb-1,0);
  }
}

int del_tree(node *root){
  int i=0;
  if(root){
     i++;
     i+=del_tree(figlio(root));
     i+=del_tree(frasucc(root));
     free(name(root));
     free(fullpath(root));      
     if(root->plfiles) DelListList(root->plfiles); /* <-- cancella lista plainfiles */
     free(root);
   }
   return i;
}

void FlushIBuffer(node *root)
{
   if(root){
      FlushIBuffer(figlio(root));
      FlushIBuffer(frasucc(root));
      if(root->plfiles){
         DelListList(root->plfiles);
         root->plfiles=NULL;
         root->list=FALSE;
         root->nf=0;
      }
   }
}

void free_list(void){
  pn=pln;
  while(pn!=NULL){ pln=pln->succ; free(pn); pn=pln; }
  ln=NULL;
}  

void cerca_node_1(STRPTR stringa, node *nodo){  
  if(nodo!=NULL){
     if((Strnicmp(stringa,name(nodo),strlen(stringa))==0)){
        if((ln=(lista_nodi *)malloc(sizeof(lista_nodi)))==NULL) ERRORE("Fine memoria");
        ln->fnode=nodo;
        ln->succ=NULL;
        if(pln!=NULL) pln->succ=ln;
        else pn=ln;
        pln=ln;
     }
     cerca_node_1(stringa,figlio(nodo));
     cerca_node_1(stringa,frasucc(nodo));    
  }  
} 

node * crea_node(void){
   node *dire;
   if((dire=(node *)malloc(sizeof(node)))==NULL) ERRORE("Fine memoria");
   name(dire)=NULL;
   fullpath(dire)=NULL;
   padre(dire)=NULL;
   liv(dire)=0;
   dire->flag1=0;
   figlio(dire)=NULL;
   fraprec(dire)=NULL;
   frasucc(dire)=NULL;
   xc(dire)=0; yc(dire)=0;
   size(dire)=-1;
   dire->plfiles=NULL;
   dire->list=FALSE;
   dire->nf=0;
   return dire;
}

void agg_figlio(node *padre, node *figlio)
{
  if(figlio(padre)==NULL) figlio(padre)=figlio;
  else{
    node *nodo=figlio(padre),*nodoprec=nodo;
    while(nodo!=NULL){
       if(stricmp(name(nodo),name(figlio))>0){
          frasucc(figlio)=nodo;
          fraprec(figlio)=fraprec(nodo);
          if(fraprec(figlio)) frasucc(fraprec(figlio))=figlio;
          else figlio(padre)=figlio;
          fraprec(nodo)=figlio;
          break;
       }
       else{
          nodoprec=nodo;
          nodo=frasucc(nodo);
       }
    } 
    if(nodo==NULL){
       frasucc(nodoprec)=figlio;
       fraprec(figlio)=nodoprec;
    }   
  }
}

int chiudi_dir(node *dire){
   int i=0;
   node *temp;
   if(dire->flag1==2)
      if((temp=figlio(dire))!=NULL){ 
         i=del_tree(temp);
         figlio(dire)=NULL;
         dire->flag1=1;
      }
   return i;
}  

     
void save_tree(node *root, STRPTR file, BOOL xpk)
{
  FILE *fp;
  char filename[108],oldfilename[108];
  if(root){
     if(file==NULL){
        if(AslRequest(FileReqSave,MyTagsSave)){        
           strcpy(oldfilename,FileReqSave->rf_Dir);
           if(AddPart(oldfilename,FileReqSave->rf_File,108)==0) ERRORE("Fatal AddPart");    
        }
        else return;
        strmfe(filename,oldfilename,"tree");
      }
      else strcpy(filename,file);
      if((fp=fopen(filename,"w"))==NULL) return;
      fprintf(fp,FILEHEADER);
      fprintf(fp,"\n");
      SetWindowPointer(w,WA_BusyPointer,TRUE,TAG_DONE);
      salva(fp,root);
      fclose(fp);
      if(xpk){
        if(XpkBase){
           strmfe(oldfilename,filename,"xpktree");
           XpkPackTags(XPK_InName,     filename,
                       XPK_OutName,    oldfilename,
                       XPK_PackMethod, packMethod,
                       XPK_PackMode,   PackMode,
                       TAG_DONE); 
           if(!DeleteFile(filename)) easyreq("Errore: DeleteFile","OK");
           else Rename(oldfilename,filename); 
        }         
        else easyreq("XPK not found, sorry","OK");
     }
     SetWindowPointer(w,WA_Pointer,NULL,TAG_DONE);
   }     
  else DisplayBeep(w->WScreen);
}

void salva(FILE *fp, node * root){
  if(root!=NULL){
     fprintf(fp,"%s\n",name(root));
     fprintf(fp,"%s\n",fullpath(root));
     fprintf(fp,"%d\n",liv(root));
     fprintf(fp,"%d\n",root->flag1);

     fprintf(fp,"%d\n",root->nf);
     if(root->nf) salva_lstfiles(fp,root);

     salva(fp,figlio(root));
     salva(fp,frasucc(root));
  } 
}

void salva_lstfiles(FILE *fp, node *dire)
{
   PlainFile *entryfile;

   entryfile=HEAD(dire->plfiles,PlainFile);
 
   while(entryfile!=NULL){      
      fwrite(entryfile,sizeof(PlainFile),1,fp);
      entryfile=SUCC(entryfile,PlainFile);
   }
}

node *load_tree_new(STRPTR filename)
{  
  node *root=NULL,*prec,*corr;
  FILE *fp;
  short int i,f;
  char buf[400],xfilename[]=".treeTmp",x=0;  
  struct XpkFib xFib;
  STRPTR tmp;

  if(XpkBase){
     XpkExamineTags(&xFib,
                    XPK_InName, filename, 
                    TAG_DONE);
     if(xFib.xf_Type){
        if(!XpkUnpackTags(XPK_InName,  filename,
                          XPK_OutName, xfilename,
                          TAG_DONE)){ filename=xfilename; x=1; }
     }
  }
  if((fp=fopen(filename,"r"))==NULL) return NULL;
  if(strcmp((tmp=_fgets(buf,31,fp)),FILEHEADER)!=0){
     easyreq(GetString(&locale,MSG_ERRFILE),"OK");
     fclose(fp);
     return NULL;
  }

  SetWindowPointer(w,WA_BusyPointer,TRUE,TAG_DONE);

//  _fgets(buf,400,fp);
  root=crea_node();
  tmp=_fgets(buf,400,fp);
  if((name(root)=(STRPTR)malloc(strlen(tmp)+1))==NULL) ERRORE("Fine memoria"); 
  strcpy(name(root),tmp); 
  tmp=_fgets(buf,400,fp); 
  if((fullpath(root)=(STRPTR)malloc(strlen(tmp)+1))==NULL) ERRORE("Fine memoria"); 
  strcpy(fullpath(root),tmp);
  liv(root)=atoi(_fgets(buf,400,fp));
  root->flag1=atoi(_fgets(buf,400,fp));
  root->nf=atoi(_fgets(buf,400,fp));

  root->plfiles=carica_lstfiles(fp,root->nf);
  if(root->plfiles!=NULL) root->list=TRUE;

  prec=root;
  while((tmp=_fgets(buf,400,fp))!=NULL){
    ndir++;
    corr=crea_node();
    if((name(corr)=(STRPTR)malloc(strlen(tmp)+1))==NULL) ERRORE("Fine memoria"); 
    strcpy(name(corr),tmp);
    tmp=_fgets(buf,400,fp);
    if((fullpath(corr)=(STRPTR)malloc(strlen(tmp)+1))==NULL) ERRORE("Fine memoria"); 
    strcpy(fullpath(corr),tmp);
    liv(corr)=atoi(_fgets(buf,400,fp));
    corr->flag1=atoi(_fgets(buf,400,fp));

    corr->nf=atoi(_fgets(buf,400,fp));
    corr->plfiles=carica_lstfiles(fp,corr->nf);
    if(corr->plfiles!=NULL) corr->list=TRUE;



    f=liv(corr)-liv(prec);
    if(f==1){ figlio(prec)=corr; padre(corr)=prec; }
    if(f<0){ f=-f; for(i=0;i<=f;i++) prec=padre(prec); 
             agg_figlio(prec,corr); padre(corr)=prec;
           }                                    
    if(f==0){ agg_figlio(padre(prec),corr); padre(corr)=padre(prec); }
    prec=corr;
  }
  fclose(fp);
  if(x)DeleteFile(filename);     
  SetWindowPointer(w,WA_Pointer,NULL,TAG_DONE);
  return root;
}

lst_list * carica_lstfiles(FILE *fp, int nf)
{
   lst_list *pfiles=NULL;
   int i;

   if(nf) pfiles=MakeList();

   for(i=0;i<nf;i++){
      PlainFile *entryfile;
      if(!(entryfile=(PlainFile *)malloc(sizeof(PlainFile)))) ERRORE("Fine memoria");
      fread(entryfile,sizeof(PlainFile),1,fp);
      ADDTAIL(pfiles,entryfile);
   }
  
   return pfiles;
}

int apri_dir(STRPTR path, node *dire, LONG RV)
{
   BPTR lock;
   struct FileInfoBlock *FIB=NULL;
   int oldir=ndir;
   STRPTR filepath;

   if(dire->flag1==1){     
      if((filepath=(STRPTR)malloc(400))==NULL) ERRORE("Fine memoria");
      strcpy(filepath,path);
      if((lock=Lock(path,ACCESS_READ))==0){
         easyreq(GetString(&locale,MSG_ERRTREE),"OK");
         return 0;
      }
      FIB=AllocDosObject(DOS_FIB,NULL);
      if(Examine(lock,FIB)==0) ERRORE("Fatal Examine");  

      listr(FIB,lock,filepath,dire,liv(dire),RV); 
      dire->flag1=2;
      UnLock(lock);
      FreeDosObject(DOS_FIB, FIB);  
   }
   return (ndir-oldir);
}

BYTE espandi_tutto(node *root)
{  
   BYTE err=1;
   if(root!=NULL){
      if(root->flag1==1){
         struct FileInfoBlock *FIB;
         BPTR lock;
         STRPTR path;
         if((path=(STRPTR)malloc(400))==NULL) ERRORE("Fine memoria");
         strcpy(path,fullpath(root));
         if((lock=Lock(fullpath(root),ACCESS_READ))==0){
            easyreq(GetString(&locale,MSG_ERRTREE),"OK");
            return 0;
         } 
         FIB=AllocDosObject(DOS_FIB,NULL);
         if(Examine(lock,FIB)==0){ FreeDosObject(DOS_FIB,FIB);  ERRORE("Fatal Examine"); }
         listr(FIB,lock,path,root,liv(root),1000); 
         root->flag1=2;
         FreeDosObject(DOS_FIB, FIB);   
         UnLock(lock);
         free(path);
      }
      err=espandi_tutto(figlio(root));
      err=espandi_tutto(frasucc(root));
   }
   return err;
}


int chiudi_tutto(node *root)
{
   int i=0;
   node *tmp=figlio(root);
   while(tmp!=NULL){
      if(tmp->flag1==2){
         i+=del_tree(figlio(tmp));
         figlio(tmp)=NULL;
         tmp->flag1=1;
      }
      tmp=frasucc(tmp);
   }
   return i;
} 
       

UBYTE esp(STRPTR name)
{
   UBYTE res=0;
   struct FileInfoBlock *FIB=NULL;
   BPTR lock;

   if((lock=Lock(name,ACCESS_READ))==0){
       ERRORE("***Error: Internal 1 please send email to author with this error!");
       exit(1);
   }
   FIB=AllocDosObject(DOS_FIB,NULL);
   if(Examine(lock,FIB)==0) ERRORE("Fatal Examine");  
   while(ExNext(lock,FIB))
      if(FIB->fib_DirEntryType>0){
         res=1;
         break;
      }
   FreeDosObject(DOS_FIB,FIB);
   UnLock(lock);
   return res;
}

void Num_dirs(short int dirs)
{
   GT_SetGadgetAttrs(Num_Dirs, w, NULL,
                     GTNM_Number, dirs,
                     TAG_DONE);
}

node* crea_tree(BPTR lock, STRPTR nm, SHORT lv)
{
   /****************************
    * lock = lock sulla dir nm *
    * nm   = nome della dir    *
    * lv   = livello nodo      *
    ****************************/
   STRPTR dirname;
   struct FileInfoBlock *FIB=NULL; /* File Info Block */
   node *root; 

   if((dirname=(STRPTR)malloc(400))==NULL) ERRORE("Fine memoria"); 
   strcpy(dirname,nm);
   FIB=AllocDosObject(DOS_FIB,NULL); /* Alloca una struttura FIB correttamente allineata */

   if(Examine(lock,FIB)==0) ERRORE("Fatal Examine");
   if(FIB->fib_DirEntryType<0) ERRORE("Fatal plain file!!!");
   root=crea_node(); xc(root)=xb; yc(root)=yb;
   if((name(root)=(STRPTR)malloc(strlen(FIB->fib_FileName)+1))==NULL) ERRORE("Fine memoria");
   strcpy(name(root),FIB->fib_FileName);
   if((fullpath(root)=(STRPTR)malloc(strlen(nm)+1))==NULL) ERRORE("Fine memoria");
   strcpy(fullpath(root),nm);
   liv(root)=lv;
   listr(FIB,lock,dirname,root,lv,recl);
   root->flag1=0;
   FreeDosObject(DOS_FIB, FIB);
   return root;
}

void listr(struct FileInfoBlock *FIB, BPTR lock, STRPTR name, node *dire, int liv, int reclev)
{
   STRPTR dirname;
   node *dirnode;
   lst_list *pfiles;
   
   if((dirname=malloc(400))==NULL) ERRORE("Fine memoria");
   strcpy(dirname,name);
   if((fullpath(dire)=(STRPTR)malloc(strlen(name)+1))==NULL) ERRORE("Fine memoria");
   strcpy(fullpath(dire),name);
   dire->flag1=esp(name);
   pfiles=MakeList(); /* <-- Creazione lista di plainfiles*/
   if(reclev-->0){
      while(ExNext(lock,FIB)!=0){
         if(FIB->fib_DirEntryType>0){
            struct FileInfoBlock *FIB1;
            BPTR lock1;
            Num_dirs(ndir++);
            dirnode=crea_node(); 
            if((name(dirnode)=(STRPTR)malloc(strlen(FIB->fib_FileName)+1))==NULL) ERRORE("Fine memoria");
            strcpy(name(dirnode),FIB->fib_FileName);            
            padre(dirnode)=dire;
            agg_figlio(dire,dirnode);
            //size(dire)=FIB->fib_Size;
            dire->flag1=2;
            dirnode->liv=++liv;
            if(AddPart(name,FIB->fib_FileName,400)==0) ERRORE("Fatal AddPart 2");
            FIB1=AllocDosObject(DOS_FIB, NULL);
            if((lock1=Lock(name,ACCESS_READ))==0) ERRORE("Fatal lock");
            if(Examine(lock1,FIB1)==0) ERRORE("Fatal lock1");
            listr(FIB1,lock1,name,dirnode,liv,reclev);
            strcpy(name,dirname);
            UnLock(lock1); FreeDosObject(DOS_FIB, FIB1); liv--;
         }
         else
            if((!dire->list)&&(pfiles)){
               PlainFile *entryfile;
               if(!(entryfile=(PlainFile *)malloc(sizeof(PlainFile)))) ERRORE("Fine memoria");
               strcpy(entryfile->name,FIB->fib_FileName);
               ADDTAIL(pfiles,entryfile);
           }
      }
      if(!dire->list){
         dire->plfiles=pfiles;
         dire->nf=NO_ENTRY(pfiles);
         dire->list=TRUE;
      }
   }
}

STRPTR cerca(){
    BOOL   valid=TRUE;
    ULONG  imsgClass;
    UWORD  imsgCode;
    STRPTR stringcer=NULL;
    struct Gadget *gad;

    CerGadList=NULL;
    CerPrev=CreateContext(&CerGadList);

    NewGad.ng_LeftEdge=PubScreen->WBorLeft;
    NewGad.ng_TopEdge=PubScreen->BarHeight+1;
    NewGad.ng_Width=300;
    NewGad.ng_Height=14;
    NewGad.ng_GadgetText=NULL;
    NewGad.ng_GadgetID = STRING;
 
    CerStr=CerPrev=CreateGadget(STRING_KIND, CerPrev, &NewGad,
                                TAG_DONE);

     cer=OpenWindowTags(NULL,
                   WA_Left,200,
                   WA_Top,100,
                   WA_Width,309,
                   WA_Height,27+PubScreen->Font->ta_YSize-8,
                   WA_Flags,WFLG_DRAGBAR|WFLG_SMART_REFRESH
                           |WFLG_ACTIVATE|WFLG_CLOSEGADGET,                           
                   WA_IDCMP,IDCMP_MOUSEBUTTONS
                           |IDCMP_GADGETUP
                           |IDCMP_CLOSEWINDOW
                           |IDCMP_ACTIVEWINDOW,                           
                   WA_Title,"Insert node",
                   WA_Gadgets,CerGadList,
                   TAG_DONE);

                   GT_RefreshWindow(cer,NULL);

    while(valid)
    {
        Wait(1 << cer->UserPort->mp_SigBit); 
        while(valid && (imsg = GT_GetIMsg(cer->UserPort)))
        {
            imsgClass = imsg->Class;
            imsgCode = imsg->Code;             
            gad = (struct Gadget *)imsg->IAddress;   
            GT_ReplyIMsg(imsg);           
            if(imsgClass==IDCMP_CLOSEWINDOW) { valid=FALSE; break; }
            if(imsgClass==IDCMP_ACTIVEWINDOW) ActivateGadget(CerStr,cer,NULL);
            if(imsgClass==IDCMP_GADGETUP) 
               switch(gad->GadgetID) 
                {              
                    case STRING     : if((stringcer=(STRPTR)malloc(strlen((((struct StringInfo *)gad->SpecialInfo)->Buffer))+1))==NULL) ERRORE("Out of memory!");
                                      strcpy(stringcer,(((struct StringInfo *)gad->SpecialInfo)->Buffer));
                                      valid=FALSE;
                                      break;
                    default         : break;
                }
        
        }
    }
  if(cer) CloseWindow(cer); 
  FreeGadgets(CerGadList);
  return stringcer;
}

void viewfile(STRPTR path){
  ULONG vissig,vsigr,lung,larg;
  BOOL done=TRUE;
  struct IntuiMessage *vimsg;
  ULONG  tidata; /*errnum;*/


    if(dto=NewDTObject(path,
                       ICA_TARGET, ICTARGET_IDCMP,
                       TAG_DONE )){

      GetDTAttrs(dto,
                 DTA_NominalVert,&lung,
                 DTA_NominalHoriz,&larg,
                 TAG_DONE);

      if((lung<=0)||(larg<=40)){ lung=512; larg=640; } /*Temporaneo*/

      vis=OpenWindowTags(NULL,
                   WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_IDCMPUPDATE,                           
	    	   WA_Title,"View file",
                   WA_Flags,WFLG_DRAGBAR|WFLG_SIMPLE_REFRESH|WFLG_NOCAREREFRESH|
                            WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_ACTIVATE,                             
	           WA_NoCareRefresh, TRUE,
		   WA_AutoAdjust, TRUE,
                   WA_Width,  larg+40,
                   WA_Height, lung+32,
		   TAG_DONE	); 
       vissig= 1L << vis->UserPort->mp_SigBit;

       pvo=NewObject(NULL,"propgclass",
                     GA_Left,       vis->Width-vis->BorderRight-PROPW,
                     GA_Top,        vis->BorderTop,
                     GA_Height,     vis->Height - vis->BorderTop - vis->BorderBottom - PROPH,
                     GA_Width,	    PROPW,
                     GACT_RIGHTBORDER, TRUE,
                     PGA_NewLook,   TRUE,
                     ICA_TARGET,    dto,
                     ICA_MAP,       VertMapping,
                     TAG_DONE );

       pho=NewObject(NULL,"propgclass",
                     GA_Left,       vis->BorderLeft,
                     GA_Top,        vis->Height - vis->BorderBottom - PROPH,
                     GA_Height,     PROPH,
                     GA_Width,      vis->Width - vis->BorderLeft - vis->BorderRight - PROPW,
                     GACT_BOTTOMBORDER, TRUE,
                     PGA_NewLook,   TRUE,
                     PGA_Freedom,   FREEHORIZ,
                     ICA_TARGET,    dto,
                     ICA_MAP,       HorizMapping,
                     TAG_DONE );

 
       GT_SetGadgetAttrs(ViewButton, w, NULL,
                         GA_Disabled, TRUE,
                         TAG_DONE);
      
       SetDTAttrs(dto,vis,NULL,
                  GA_Left,    vis->BorderLeft,
                  GA_Top,     vis->BorderTop,
                  GA_Width,   vis->Width - vis->BorderLeft - vis->BorderRight - PROPW,
                  GA_Height,  vis->Height - vis->BorderTop - vis->BorderBottom - PROPH,
                  TAG_DONE);  
 
       AddGadget(vis,(struct Gadget *)pvo,-1);
       AddGadget(vis,(struct Gadget *)pho,-1);
       AddDTObject(vis,NULL,dto,-1); 
 
       RefreshDTObjects(dto,vis,NULL,NULL);
       RefreshGadgets((struct Gadget *)pvo,vis,NULL);

     while(done){
       vsigr=Wait(vissig);
       if(vsigr & vissig){    
         while(vimsg=(struct IntuiMessage*)GetMsg(vis->UserPort)){
           switch(vimsg->Class){
               case IDCMP_IDCMPUPDATE:
                 tstate=tags=(struct TagItem *)vimsg->IAddress;
                 while (tag=NextTagItem(&tstate)) {
                   tidata=tag->ti_Data;
                   switch (tag->ti_Tag) {
                      case DTA_Busy: if (tidata)
                                        SetWindowPointer(vis,WA_BusyPointer,TRUE,TAG_DONE);
                                     else
                                        SetWindowPointer(vis,WA_Pointer,NULL,TAG_DONE);
                                     break;
                      case DTA_Sync: 
                                    RefreshDTObjects(dto,vis,NULL,NULL); 
                                     break;
                      case DTA_Title:
                                     SetWindowTitles(vis,(STRPTR)tag->ti_Data,(STRPTR)~0);
                                     break;
                      case DTA_TopVert:
                                     SetGadgetAttrs((struct Gadget *)pvo,vis,NULL,PGA_Top,tag->ti_Data,TAG_DONE);
                                     break;
                      case DTA_TotalVert:
                                     SetGadgetAttrs((struct Gadget *)pvo,vis,NULL,PGA_Total,tag->ti_Data,TAG_DONE);
                                     break;
                      case DTA_VisibleVert:
                                     SetGadgetAttrs((struct Gadget *)pvo,vis,NULL,PGA_Visible,tag->ti_Data,TAG_DONE);
                                     break;
                      case DTA_TopHoriz:
                                     SetGadgetAttrs((struct Gadget *)pho,vis,NULL,PGA_Top,tag->ti_Data,TAG_DONE);
                                     break;
                      case DTA_TotalHoriz:
                                     SetGadgetAttrs((struct Gadget *)pho,vis,NULL,PGA_Total,tag->ti_Data,TAG_DONE);
                                     break;
                      case DTA_VisibleHoriz:
                                     SetGadgetAttrs((struct Gadget *)pho,vis,NULL,PGA_Visible,tag->ti_Data,TAG_DONE);
                                     break;

                      default:  break;
                   }
                }
                break;

             case IDCMP_CLOSEWINDOW: done=FALSE; break;

             default : break;
           } 
          ReplyMsg((struct Message*) vimsg);
         } 
       }
     } 

    RemoveGadget(vis,(struct Gadget *)pvo);
    DisposeObject(pvo);
    RemoveGadget(vis,(struct Gadget *)pho);
    DisposeObject(pho);
    RemoveDTObject(vis,dto);
    DisposeDTObject(dto);

    CloseWindow(vis);

    GT_SetGadgetAttrs(ViewButton, w, NULL,
                      GA_Disabled, FALSE,
                      TAG_DONE);

   }
   else easyreq(GetString(&locale,MSG_ERRDT),"OK");
}

/*
void SaveAscii(node *root)
{
  if(root){
      printf("\n%s",name(root));
      SaveAsciiSub(figlio(root));
  }
}

void SaveAsciiSub(node *root)
{
  if(root){
     short int i,s;  
     s=liv(root)*3;
     printf("\n");
     for(i=1; i<s; i++){
        printf(" ");             
     }
     printf("|--%s",name(root));
     SaveAsciiSub(figlio(root));
     SaveAsciiSub(frasucc(root));
  }
}
*/

int GetSizeDir(node *dire)
{
  struct FileInfoBlock *FIB=NULL; 
  BPTR lock=NULL;
  int size=0;  
  if(dire!=NULL)
     if((lock=Lock(fullpath(dire),ACCESS_READ))!=0){
        FIB=AllocDosObject(DOS_FIB,NULL);
        if(Examine(lock,FIB)==0) ERRORE("Fatal Examine in GetSizeDir");       
        while(ExNext(lock,FIB)!=0)
           if(FIB->fib_DirEntryType<0) size+=FIB->fib_Size;
        UnLock(lock); FreeDosObject(DOS_FIB, FIB);   
     }                 
  return size;
}

STRPTR GetString(struct LocaleInfo *li, LONG stringNum)
{
   int i=0;
   STRPTR  builtIn;

   while(stringNum!=CatCompArray[i].cca_ID) i++;

   builtIn=CatCompArray[i].cca_Str;

    if (li->li_LocaleBase)
        return(GetCatalogStr(li->li_Catalog,stringNum,builtIn));

    return(builtIn);
}

void AddExtClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
   GT_SetGadgetAttrs(wingads[ProgExt_Gadget5], win, NULL,
                     GA_Disabled, TRUE,
                     TAG_DONE);     
   GT_SetGadgetAttrs(wingads[StringExt_Gadget], win, NULL,
                     GTST_String, NULL,
                     TAG_DONE);     
   GT_SetGadgetAttrs(wingads[DelExt_Gadget], win, NULL,
                     GA_Disabled, TRUE,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[ListExt_Gadget],win,NULL,
                     GTLV_Selected, ~0,
                     TAG_DONE);

   flagsel=-1;
   ActivateGadget(wingads[StringExt_Gadget],win,NULL);

}      

void StringExtClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
  exts *ext_entry;
  
  if(flagsel==-1){
     if(!(ext_entry=(exts*)malloc(sizeof(exts))))ERRORE("Fine memoria");
     if(ext_entry){
         ext_entry->extension[0]=NULL;
         ext_entry->prog[0]=NULL;
         strcpy(ext_entry->extension,getstring(wingads[StringExt_Gadget]));
         ADDTAIL(ExtList,ext_entry);
         g_entry=ext_entry;
         AggiornaListExt(win,wingads,ExtList);
         GT_SetGadgetAttrs(wingads[ProgExt_Gadget5], win, NULL,
                           GA_Disabled, FALSE,
                           GTST_String, NULL,
                           TAG_DONE);     
         ActivateGadget(wingads[ProgExt_Gadget5],win,NULL);
     }
     else ERRORE("Entry NULL(1)");
  }
  else{
     exts *ext_items;
     int i;
     ExtList=tmp_list;
     ext_items=HEAD(ExtList,exts);
     for(i=0;i<flagsel;i++) ext_items=SUCC(ext_items,exts);
     strcpy(ext_items->extension,getstring(wingads[StringExt_Gadget]));     
     AggiornaListExt(win,wingads,ExtList);
     flagsel=-1;
  }  
}      

void ProgExtClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
   if(g_entry){
         strcpy(g_entry->prog,getstring(wingads[ProgExt_Gadget5]));
   }
   else ERRORE("UHMMM...");
}

void AggiornaListExt(struct Window *win,struct Gadget *wingads[],lst_list *ExtList)
{
   struct Node *nodo;
   exts *exts_node;
  
   GT_SetGadgetAttrs(wingads[ListExt_Gadget],win,NULL,
                     GTLV_Labels, NULL,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[ListExt_Gadget],win,NULL,
                     GTLV_Labels, ~0,
                     TAG_DONE);
   FreeRemember(&rem_key2,TRUE);
   if(NO_ENTRY(ExtList)){
      NewList(&lista_exts);
      exts_node=HEAD(ExtList,exts);
      while(exts_node){
         nodo = (struct Node *)AllocRemember(&rem_key2,sizeof(struct Node),MEMF_CLEAR);
         if(nodo==NULL) ERRORE("Fine memoria");
         nodo->ln_Name=(STRPTR)AllocRemember(&rem_key2,strlen(exts_node->extension)+1,NULL);
         if(nodo->ln_Name==NULL) ERRORE("Fine memoria");
         strcpy(nodo->ln_Name,exts_node->extension);
         AddTail(&lista_exts,nodo);
         exts_node=SUCC(exts_node,exts);
      }
      GT_SetGadgetAttrs(wingads[ListExt_Gadget],win,NULL,
                        GTLV_Labels, &lista_exts,
                        TAG_DONE);
   }
}
   
   
void ListExtClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
   int i;
   exts *nod;
   
   nod=HEAD(ExtList,exts);
   for(i=0;i<messagecode;i++) nod=SUCC(nod,exts); 
   
   GT_SetGadgetAttrs(wingads[StringExt_Gadget], win, NULL,
                     GTST_String, nod->extension,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[ProgExt_Gadget5], win, NULL,
                     GTST_String, nod->prog,
                     GA_Disabled, FALSE,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[DelExt_Gadget], win, NULL,
                     GA_Disabled, FALSE,
                     TAG_DONE);

   g_entry=nod;
   flagsel=messagecode;
   tmp_list=ExtList;
   ActivateGadget(wingads[StringExt_Gadget],win,NULL);
}   

void DelExtClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
   int i;
   exts *nod;
   
   ExtList=tmp_list;
   nod=HEAD(ExtList,exts);
   for(i=0;i<flagsel;i++) nod=SUCC(nod,exts); 
   free(REMNODE(ExtList,nod,exts));
   AggiornaListExt(win,wingads,ExtList);
   flagsel=-1;
   GT_SetGadgetAttrs(wingads[DelExt_Gadget], win, NULL,
                     GA_Disabled, TRUE,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[StringExt_Gadget], win, NULL,
                     GTST_String, NULL,
                     TAG_DONE);
   GT_SetGadgetAttrs(wingads[ProgExt_Gadget5], win, NULL,
                     GTST_String, NULL,
                     GA_Disabled,TRUE,
                     TAG_DONE);

}

void ProgSelClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,lst_list *ExtList)
{
  FileVis=AllocAslRequest(ASL_FileRequest,MyTagsVis);  
  if(AslRequest(FileVis,MyTagsVis)){
     strcpy(g_entry->prog,FileVis->rf_Dir);
     AddPart(g_entry->prog,FileVis->rf_File,255);
     GT_SetGadgetAttrs(wingads[ProgExt_Gadget5], win, NULL,
                       GTST_String, g_entry->prog,
                       TAG_DONE);    
  }
  FreeFileRequest(FileVis);  
}

void SaveTypesList(lst_list *DTPList)
{
   if(NO_ENTRY(DTPList)){
      BPTR file;
      dtprogs *nod;
      DeleteFile(PREFS3);   
      if((file=Open(PREFS3,MODE_READWRITE))){
         Write(file,&NO_ENTRY(DTPList),sizeof(int));
         nod=HEAD(DTPList,dtprogs);
         while(nod){
            Write(file,nod,sizeof(dtprogs));
            nod=SUCC(nod,dtprogs);
         }
        Close(file);
      }
   }
}
   

void SaveExtList(lst_list *ExtList)
{
   if(NO_ENTRY(ExtList)){
      BPTR file;
      exts *nod;
      DeleteFile(PREFS2);   
      if((file=Open(PREFS2,MODE_READWRITE))){
         Write(file,&NO_ENTRY(ExtList),sizeof(int));
         nod=HEAD(ExtList,exts);
         while(nod){
            Write(file,nod,sizeof(exts));
            nod=SUCC(nod,exts);
         }
        Close(file);
      }
   }
}

void LoadTypesList(lst_list *DTPList)
{
   BPTR file;
   dtprogs *nod;
   int i;
   if((file=Open(PREFS3,MODE_OLDFILE))){
      Read(file,&i,sizeof(int));
      for(;i>0;i--){
         if(!(nod=(dtprogs*)malloc(sizeof(dtprogs)))) ERRORE("Fine memoria");
         Read(file,nod,sizeof(dtprogs));
         ADDTAIL(DTPList,nod);
      }
      Close(file);
   }
}

void LoadExtList(lst_list *ExtList)
{
   BPTR file;
   exts *nod;
   int i;
   if((file=Open(PREFS2,MODE_OLDFILE))){
      Read(file,&i,sizeof(int));
      for(;i>0;i--){
         if(!(nod=(exts*)malloc(sizeof(exts)))) ERRORE("Fine memoria");
         Read(file,nod,sizeof(exts));
         ADDTAIL(ExtList,nod);
      }
      Close(file);
   }
}

/*   
void stampalistadeb(lst_list *ExtList)
{
   exts *nod;

   printf("\nN.Elementi Lista: %d",NO_ENTRY(ExtList));
   nod=HEAD(ExtList,exts);
   while(nod){
      printf("\n-> %s  -> %s",nod->extension,nod->prog);
      nod=SUCC(nod,exts);
   }
}
*/
/*
char * UserSetupIDatWin(struct Window *win,struct Gadget *wingads[],char *userdata)
{
   GT_SetGadgetAttrs(wingads[TextDat_ID], win, NULL, 
                     GTTX_Text, buf,
                     TAG_DONE);    
}
*/
void ButIDatClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,char *userdata)
{
  char buf[255];
  FileVis=AllocAslRequest(ASL_FileRequest,MyTagsVis);  
  if(AslRequest(FileVis,MyTagsVis)){
     strcpy(buf,FileVis->rf_Dir);
     AddPart(buf,FileVis->rf_File,255);
     GT_SetGadgetAttrs(wingads[StrIDat_ID], win, NULL,
                       GTST_String, buf,
                       TAG_DONE);    
  }
  FreeFileRequest(FileVis);  
}
void OK_DATIClicked(struct Window *win,struct Gadget *wingads[],ULONG gadgetid,ULONG messagecode,char *userdata)
{
   dtprogs *dtp;
   if(!(dtp=(dtprogs*)malloc(sizeof(dtprogs)))) ERRORE("Fine memoria");;
   strcpy(dtp->type, userdata);
   strcpy(dtp->prog,getstring(wingads[StrIDat_ID]));
   ADDTAIL(DTPList,dtp);
}