/**********************************************************************/
/*      FileWindow2              A.Bjerin/B.Schied          (FF336)   */
/*                                                                    */
/**********************************************************************/

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
       operation = FileWindow2(title, ext, x, y, my_screen, file);
       operation:      USHORT operation;
       title    :      UBYTE  title[ANY_LENGTH];
       ext      :      UBYTE  ext[7];
       x, y     :      SHORT  x, y;
       my_screen:      struct Screen *my_screen;
       file     :      UBYTE  file[TOTAL_LENGTH];
нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/

#include <proto/all.h>
#include <string.h>
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <exec/ports.h>
#include <exec/interrupts.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#define  CLEAR           0
#define  TAKE          500      /*    FileWindow2() return value    */
#define  RENAME        600
#define  DELETE        700
#define  ABORT         900      /*    FileWindow2() return value    */
#define  PANIC        1000      /*    FileWindow2() return value    */
                                /* The minimum size of the strings: */
#define  DRAWER_LENGTH  100     /*    100 characters including NULL */
#define  FILE_LENGTH     30     /*     30 characters including NULL */
#define  TOTAL_LENGTH   130     /*    130 characters including NULL */

struct   Window            *file_window;
struct   IntuiMessage      *my_gadget_message;
struct   FileInfoBlock     *file_info;
BPTR     lock;

USHORT  FileWindow2(STRPTR,STRPTR,int,int,struct Screen *,STRPTR);
USHORT  clear_gadgets(STRPTR);
STRPTR  right_pos(STRPTR, char);
APTR    save_file_info(struct FileInfoBlock *);
BOOL    file_comp(struct file_info *, struct file_info *);
BOOL    directory(struct FileInfoBlock *);
BOOL    pick_file(int),   new_drawer(void),   last_check(STRPTR);
void    put_in(struct file_info *, struct file_info *);
void    change_device(STRPTR),             parent(void);
void    request_ok(STRPTR),                request_ask(STRPTR);
void    display_list(int),                 adjust_string_gadgets(void);
void    connect_dir_file(STRPTR),          delete_file_dir(STRPTR);
void    rename_file_dir(STRPTR),           deallocate_file_info(void);
STRPTR  right_pos(STRPTR, char);
BPTR    Lock(char *, long);


BOOL    file_lock,        first_file,      more_files;
USHORT  ren=0;                               /* Rename-Flag = 0,1,2,3 */
USHORT  gadget_flag=CLEAR;                   /* Gadget selected ? */
STRPTR  total_file_name1;
UBYTE   total_file[TOTAL_LENGTH],   display_text[8][34];
UBYTE   file_name[FILE_LENGTH],     extension_name[7];
UBYTE   name_backup[DRAWER_LENGTH];  /* UndoBuffer for string gadgets: */
UBYTE   drawer_name[DRAWER_LENGTH];
UBYTE   *errors[]=
        {
           " OKAY = delete dir       ABORT = abort ",  /*  0 */
           " OKAY = delete file      ABORT = abort ",  /*  1 */
           " 1.type new dir name      2.OKAY/ABORT ",  /*  2 */
           " 1.type new file name     2.OKAY/ABORT ",  /*  3 */
           "NOT enough memory available !",            /*  4 */
           "File name is too long!",                   /*  5 */
           "Device NOT found!",                        /*  6 */
           "Directory NOT found!",                     /*  7 */
           "NO item has been selected!",               /*  8 */
           "You can NOT delete a device!",             /*  9 */
           "You can NOT rename a device!",             /* 10 */
           "Could NOT delete this file!",              /* 11 */
           "Could NOT delete this directory!",         /* 12 */
           "Could NOT rename this file!",              /* 13 */
           "Could NOT rename this directory!",         /* 14 */
           "NOT a valid directory name!",              /* 15 */
           "Drawer string is too long",                /* 16 */
           "Directory name is too long!",              /* 17 */
           "ERROR reading file/directory!",            /* 18 */
        };

/* We will allocate memory, using this structure, for every file/     */
/* directory we find. They will be linked to each otherer, in such a  */
/* way that all directories will come first (sorted alphabetically),  */
/* and after them will the files come (also sorted alphabetically).   */
struct file_info
{
   BYTE name[28];           /* Name of the file/directory, 27 chars   */
   BOOL directory;          /* If it is a directory.                  */
   struct file_info *next;  /* Pointer to the next file_info structur */
};
struct  file_info         *first_pointer;


/*   The program will use a ROM-font, 80 characters wide (40 LOWRES). */
/*   This is to make sure that all the text will fit in nicely in the */
/*   window, even if the calling program is using another font.       */
struct TextAttr my_font=
{
   "topaz.font",                              /* Font Name            */
   TOPAZ_EIGHTY,                              /* Font Height          */
   FS_NORMAL,                                 /* Style                */
   FPF_ROMFONT                                /* Preferences          */
};

/*
  extern struct GfxBase       *GfxBase=NULL;
  extern struct IntuitionBase *IntuitionBase;
*/
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   IntuiText structures for the requesters                          */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_request=
{
  3, 2,                        /* FrontPen, BackPen */
  JAM1,                        /* DrawMode */
  15, 15,                      /* LewftEdge, TopEdge */
  &my_font,                    /* *ITextFont */
  NULL,                        /* *IText */
  NULL                         /* *NextText */
};

struct IntuiText ok_request=
{
  3, 2,
  JAM2,
  6, 3,
  &my_font,
"         C O N T I N U E        ",
  NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points4[]=               /* Values for a 4-letter box: */
{
   0,  0,
  44,  0,
  44, 14,
   0, 14,
   0,  0
};
SHORT points6[]=               /* Values for a 6-letter box: */
{
   0, 0,
  52, 0,
  52,10,
   0,10,
   0, 0
};
SHORT points9b []=             /* Values for a 9-letter box: */
{
   0,  0,
  76,  0,
  76, 11,
   0, 11,
   0,  0
};
SHORT points9[]=               /* Values for a 9-letter box: */
{
   0,  0,
  80,  0,
  80, 15,
   0, 15,
   0,  0
};
struct Border border_text4=    /* A border for a 4-letter box: */
{
  0, 0,                        /* LeftEdge, TopEdge */
  1, 2, JAM1,                  /* FrontPen, BackPen, DrawMode */
  5,                           /* Count */
  points4,                     /* *XY */
  NULL                         /* *NextBorder */
};
struct Border border_text6=    /* A border for a 6-letter box: */
{
  -2,-2,
  1, 0, JAM2,
  5,         
  points6,   
  NULL       
};
struct Border border_text9b=   /* An inner border for 9-letter box: */
{
  0, 0,      
  3, 0, JAM1,
  5,         
  points9b,  
  NULL       
};
struct Border border_text9=    /* A outer border for a 9-letter box: */
{
 -2, -2,     
  3, 0, JAM1,
  5,         
  points9,   
  &border_text9b
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the proportional gadget                          */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*
  Since we are using the auto-knob we set GadgetRender to point to an
  Image. In this case we do not need to initialize the Image structure:
*/
struct Image image_prop;
struct PropInfo prop_info=
{
  AUTOKNOB|          /* We want to use the auto-knob. */
  FREEVERT,          /* The knob should move vertically. */
  0,0,               /* HorizPot, VertPot: will be initialized later. */
  0,                 /* HorizBody                 -"-                 */
  0xFFFF,            /* VertBody: No data to show, maximum. */
  0,0,0,0,0,0        /* Intuition sets and maintains these variables. */
};

struct Gadget gadget_proportional=
{
  NULL,                     /* *NextGadget */
  290, 68, 21, 72,          /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,                                      /* Flags      */
  GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,            /* Activation */
  PROPGADGET,                                     /* GadgetType */
  (APTR) &image_prop,       /* GadgetRender */
  NULL,                     /* SelectRender */
  NULL,                     /* *GadgetText */
  NULL,                     /* MutualExclude */
  (APTR) &prop_info,        /* SpecialInfo */
  NULL,                     /* GadgetID */
  NULL                      /* UserData */
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the string gadget "Drawer:"                      */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points28s[]=              /* Values for a 28-letter string box: */
{
   -7, -3,
  200, -3,
  200, 10,
   -7, 10,
   -7, -3,
};
struct Border border_text28s=   /* Border for 28-letter string box: */
{
  0, 0,                     /* LeftEdge, TopEdge */
  1, 2, JAM1,               /* FrontPen, BackPen, DrawMode */
  5,                        /* Count */
  points28s,                /* *XY   */
  NULL                      /* *NextBorder */
};


struct IntuiText text_drawer=
{
  1, 2,                     /* FrontPen, BackPen  */
  JAM1,                     /* DrawMode           */
  -67, 0,                   /* LewftEdge, TopEdge */
  &my_font,                 /* *ITextFont */
  "Drawer:",                /* *IText */
  NULL                      /* *NextText */
};

struct StringInfo string_drawer=
{
  drawer_name,              /* *Buffer */
  name_backup,              /* *UndoBuffer */
  0,                        /* BufferPos */
  70,                       /* MaxChars (Including NULL) */
  0,                        /* DispPos */
  0,                        /* UndoPos */
  0, 0,                     /* CLeft, CTop */
  NULL,                     /* *LayerPtr */
  NULL,                     /* LongInt */
  NULL,                     /* *AltKeyMap */
};

struct Gadget gadget_drawer =
{
  &gadget_proportional,     /* *NextGadget */
  83, 53, 198, 8,           /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,                /* Flags */
  RELVERIFY,                /* Activation */
  STRGADGET,                /* GadgetType */
  (APTR) &border_text28s,   /* GadgetRender */
  NULL,                     /* SelectRender */
  &text_drawer,             /* *GadgetText */
  NULL,                     /* MutualExclude */
  (APTR) &string_drawer,    /* SpecialInfo */
  NULL,                     /* GadgetID */
  NULL                      /* UserData */
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*  Information for the string gadget "File:"                         */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points30s[]=                /* Values for 30-letter string box: */
{
   -7, -3,
  244, -3,
  244, 10,
   -7, 10,
   -7, -3 
};
struct Border border_text30s=     /* Border for 30-letter string box: */
{
  0, 0,              /* LeftEdge, TopEdge */
  1, 0, JAM1,        /* FrontPen, BackPen, DrawMode */
  5,                 /* Count */
  points30s,         /* *XY */
  NULL               /* *NextBorder */
};
struct IntuiText text_file=
{
  1, 0,              /* FrontPen, BackPen */
  JAM1,              /* DrawMode */
  -53, 0,            /* LewftEdge, TopEdge */
  &my_font,          /* *ITextFont */
  "File:",           /* *IText */
  NULL               /* *NextText */
};
struct StringInfo string_file=
{
  file_name,         /* *Buffer */
  name_backup,       /* *UndoBuffer */
  0,                 /* BufferPos */
  40,                /* MaxChars (Including NULL) */
  0,                 /* DispPos */
  0,                 /* UndoPos */
  0, 0,              /* CLeft, CTop */
  NULL,              /* *LayerPtr */
  NULL,              /* LongInt */
  NULL,              /* *AltKeyMap */
};
struct Gadget gadget_file=
{
  &gadget_drawer,         /* *NextGadget */
  66,  147, 240, 7,       /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,              /* Flags */
  RELVERIFY,              /* Activation */
  STRGADGET,              /* GadgetType */
  (APTR) &border_text30s, /* GadgetRender */
  NULL,                   /* SelectRender */
  &text_file,             /* *GadgetText */
  NULL,                   /* MutualExclude */
  (APTR) &string_file,    /* SpecialInfo */
  NULL,                   /* GadgetID */
  NULL                    /* UserData */
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* * Information for the string gadget "Extension"                     * */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points6s[]=           /* Values for a 6-letter string box: */
{
  -7, -3,
  57, -3,
  57, 10,
  -7, 10,
  -7, -3
};
struct Border border_text6s=  /* Border for 6-letter string box: */
{
  0, 0,                     /* LeftEdge, TopEdge */
  1, 2, JAM1,               /* FrontPen, BackPen, DrawMode */
  5,                        /* Count */
  points6s,                 /* *XY */
  NULL                      /* *NextBorder */
};
struct IntuiText text_extension=
{
  1, 2,                     /* FrontPen, BackPen */
  JAM1,                     /* DrawMode */
  -43, 0,                   /* LewftEdge, TopEdge */
  &my_font,                 /* *ITextFont */
  "Ext:",                   /* *IText */
  NULL                      /* *NextText */
};
struct StringInfo string_extension=
{
  extension_name,           /* *Buffer */
  name_backup,              /* *UndoBuffer */
  0,                        /* BufferPos */
  7,                        /* MaxChars (Including NULL) */
  0,0,                      /* DispPos, UndoPos */
  0, 0,                     /* CLeft, CTop */
  NULL,NULL,NULL,           /* *LayerPtr, LongInt, *AltKeyMap */
};
struct Gadget gadget_extension=
{
  &gadget_file,             /* *NextGadget */
  253, 35, 59, 8,           /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,                /* Flags */
  RELVERIFY,                /* Activation */
  STRGADGET,                /* GadgetType */
  (APTR) &border_text6s,    /* GadgetRender */
  NULL,                     /* SelectRender */
  &text_extension,          /* *GadgetText */
  NULL,                     /* MutualExclude */
  (APTR) &string_extension, /* SpecialInfo */
  NULL,                     /* GadgetID */
  NULL                      /* UserData */
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget parent "<"                    */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points1[]=            /* Values for a 1-letter box: */
{
   0,  0,
  20,  0,
  20, 15,
   0, 15,
   0,  0
};
struct Border border_text1= /* A border for a 1-letter box: */
{
  0, 0,                     /* LeftEdge, TopEdge */
  1, 2, JAM1,               /* FrontPen, BackPen, DrawMode */
  5,                        /* Count */
  points1,                  /* *XY */
  NULL                      /* *NextBorder */
};
struct IntuiText text_parent=
{
  1, 2,                     /* FrontPen, BackPen */
  JAM1,                     /* DrawMode */
  7,4,                      /* LeftEdge, TopEdge */
  &my_font,                 /* *ITextFont, (Topaz, 80) */
  "<",                      /* *IText */
  NULL                      /* *NextText */
};
struct Gadget gadget_parent=
{
  &gadget_extension,        /* *NextGadget */
  290, 49, 21, 16,          /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,                /* Flags */
  RELVERIFY,                /* Activation */
  BOOLGADGET,               /* GadgetType */
  (APTR) &border_text1,     /* GadgetRender */
  NULL,                     /* SelectRender */
  &text_parent,             /* *GadgetText */
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "df1:"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_df1=
{
  1, 2,    
  JAM1,    
  7,4,     
  &my_font,
  "df1:",  
  NULL     
};
struct Gadget gadget_df1=
{
  &gadget_parent, 
  110, 13, 45, 15,
  GADGHCOMP,      
  RELVERIFY,      
  BOOLGADGET,     
  (APTR) &border_text4,
  NULL,           
  &text_df1,      
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "df0:"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_df0=
{
  1, 2,                     /* FrontPen, BackPen */
  JAM1,                     /* DrawMode */
  7,4,                      /* LeftEdge, TopEdge */
  &my_font,                 /* *ITextFont, (Topaz, 80) */
  "df0:",                   /* *IText */
  NULL                      /* *NextText */
};
struct Gadget gadget_df0=
{
  &gadget_df1,              /* *NextGadget */
  59, 13, 45, 15,           /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,                /* Flags */
  RELVERIFY,                /* Activation */
  BOOLGADGET,               /* GadgetType */
  (APTR) &border_text4,     /* GadgetRender */
  NULL,                     /* SelectRender */
  &text_df0,                /* *GadgetText */
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "ram:"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_ram=
{
  1, 2,    
  JAM1,    
  7,4,     
  &my_font,
  "ram:",  
  NULL     
};
struct Gadget gadget_ram=
{
  &gadget_df0,  
  8, 13, 45, 15,
  GADGHCOMP,    
  RELVERIFY,    
  BOOLGADGET,   
  (APTR) &border_text4,
  NULL,     
  &text_ram,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*  Information for the boolean gadget "dh2:"                         */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_dh2=
{
  1, 2,
  JAM1,
  7,4, 
  &my_font,
  "dh2:",
  NULL 
};
struct Gadget gadget_dh2=
{
  &gadget_ram,
  110, 31, 45, 15,
  GADGHCOMP, 
  RELVERIFY, 
  BOOLGADGET,
  (APTR) &border_text4,
  NULL,     
  &text_dh2,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "dh1:"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_dh1=
{
  1, 2,
  JAM1,
  7,4, 
  &my_font,
  "dh1:",  
  NULL     
};
struct Gadget gadget_dh1=
{
  &gadget_dh2,
  59, 31, 45, 15,
  GADGHCOMP, 
  RELVERIFY, 
  BOOLGADGET,
  (APTR) &border_text4,
  NULL,     
  &text_dh1,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "dh0:"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_dh0=
{
  1, 2,
  JAM1,
  7,4, 
  &my_font,
  "dh0:",
  NULL   
};
struct Gadget gadget_dh0=
{
  &gadget_dh1,
  8, 31, 45, 15,
  GADGHCOMP,
  RELVERIFY,
  BOOLGADGET,
  (APTR) &border_text4,
  NULL,
  &text_dh0,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "ABORT"                       */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_abort=
{
  1, 2,
  INVERSVID,
  3,2, 
  &my_font,
  "- ABORT -",
  NULL
};
struct Gadget gadget_abort=
{
  &gadget_dh0,
   95, 162, 77, 12,
  GADGHCOMP,
  RELVERIFY,
  BOOLGADGET,
  (APTR) &border_text9b,
  NULL,
  &text_abort,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "DELETE"                      */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_delete=
{
  1, 0,
  JAM2,
  0,0, 
  &my_font,
  "DELETE",
  NULL 
};
struct Gadget gadget_delete=
{
  &gadget_abort,
  196, 168, 49, 8,
  GADGHCOMP,
  RELVERIFY,
  BOOLGADGET,
  (APTR) &border_text6,
  NULL,
  &text_delete,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "RENAME"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_rename=
{
  1, 0,
  JAM2,
  0,0, 
  &my_font,
  "RENAME",
  NULL
};
struct Gadget gadget_rename=
{
  &gadget_delete,
  259, 168, 48, 8,
  GADGHCOMP,
  RELVERIFY,
  BOOLGADGET,
  (APTR) &border_text6,
  NULL,
  &text_rename,
  NULL, NULL, NULL, NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadget "TAKE"                        */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_take=
{
  1, 2,     
  INVERSVID,
  3,2,      
  &my_font, 
  " O K A Y ",
  NULL
};
struct Gadget gadget_take=
{
  &gadget_rename,
  8, 162, 77, 12,         /* LeftEdge, TopEdge, Width, Height */
  GADGHCOMP,              /* Flags */
  RELVERIFY,              /* Activation */
  BOOLGADGET,             /* GadgetType */
  (APTR) &border_text9,   /* GadgetRender */
  NULL,                   /* SelectRender */
  &text_take,             /* *GadgetText */
  NULL, NULL, NULL, NULL
};
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the boolean gadgets "gadget_display"             */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct IntuiText text_list[8]=
{
  {
    1, 0,            /* FrontPen, BackPen */
    JAM2,            /* DrawMode */
    0,18,            /* LeftEdge, TopEdge */
    &my_font,        /* *ITextFont */
    display_text[0], /* IText */
    &text_list[1]    /* *NextText */
  },
  {
    1, 0,            
    JAM2,            
    0,26,            
    &my_font,        
    display_text[1], 
    &text_list[2]    
  },
  {
    1, 0,            
    JAM2,            
    0,34,            
    &my_font,        
    display_text[2], 
    &text_list[3]    
  },
  {
    1, 0,            
    JAM2,            
    0,42,            
    &my_font,        
    display_text[3], 
    &text_list[4]    
  },
  {
    1, 0,            
    JAM2,            
    0,50,            
    &my_font,        
    display_text[4], 
    &text_list[5]    
  },
  {
    1, 0,            
    JAM2,            
    0,58,            
    &my_font,        
    display_text[5], 
    &text_list[6]    
  },
  {
    1, 0,            
    JAM2,            
    0,66,            
    &my_font,        
    display_text[6], 
    &text_list[7]    
  },
  {
    1, 0,            
    JAM2,            
    0,74,            
    &my_font,        
    display_text[7], 
    NULL             
  }
};

struct Gadget gadget_display[8]=
{
  {
    &gadget_display[1],      /* *NextGadget */
    8, 68, 276, 12,          /* LeftEdge, TopEdge, Width, Height */
    GADGHCOMP,               /* Flags */
    RELVERIFY|GADGIMMEDIATE, /* Activation */
    BOOLGADGET,              /* GadgetType */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[2],
    8, 80, 276, 8,
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[3],
    8, 88, 276, 8,  
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET, 
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[4],
    8, 96, 276, 8,
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[5],
    8, 104, 276, 8,
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[6],
    8, 112, 276, 8,  
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET, 
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_display[7],
    8, 120, 276, 8, 
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  },
  {
    &gadget_take,
    8, 128, 276, 12,
    GADGHCOMP,
    RELVERIFY|GADGIMMEDIATE,
    BOOLGADGET,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL
  }
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   BIG BOX                                                          */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
SHORT points_big_box[]=
{
   8, 68,
 283, 68,
 283,139,
   8,139,
   8, 68 
};
struct Border border_big_box=             /* Border for 1-letter box: */
{
  0, 0,
  1, 2, JAM1,
  5,
  points_big_box,
  NULL
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*   Information for the window                                       */
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
struct NewWindow new_file_window=
{
  0,0,                    /* LeftEdge, TopEdge   */
  320, 180,               /* Width, Height       */
  0,1,                    /* DetailPen, BlockPen */
  GADGETUP|VANILLAKEY|    /* IDCMPFlags          */
  GADGETDOWN|MOUSEMOVE,
  ACTIVATE|SMART_REFRESH| /* Flags */
  WINDOWDRAG,
  &gadget_display[0],     /* *FirstGadget        */
  NULL, NULL,             /* *CheckMark, *Title  */
  NULL, NULL,             /* *Screen, *BitMap    */
  40,20,640,256,          /* MinWidth, MinHeight, MaxWidth, MaxHeight */
  WBENCHSCREEN            /* Type  */
};

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
USHORT  FileWindow2(STRPTR title,STRPTR extension,int x,int y,struct Screen *screen,STRPTR total_file_name)
{
  int temp1;                  /* Variable used for loops etc.       */
  int file_count;             /* Number of files/directories        */
  ULONG   class;              /* Saved IntuiMessage: IDCMP flags.   */
  USHORT  code;               /*                     key flags.     */
  APTR    address;            /*                     Object-Address */
  int     position;           /* Number of first file in display    */
  BOOL    working;            /* Wants the user to abort?           */
  BOOL    fix_display;        /* Should we update the file-display? */
  STRPTR  string_pointer;     /* Pointer to a string.               */
  struct  file_info *pointer; /* Pointer to a file_info structure   */
  struct  RastPort *rp;       /* Pointer to FileWindow2-rastport    */
  USHORT  operation=0;        /* user action returned by FileWindow2 */
  file_lock =FALSE;           /* No file/directory has been locked  */
  more_files=FALSE;           /* Do not list any files yet          */
  prop_info.VertBody =0xFFFF; /* Make sure the proportional gadget  */
  prop_info.HorizBody=0;      /* is at the top, showing 100%        */
  prop_info.VertPot  =0;
  prop_info.HorizPot =0;
  new_file_window.LeftEdge=x;
  new_file_window.TopEdge =y;
  new_file_window.Title   =title;
  strcpy(extension_name, extension);
  if(*extension_name != '\0')   text_extension.FrontPen=3;
  else                          text_extension.FrontPen=1;

  if(screen)                  /* Does user want to use an own screen? */
  {
    new_file_window.Screen=screen;
    new_file_window.Type=CUSTOMSCREEN;
  }

/*нннннннннннннннннн   Library-Initialisierung   ннннннннннннннннннннн*/
  if(!GfxBase)
  {
     GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
     if(!GfxBase)          return(PANIC);
  }
  if(!IntuitionBase)
  {
     IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0);
     if(!IntuitionBase)    return(PANIC);
  }
  file_window=(struct Window *)OpenWindow(&new_file_window);
  if(file_window==NULL)    return(PANIC);
  rp=file_window->RPort;
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
  DrawBorder(rp, &border_big_box, 0, 0);
  if((file_info=(struct FileInfoBlock *)
    AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  { request_ok(errors[4]);    return(PANIC); }
  if(*total_file_name != '\0')
  {
    if((lock=Lock(total_file_name, ACCESS_READ))==NULL)
    { /* PROBLEMS!  File/directory/device did NOT exist! */ }
    else
    {
      file_lock=TRUE;              /* Could lock the file/directory! */
      if((Examine(lock, file_info))==NULL)   request_ok(errors[18]);
      else
      {
        if(directory(file_info))                /* It is a directory! */
        {
          *file_name='\0';                 /* Clear file_name string. */
          strcpy(drawer_name, total_file_name);
          more_files=TRUE;
        }
        else                                         /* It is a file! */
        {
          /* Separate the file name from the path: */
          if(string_pointer=right_pos(total_file_name, '/'))
          {
            /* Copy the file name into file_name string: */
            strcpy(file_name, string_pointer+1);
            *string_pointer='\0';
          }
          else
          {
            if(string_pointer=right_pos(total_file_name, ':'))
            {
              /* Copy the file name into file_name string: */
              strcpy(file_name, string_pointer+1);
              *(string_pointer+1)='\0';
            }
            else
            {
              strcpy(file_name, total_file_name);
              *drawer_name='\0';
              *total_file_name='\0';
            }
          }
          strcpy(drawer_name, total_file_name);
              /* Since it is a file, we will NOT look for more files: */
              /* However, more_files is already FALSE. */
        }     /* Is it a directory? */
      }       /* Could we examine the object? */
    }         /* Could we "lock" the file/directory? */
  }           /* Anything in the total_file_name string? */

  /* Since we have messed around with the string gadgets it is best */
  /* to adjust them so the user can see them clearly:               */
  adjust_string_gadgets();
  new_drawer();           /* Start to show us the files             */
  position=0;             /* The display will show the first file.  */
  fix_display=FALSE;      /* We do not need to fix the display      */
  first_file=TRUE;        /* No files saved. */
  file_count=0;           /* No files saved. */
  working=TRUE;
  do
  {
    /* If we have shown all files in the directory, we put our task */
    /* to sleep. That will speed up other programs, and we will not */
    /* use unnecessary processing time:                             */
    if(more_files==FALSE)   Wait(1<<file_window->UserPort->mp_SigBit);
    /* Has something happened with the gadgets in the file_window?  */
    while(my_gadget_message = (struct IntuiMessage *)
      GetMsg(file_window->UserPort))
    {
      /* As long as something is happening with the gadgets we will     */
      /* stay in the while loop. This is very handy since we can        */
      /* recieve hundereds of messages if the mouse is moving, and      */
      /* we only want to update the display when the mouse has stopped: */
      class   = my_gadget_message->Class;
      code    = my_gadget_message->Code; 
      address = my_gadget_message->IAddress;

      /* We have now saved some important values, and can now reply: */
      ReplyMsg((struct Message *)my_gadget_message);
      if(code==13||code==27)   class=GADGETUP;
                                   /* RETURN key used instead of TAKE */
                                   /* ESC key used instead of ABORT */
      switch(class)
      {
        case MOUSEMOVE:
          /* The proportional gadget is selected, and the mouse is  */ 
          /* moving; we must update the file_display when the mouse */
          /* has stopped: */
          fix_display=TRUE;   break;

        case GADGETDOWN:
           /* A gadget has been pressed down. Which one? */
           /* DISPLAY */
           /* Is the user clicking inside the file display? */
           for(temp1=0; temp1<8; temp1++)
           {
             if(address == (APTR)&gadget_display[temp1])
             { pick_file(temp1+position); }      /* File/dir selected */
           }
           break;

        case GADGETUP:            /* Which gadget has been selected ? */
/* TAKE */
           if(address == (APTR)&gadget_take || code==13)
           {
             if(operation==DELETE||operation==RENAME)   gadget_flag=TAKE;
             else
             {
                if(last_check(total_file_name))
                  { working=FALSE;   operation=TAKE;  break; }
             }
           }

/* ABORT */
           if(address==(APTR)&gadget_abort||operation==ABORT||code==27)
           {
             if(operation==DELETE||operation==RENAME)   gadget_flag=ABORT;
             else
             {
                connect_dir_file(total_file_name);
                clear_gadgets(title);   operation=ABORT;
                working=FALSE;    break;
             }
           }

/* DELETE */
           if(address==(APTR)&gadget_delete || operation==DELETE)
           {
             if(!(gadget_flag==ABORT||gadget_flag==TAKE))
             {
                 delete_file_dir(total_file_name);
                 operation=DELETE;
             }
             if(gadget_flag==TAKE)
             {
                 delete_file_dir(total_file_name);
                 operation=clear_gadgets(title);     break;
             }
             if(gadget_flag==ABORT)
               { operation=clear_gadgets(title);     break; }
           }

/* RENAME */
           if(address==(APTR)&gadget_rename||operation==RENAME)
           {
           if(ren==1)
             {
                if(gadget_flag==ABORT)
                  { operation=clear_gadgets(title);  break; }

                else   ren=2;
             }
             if(ren==0)   { operation=RENAME;   ren=1; }
             rename_file_dir(total_file_name);

             if(ren==2)   { operation=clear_gadgets(title);   break; }
           }

           if(address == (APTR)&gadget_ram)           /* ram: */
             { change_device("ram:");   break; }
           if(address == (APTR)&gadget_df0)           /* df0: */
             { change_device("df0:");   break; }
           if(address == (APTR)&gadget_df1)           /* df1: */
             { change_device("df1:");   break; }
           if(address == (APTR)&gadget_dh0)           /* dh0: */
             { change_device("dh0:");   break; }
           if(address == (APTR)&gadget_dh1)           /* dh1: */
             { change_device("dh1:");   break; }
           if(address == (APTR)&gadget_dh2)           /* dh2: */
             { change_device("dh2:");   break; }

           /* DRAWER: */
           if(address == (APTR)&gadget_drawer)
           {
             /* The user has entered something new in the drawer: */
             new_drawer();   break;
           }

           /* EXTENSION: */
           if(address == (APTR)&gadget_extension)
           {
             new_drawer();   break;
           }

           /* PARENT: "<" */
           if(address == (APTR)&gadget_parent)    { parent();   break; }

           /* PROPORTIONAL */
           if(address == (APTR)&gadget_proportional)
           {
             /* User has released the prop-gadget, update display: */
             fix_display=TRUE;   break;
           }
      }
    }
    if(fix_display)         /* Do we need to update the file display? */
    {
      fix_display=FALSE;
      if(file_count>8)          /* Which file should be shown */
        position=(int) prop_info.VertPot/(float)0xFFFF*(file_count-8);
      else   position=0;
      display_list(position);   /* List files: (Starts with position) */
    }
    if(more_files)              /* Are there more files/dirs? */
    {
      if(ExNext(lock, file_info))
      {
                          /* List the file/directory if it is: */
                          /* 1. A file which has the right extension. */
                          /* 2. A directory. */
        if(stricmp(extension_name, (file_info->fib_FileName+
           strlen(file_info->fib_FileName)-strlen(extension_name)))==0 ||
           directory(file_info) )
        {
          if(first_file)  /* Is this the first file/directory? */
          {
            /* first_pointer will point at the first file in our list: */
            first_pointer=(struct file_info *) save_file_info(file_info);
            if(first_pointer != NULL)
            {
              /* No more elements (for the moment) in the list: */ 
              first_pointer->next=NULL; 
              first_file=FALSE;
            }
            file_count=1;   position=1;
          }
          else
          {
            /* save_file_info will return a pointer to the allocated */
            /* structure: */
            pointer=(struct file_info *) save_file_info(file_info);
            
            /* If we have been able to allocate space for the file we */
            /* put it into our list: */
            if(pointer!=NULL)         /* Put new structure into list: */
            {
              put_in(first_pointer, pointer);
              file_count++;
            }
          }
          /* If there are more than eight files/directories we modify */
          /* the proportional gadget: */
          if(file_count > 8)
          {
            ModifyProp
            (
              &gadget_proportional,       /* PropGadget */
              file_window,                /* Pointer */
              NULL,                       /* Requester */
              prop_info.Flags,            /* Flags */
              0,                          /* HorizPot */
              prop_info.VertPot,          /* VertPot */
              0,                          /* HorizBody */
              (ULONG) 0xFFFF*8/file_count /* VerBody */
            );            
            position=(int) prop_info.VertPot/(float) 0xFFFF*(file_count-8);
          }
          else
           position=0;
          display_list(position);         /* List all the files: */
        }
      }
      else                                /* ExNext() failed: */
      {
        more_files=FALSE;                 /* Don't list any more files */
        /* Check what went wrong: */
        /* If error message is NOT "ERROR_NO_MORE_ENTRIES" something */
        /* went terrible wrong while reading: */
        if(IoErr() != ERROR_NO_MORE_ENTRIES)   request_ok(errors[18]);
      }
    }
  } while(working);                       /* Clean up and leave: */
                              /* This will clear the IDCMP port: */
  while( (my_gadget_message = (struct IntuiMessage *)
           GetMsg(file_window->UserPort)) )
  {
    ReplyMsg((struct Message *)my_gadget_message);
  }
  /* Deallocate the memory we have dynamically allocated: */ 
  deallocate_file_info();
  if(file_lock)       /* If we have "locked" a file/dir, "unlock" it: */
  {
    UnLock(lock);   file_lock=FALSE;
  }
  if(file_info) FreeMem(file_info, sizeof(struct FileInfoBlock));
  /* If we have successfully opened the file_window, we close it: */
  if(file_window)
  {
     if(GfxBase)         CloseLibrary((struct Library *) GfxBase);
     if(IntuitionBase)   CloseLibrary((struct Library *) IntuitionBase);
     CloseWindow(file_window);
  }
  return(operation);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
void deallocate_file_info(void)
{
  struct file_info *pointer, *temp_pointer;

  /* Does the first pointer point to an allocated structure? */
  if(first_pointer)
  {
    /* Save the address of the next structure: */
    pointer=first_pointer->next;
    
    /* Deallocate the first structure: */
    FreeMem( first_pointer, sizeof(struct file_info));

    /* As long as pointer points to an allocated structure: */
    while(pointer)
    {
      /* Save the address of the next structure: */
      temp_pointer=pointer->next;
      
      FreeMem( pointer, sizeof(struct file_info));
      pointer=temp_pointer;
    }
  }
  first_pointer=NULL;                         /* Clear first_pointer: */

  /* Next time we try to list the files, we start with the first_file: */
  first_file=TRUE;
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Allocate memory for the new file/directory, and fills the structure */
/* with information. (name of the object, and if it is a directory.)   */
/* Returns a memory pointer to the allocated structure, or NULL.       */
APTR save_file_info(struct FileInfoBlock *info)
{
  struct file_info *pointer;

  if((pointer=(struct file_info *)
    AllocMem(sizeof(struct file_info), MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  {
    request_ok(errors[4]);
    more_files=FALSE;              /* Do not list any more files/dirs */
    return(NULL);
  }
  else
  {
    /* If file/dirname is not too long, we copy it into new stucture: */
    if(strlen(info->fib_FileName) < 28)
      strcpy(pointer->name, info->fib_FileName);
    else
    {
      /* The file/directory name is too long! */
      if( directory(info))   request_ok(errors[17]);   /* It's a dir  */
      else                   request_ok(errors[5]);    /* It's a file */
      FreeMem( pointer, sizeof(struct file_info));
      return(NULL);
    }
    if( directory(info))        /* Is it a file or a directory? */
      pointer->directory=TRUE;  /* It is a directory. */
    else    
      pointer->directory=FALSE; /* It is a file. */
  }
  return( (APTR) pointer);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Will check a FileInfoBlock if it is a file or a directory. */
/* Return TRUE if it is a directory, FALSE if it is a file.   */
BOOL directory(struct FileInfoBlock *info)
{
  if(info->fib_DirEntryType<0)   return(FALSE);
  else                           return(TRUE);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Put the new structure into the dynamically allocated list at the */
/* right place (sorted alphabetically, directories first):          */
void put_in(struct file_info *a_pointer, struct file_info *pointer)
{
  struct file_info *old_pointer=NULL;

  /* Move slowly down the list and try to fit in the structure: */
  while(a_pointer && file_comp(a_pointer, pointer))   /* ->name */
  {
    old_pointer=a_pointer;   a_pointer=a_pointer->next;
  }
  if(a_pointer)
  {
    if(old_pointer)
    {
      /* Put the structure into the list: */
      pointer->next=old_pointer->next;    old_pointer->next=pointer;
    }
    else
    {
      pointer->next=first_pointer;   first_pointer=pointer;
    }
  }
  else
  {
    /* Last int the list: */
    old_pointer->next=pointer;   pointer->next=NULL;
  }
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* This function will return TRUE if the first pointer (a_pointer) */
/* points to a file structure which should come before the second  */
/* pointers file structure.                                        */
/* ORDER:   1. DIRECTORIES sorted alphabetically. */
/*          2. FILES       sorted alphabetically. */

BOOL file_comp(struct file_info *a_pointer, struct file_info *pointer)
{
  if(a_pointer->directory == FALSE && pointer->directory)
    return(FALSE);
    
  if(a_pointer->directory == pointer->directory)
  {
    if(stricmp(a_pointer->name, pointer->name) <= 0 )   return(TRUE);
    else                                                return(FALSE);
  } 
  return(TRUE);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Give this function a string and a character, and it will return a */
/* pointer to the right most occurance character in you string which */
/* match your character.                                             */
STRPTR right_pos(STRPTR string, char sign)
{
  STRPTR start_pos;
  
  start_pos=string;
  while(*string != '\0')                         string++;
  /* Start to go backwards and check teh string: */
  while(*string != sign && string > start_pos)   string--;
  if(*string==sign)
    return(string);        /* We have found a matching character. */
  return(NULL);            /* We could not find a matching character. */
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* This function will change to a new device, for example df0:. */
/* Does not return anything.                                    */
void change_device(STRPTR device)
{
  strcpy(drawer_name, device);  /* Change the drawer string.  */
  adjust_string_gadgets();      /* Adjust the string gadgets. */
  new_drawer();                 /* Showing the new files/directories */
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* When the user or the program has changet the drawer string, this      */
/* function is called, and will do what is necessary to start to collect */
/* the new files/directories from the disk.                              */
/* Returns TRUE if everything is OK, and FALSE if something went wrong   */
BOOL new_drawer(void)
{
  STRPTR string_pointer;

  if(file_lock)   { UnLock(lock);   file_lock=FALSE; }
  deallocate_file_info();

  ModifyProp
  (
    &gadget_proportional, /* PropGadget */
    file_window,          /* Pointer */
    NULL,                 /* Requester */
    prop_info.Flags,      /* Flags */
    0,                    /* HorizPot */
    0,                    /* VertPot */
    0,                    /* HorizBody */
    (ULONG) 0xFFFF        /* VerBody */
  );
  display_list(0);        /* Clear the display: */
  more_files=FALSE;
  if((lock=Lock(drawer_name, ACCESS_READ))==NULL)
  {
    /* We could NOT lock the file/dir/device!  Inform the user: */
    string_pointer=drawer_name+strlen(drawer_name)-1;
    if(*string_pointer==':')  request_ok(errors[6]);
    else                      request_ok(errors[7]);
    return(FALSE);        /* ERROR */
  }
  else
  {
    file_lock=TRUE;          /* We "locked" the file/directory! */
  }

  /* Now try to get some information from the file/directory: */
  if((Examine(lock, file_info))==NULL)
    { request_ok(errors[18]);   return(FALSE); }

  if(directory(file_info))   /* Is it a directory or a file? */
  {
    /* It is a directory:    We will look for more files: */
    more_files=TRUE;
  }
  else   { request_ok(errors[15]);   return(FALSE);  } /* It's a file! */
  return(TRUE);
}
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* The function parent() will try to go backwards one step in the     */
/* directory path.    Does not return anything.                       */
void parent(void)
{
  STRPTR string_pointer;

  /* Separate the last directory from the path: */
  if(string_pointer=right_pos(drawer_name, '/'))
  {
    *string_pointer='\0';    /* Take away the last directory: */
  }
  else
  {
    if(string_pointer=right_pos(drawer_name, ':'))
    {
      /* Take away the last directory: */
      /* Only the device ("df0:" for example) left: */
      *(string_pointer+1)='\0';
    }
    else
    {
      *drawer_name='\0';
    }
  }

  adjust_string_gadgets();
  new_drawer();              /* Show user files etc in the new dir: */
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* You give this function a pointer to an error string and it'll open */
/* a simple requester displaying the message. Requester will go away  */
/* first when user has selected the button "OK".                      */
void request_ok(STRPTR message)
{
  text_request.IText=message;
  AutoRequest
  (
    file_window,   /* Window */
    &text_request, /* BodyText */
    NULL,          /* PositiveText nothing */
    &ok_request,   /* NegativeText OK */
    NULL, NULL,    /* PositiveFlags, NegativeFlags */
    320, 65        /* Width, Height*/
  );
  gadget_flag=ABORT;
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* This function will give user advices on the drag bar how to go on  */
void request_ask(STRPTR message)
{
  SetAPen(file_window->RPort,2);      SetBPen(file_window->RPort,3);
  SetDrMd(file_window->RPort,JAM2);   Move(file_window->RPort,6,7);
  Text(file_window->RPort, message, strlen(message));
  OffGadget(&gadget_rename, file_window, NULL);
  OffGadget(&gadget_delete, file_window, NULL);
}
/*ннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* This function displays files etc which are inside the dir, starting */
/* with the file number start_pos.   Does not return anything.         */
void display_list(int start_pos)
{
  struct file_info *pointer;
  int    pos, temp1;
                    /* 123456789012345678901234567890123 */
  char   empty_name[]="                                 ";
  STRPTR string_pointer;
  BOOL   clear;
  
  pos=0;
  if(first_pointer)          /* Does it exist any files at all? */
  {
    pointer=first_pointer;

    /* Go through the list until you have found the file/directory */
    /* which should be shown first:                                */
    while(pointer && pos < start_pos)
    {
      pos++;
      pointer=pointer->next;
    }
    pos=0;
    while(pointer && pos<8)  /* Try to show the eight files: */
    {
      strcpy(display_text[pos], pointer->name);
      clear=FALSE;   temp1=0;
      string_pointer=display_text[pos];
      if(pointer->directory)                    /* It is a directory: */
      {
        text_list[pos].FrontPen=3;              /* Highlight it. */

        /* Clear everything after the name, and add string "(Dir)" */
        while(temp1а< 28)
        {
          if(*string_pointer=='\0')   clear=TRUE;
          if(clear)                   *string_pointer=' ';
          string_pointer++;  temp1++;
        }
        *string_pointer='\0';  strcat(display_text[pos], "(Dir)");
      }
      else   text_list[pos].FrontPen=1;         /* It is a file: */
      {

        /* Clear everything after the name: */
        while(temp1а< 33)
        {
          if(*string_pointer=='\0')   clear=TRUE;
          if(clear)                   *string_pointer=' ';
          string_pointer++;   temp1++;
        }
        *string_pointer='\0';
      }
      pos++;   pointer=pointer->next;           /* Next. */
    }
  }

  /* If there are less than 8 files, show clear rest of the display: */
  while(pos < 8)
  {
    strcpy(display_text[pos], empty_name);   pos++;
  }
  
  /* Show the user the new display: */
  PrintIText(file_window->RPort, text_list, 16, 54);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* User has selected a file or a directory.  If it is a file put it   */
/* into the file string, otherwise put it into the drawer string.     */
/* Returns TRUE if everything went OK, FALSE if there was a problem.  */
BOOL pick_file(int file_pos)
{
  struct file_info  *pointer=NULL;
  STRPTR            string_pointer;
  int               pos=0;
  
  /* Go through the allocated list untill we find the file/directory: */
  if(first_pointer)
  {
    pointer=first_pointer;
    
    while(pointer && pos < file_pos)
    {
      pos++;   pointer=pointer->next;
    }
  }
  if(pointer)                /* Have we found the file/directory? */
  {
    if(pointer->directory)   /* It's a directory! */
    {
      /* Is the drawer_name string long enough? */
      /* (+2: 1 for the NULL ('\0') character, 1 for the '\' char) */
      if((strlen(pointer->name)+strlen(drawer_name)+2) <= DRAWER_LENGTH)
      {
        /* YES!, there is enough room for it. */
        string_pointer=drawer_name+strlen(drawer_name)-1;
        if(*string_pointer==':' || *string_pointer=='\0' )
          strcat(drawer_name, pointer->name);
        else
        {
          /* We need to add a '/' before we can add the directory. */
          strcat(drawer_name, "/");
          strcat(drawer_name, pointer->name);
        }
        adjust_string_gadgets();
      }
      else   { request_ok(errors[16]);   return(FALSE); }
      new_drawer();
      return(TRUE);          /* OK */
    }
    else
    {
      /* It is a File! */
      /* Is the file_name string long enough? */
      /* (+1 for the NULL ('\0') character.) */
      if((strlen(pointer->name)+1) <= FILE_LENGTH)
      {
        strcpy(file_name, pointer->name);
        adjust_string_gadgets();
      }
      else         /* The file_name is NOT big enough! */
      {
        request_ok(errors[5]);   return(FALSE);
      }
      return(TRUE);
    }
  }
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Adjust the string gadgets, so user can  at least see the last      */
/* 28/22 characters.   Does not return anything.                      */
void adjust_string_gadgets(void)
{
  int length;

  length=strlen(file_name);
  if(length>28)   string_file.DispPos=length-28;
  else            string_file.DispPos=0;
  string_file.BufferPos=string_file.DispPos;
  length=strlen(drawer_name);

  if(length>22)   string_drawer.DispPos=length-22;
  else            string_drawer.DispPos=0;
  string_drawer.BufferPos=string_drawer.DispPos;
  RefreshGadgets(&gadget_file, file_window, NULL);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* Returns TRUE if there exist a file name, otherwise FALSE.          */
BOOL last_check(STRPTR name)
{
  if(*file_name=='\0')
  {
    request_ok(errors[8]);   return(FALSE);     /* No file name! */
  }
  else
  {
    connect_dir_file(name);  /* Change total_file_name. Drawer + File */
  }
  return(TRUE);
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/* This function will connect the drawer string with the file string. */
/* Does not return anything.                                          */
void connect_dir_file(STRPTR name)
{
  STRPTR string_pointer;

  strcpy(name, drawer_name);
  if(*file_name!='\0')       /* Does it exist a file name? */
  {
    string_pointer=drawer_name+strlen(drawer_name)-1;
    if(*string_pointer==':'||*string_pointer=='\0' )
    {
      strcat(name, file_name);
    }
    else   { strcat(name, "/");   strcat(name, file_name); }
  }
}

/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
void delete_file_dir(STRPTR total_file_name)
{

  if(*file_name=='\0' && *drawer_name!='\0')
  {
    /* There is no filename string, but there is something in  */
    /* the drawer string. The user wants to delete a directory */

    /* Is it a device or a directory? */
    if( *(drawer_name+strlen(drawer_name)-1) ==':')
    {
      /* The user wants to delete a device: */
      /* Not a very good idea! */
      request_ok(errors[9]);
    }
    else           /* The user wants to delete a dir:    */
    {
      /* However, it is important to check that the user */
      /* realy wants to delete it:                       */
      request_ask(errors[0]);
      if(gadget_flag==TAKE)
      {
        /* YES! The user wanted to delete the directory.  */
        /* Before we try to delete it we must "unlock" it */
        if(file_lock)
        {
          UnLock(lock);   file_lock=FALSE;
        }
      }
    }
  }
  else
  {
    if(*file_name!='\0')
    {
      /* There is something in the file_name string. */
      /* The user wants to delete a file:            */
      
      /* We will here again give the user a last */
      /* chance to  make up his mind:            */
      request_ask(errors[1]);
      }
    else
    {
      /* Nothing in the drawer string, nor in the file string. */
      /* The user wants to delete something, but has NOT       */
      /* declared which file/directory he/she wants to delete: */
      request_ok(errors[8]);
    }
  }
  if(gadget_flag==TAKE)              /* Should we delete the file/dir? */
  {
    /* Put the drawer name together with the file name: */
    connect_dir_file(total_file_name);
    if(DeleteFile(total_file_name))
    {
      if(*file_name!='\0')   /* A file was deleted sucessfully: */
      {
        *file_name='\0';     /* Take away the file name */
        adjust_string_gadgets();
        new_drawer();        /* Show remaining files to user */
      }
      else                   /* A directory was deleted: */
      {
        parent();            /* Go back one directory */
      }
    }
    else                     /* Something went wrong: */
    {
      if(*file_name != '\0')   request_ok(errors[11]);
      else                     request_ok(errors[12]);
      
      /* Since we have unlocked the directory/file we have */
      /* to lock it again, and clean up the display:       */
      new_drawer();
    }
  }
}
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
void rename_file_dir(STRPTR total_file_name)
{
  /* Presume the user do not want to rename file/dir: */
  if(ren==1)
  {
     if(*file_name=='\0' && *drawer_name!='\0')
     {
        /* There is no filename string, but there is something in  */
        /* the drawer string. The user wants to rename a directory */

        /* Is it a device or a directory? */
        if( *(drawer_name+strlen(drawer_name)-1) ==':')
        {
           /* The user wants to rename a device: */
           /* Not a very good idea! */
           request_ok(errors[10]);
        }
        else                 /* The user wants to rename a directory: */
        {
           request_ask(errors[2]);
           strcpy(total_file, drawer_name);
           total_file_name1=(STRPTR)(&total_file);
           /* YES! The user wanted to rename the directory.  */
           /* Before we try to rename it we must "unlock" it */
           if(file_lock)    { UnLock(lock);   file_lock=FALSE; }
        }
     }
     else
     {
        if(*file_name!='\0')    /*File selected */
        {
           /* There is something in the file_name string. */
           /* The user wants to rename a file:            */

           request_ask(errors[3]);
           connect_dir_file(total_file_name);
           strcpy(total_file,total_file_name);
           total_file_name1=(STRPTR)(&total_file);
        }
        else          /* Nothing in drawer string, nor in file string */
        {
               request_ok(errors[8]);
        }
     }
  }
/*ннн*****ннннннн*****ннннннннн*****нннннннннн*****ннннннннн*****ннннн*/
  if(ren==2) 
  {
     connect_dir_file(total_file_name);
     if(Rename(total_file_name1, total_file_name))
     {
        if(*file_name!='\0') /* File was renamed succecfully: */
        {
           adjust_string_gadgets();
           new_drawer();     /* Show user the remaining files. */
        }
        else                 /* A directory was renamed: */
        {
           parent();         /* Go back one directory.   */
        }
     }
     else                    /* Something went wrong:    */
     {
        if(*file_name!='\0')   request_ok(errors[13]);
        else                   request_ok(errors[14]);

        /* Since we have unlocked the directory/file we have */
        /* to lock it again, and clean up the display:       */
        new_drawer();
     }
  }
}
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
USHORT clear_gadgets(STRPTR title)
{
     OnGadget(&gadget_rename, file_window, NULL);
     OnGadget(&gadget_delete, file_window, NULL);
     SetWindowTitles(file_window, title, (char *)(-1));
     ren=0;   gadget_flag=CLEAR;   return(CLEAR);
}
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/
/*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*/




