/***************************************************************************
**                             Filerequester                              **
****************************************************************************
**                            geschrieben von                             **
**                            Daniel Neukomm                              **
**                             Sustenweg 17                               **
**                             CH-3014 Bern                               **
**                           Tel 031/41 80 97                             **
**                    od.   00 41 31 41 80 97 (von Deutschland aus)       **
****************************************************************************
**                Dieses Programm darf man frei kopieren.                 **
**             Das Kopieren ist nur für diejenigen verboten,              **
**         die daraus einen geschäftlichen Profit schlagen wollen         **
**             Die Copyright-Erklärung und meine Adresse muss             **
**                      im Programm stehen bleiben!                       **
***************************************************************************/
/*  Dieser Programmteil wird benutzt um einen Filenamen zu erhalten.
    Dazu wird das Directory angezeigt und der Benützer kann mit der Maus
    auf einen Eintrag draufklicken und so einen Filenamen selektieren.
    Dem Programm muss ein Chararray auf das zu benutzende Directory und
    ein Flag, welches einen Directorywechsel erlaubt oder nicht übergeben
    werden. Zurückgegeben wird im Chararray der Filename. Lief alles
    tadellos, so wird eine Null zurückgegeben, andernfalls eine negative
    Zahl.      */
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <exec/memory.h>
extern struct GfxBase *GfxBase;
extern struct IntuitionBase *IntuitionBase;
extern long Font9;  /*Font9 ist der Zeiger auf den topaz.font 9 */
#define DIRGROESSE 31
#define DIRLAENGE  60
struct Window *wi;
struct IntuiMessage *message;
struct RastPort *RPort;
struct TextAttr Topaz9Attr ={
   (UBYTE *)"topaz.font",
   9,0,0};
struct IntuiText okText = {3,0,JAM1,23,4,&Topaz9Attr,(UBYTE *) "ok",0};
struct IntuiText cancelText ={3,0,JAM1,5,4,&Topaz9Attr,(UBYTE *)"cancel",0};
struct IntuiText STRText ={3,0,JAM1,-45,0,0,(UBYTE *)"Path:",0};
UBYTE DefString[24],UndoString[24];        /*Buffer für Stringgadget*/
struct StringInfo STRString ={
   DefString,UndoString,0,24,0,0,23,0,0,0,NULL,0,NULL };
short Koord[] = {
   0,0, 70,0, 70,17, 0,17, 0,0 };
short STRKoord[] = {
   0,0, 279,0, 279,12, 0,12, 0,0 };
struct Border Border = {
   -1,-1,
   1,0,JAM1,
   5,Koord,NULL  };
struct Border STRBorder = {
   -53,-2,
   2,0,JAM1,
   5,STRKoord,NULL  };
struct Image propimage;
struct PropInfo propInfo ={
   FREEVERT | AUTOKNOB,
   0,0, 0,0xffff, 0,0,0,0,0,0 };
struct Gadget okGadget = {
   0,30,162,70,16,GADGHCOMP,GADGIMMEDIATE| RELVERIFY,
   BOOLGADGET,(APTR)&Border,0,
   &okText,0,0,1,0   };
struct Gadget cancelGadget = {
   &okGadget,200,162,70,16,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,
   BOOLGADGET,(APTR)&Border,0,
   &cancelText,0,0,2,0   };
struct Gadget PropGadget = {
   &cancelGadget,280,20,20,78,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,
   PROPGADGET,(APTR)&propimage,0,
   0,0,(APTR)&propInfo,4,0   };
struct Gadget Pfeil1Gadget = {
   &PropGadget,280,9,20,11,GADGHCOMP,GADGIMMEDIATE| RELVERIFY,
   BOOLGADGET,0,0,
   0,0,0,5,0   };
struct Gadget Pfeil2Gadget = {
   &Pfeil1Gadget,280,98,20,11,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,
   BOOLGADGET,0,0,
   0,0,0,6,0   };
struct Gadget STRGadget = {
   &Pfeil2Gadget,63,118,184,12,GADGHCOMP,GADGIMMEDIATE | RELVERIFY,
   STRGADGET,(APTR)&STRBorder,0,
   &STRText,0,(APTR)&STRString,3,0   };
struct NewWindow nw ={
   170,10,300,190,
   0,1,
   MOUSEBUTTONS | GADGETUP | GADGETDOWN,
   SMART_REFRESH | ACTIVATE | WINDOWDRAG,
   &Pfeil2Gadget,
   NULL,
   (UBYTE *) "Directory",
   NULL,NULL,
   0,0,0,0,
   WBENCHSCREEN
   };
ULONG lock;
char dir[DIRLAENGE][DIRGROESSE];  /*in diesem Array werden die Directory-
                                    Einträge gespeichert */
char Path[30];
short zurueck,Eintraege,modulo;

FileName(File,dirchange)
/*Hier beginnt der Programm-Code des Filerequesters
 Uebergeben werden ein Array, in dem das zu benutzende Directory steht,
 und die Variable dirchange, die besagt, ob ein Directorywechsel erlaubt
 sei (dirchange=1) oder nicht (dirchange=0). */
UBYTE dirchange;
char File[40];
{
register struct FileInfoBlock *InfoBlock;
USHORT Laenge;
short  event;
struct Window *OpenWindow();
struct IntuiMessage *GetMsg();
void *AllocMem();
   zurueck=-1;Eintraege=0;modulo=0;
   if ((InfoBlock=AllocMem(260,MEMF_PUBLIC))==0) return(-2);
   strcpy (DefString,File);
   strcpy (Path,File);
   STRString.NumChars=strlen(File);
   propInfo.VertPot=0;propInfo.VertBody=0xffff;
   if (!(wi = (struct Window *)OpenWindow(&nw)))
        goto closeall;
   RPort=wi->RPort;
   SetFont(RPort,Font9);
   if (dirchange)
   {
   AddGadget (wi,&STRGadget,-1);
   OnGadget  (&STRGadget,wi,0);
   }
   SetAPen(RPort,1);
   Move (RPort,0,108); Draw (RPort,300,108);
   Move (RPort,280,10);Draw (RPort,280,107);
   RectFill (RPort,281,10,298,20);RectFill(RPort,281,98,298,108);
   SetAPen(RPort,2);
   Move (RPort,10,140);Draw (RPort,289,140);Draw (RPort,289,152);
   Draw (RPort,10,152);Draw (RPort,10,140);
   SetAPen(RPort,0);
   Move (RPort,289,18);Draw (RPort,289,11);
   Draw (RPort,282,14);Move (RPort,289,11);Draw (RPort,296,14);
   Move (RPort,289,99);Draw (RPort,289,106);
   Draw (RPort,282,103);Move (RPort,289,106);Draw (RPort,296,103);
   SetAPen(RPort,3);
   if ((lock = Lock(File,SHARED_LOCK))==0)
      {
      DefString[0]=0;
      Path[0]=0;
      if ((lock = Lock("",SHARED_LOCK))==0) goto error;
      }
loop:if (Examine(lock,InfoBlock)==0)
     {
     UnLock(lock);
     DefString[0]=0;
     Path[0]=0;
     if ((lock=Lock("",SHARED_LOCK)==0 && Examine(lock,InfoBlock))==0)
         goto error;
     }
   if (dirchange && Path[0]!=0 && Path[strlen(Path)-1]!=':')
     {
     strcpy (dir,"Parent (Dir)");
     dir[0][DIRGROESSE-1]=0;
     Move (RPort,10,20);
     Text (RPort,dir,12);
     Eintraege++;
     }
   while (Eintraege<10 && ExNext(lock,InfoBlock)!=0)
   if (!(InfoBlock->fib_DirEntryType>0 && !dirchange))
     {
     Move (RPort,10,20+9*Eintraege);
     Laenge=strlen(InfoBlock->fib_FileName);
     if (Laenge>25) Laenge=25;
     Text(RPort,InfoBlock->fib_FileName,Laenge);
     strcpy(&dir[Eintraege][0],InfoBlock->fib_FileName);
     dir[Eintraege][DIRGROESSE-1]=InfoBlock->fib_DirEntryType;
     if (InfoBlock->fib_DirEntryType>0)
        {
        if (Laenge>21) Move (RPort,218,20+9*Eintraege);
        Text (RPort," (Dir)",6);
        }
     if (message=GetMsg(wi->UserPort))
        {
        if ((event=Event())==-1) goto loop;
        if (event==1) goto closeall;
        }
     Eintraege++;
    }
    if (Eintraege==10)
     {
     while(Eintraege<60 && ExNext(lock,InfoBlock)!=0)
     if (!(InfoBlock->fib_DirEntryType>0 && !dirchange))
        {
        dir[Eintraege][DIRGROESSE-1]=InfoBlock->fib_DirEntryType;
        strcpy(&dir[Eintraege][0],InfoBlock->fib_FileName);
        if (message=GetMsg(wi->UserPort))
           {
           if ((event=Event())==-1) goto loop;
           if (event==1) goto closeall;
           }
        Eintraege++;
        }
      ModifyProp(&PropGadget,wi,NULL,FREEVERT | AUTOKNOB,0,propInfo.VertPot,0,0xffff*10/Eintraege);
      }
    while()
      {
      WaitPort(wi->UserPort);
      message = (struct IntuiMessage *) GetMsg(wi->UserPort);
      if ((event=Event())==-1) goto loop;
      if (event==1) goto closeall;
     }
error:
   zurueck=-2;
closeall:
   FreeMem(InfoBlock,260);
   if (lock!=0) UnLock(lock);
   if (dirchange) RemoveGadget(wi,&STRGadget);
   if (wi) CloseWindow(wi);
   if (zurueck<0) return(zurueck);
   strcpy(File,Path);
   if (File[0]!=0 && File[strlen(File)-1]!=':') strcat(File,"/");
   strcat(File,&dir[zurueck][0]);
   return(0);
}

Event()
{
   ULONG MessageClass;
   struct Gadget *gad;
   short Laenge;
   static USHORT toggle=0,oldMouseY;
   register short speicher,var;
   USHORT MouseX;
   USHORT MouseY;
   ULONG  duplock;

   MessageClass = message->Class;
   ReplyMsg(message);
   switch(MessageClass)
      {
      case GADGETDOWN:   goto controlGadgetsdown;
      case GADGETUP:     goto controlGadgetsup;
      case MOUSEBUTTONS: goto controlMouse;
      }

controlGadgetsdown:
   gad= (struct Gadget *) message->IAddress;
   switch (gad->GadgetID)
      {
      case 5: if (modulo>0 && Eintraege>10)                  /* Pfeil1Gad  */
              {
              modulo-=5;
              show();
              ModifyProp(&PropGadget,wi,NULL,FREEVERT | AUTOKNOB,
                   0,0xffff*modulo/(Eintraege-10),0,0xffff*10/Eintraege);
              }
              break;
      case 6: if (modulo+10<Eintraege)                       /* Pfeil2Gad  */
              {
              modulo+=5;
              show();
              ModifyProp(&PropGadget,wi,NULL,FREEVERT | AUTOKNOB,
                   0,0xffff*modulo/(Eintraege-10),0,0xffff*10/Eintraege);
              }
     }
   return(0);
controlGadgetsup:
   gad= (struct Gadget *) message->IAddress;
   switch (gad->GadgetID)
      {
      case 1: return(1);                        /* okGadget   */
      case 2: zurueck=-1;                       /* cancelGad  */
              return(1);
      case 3: if((duplock=Lock(DefString,SHARED_LOCK))==0) /* StrGad     */
                 {
                 strcpy(DefString,Path);
                 DisplayBeep(wi->WScreen);
                 return(0);
                 }
              strcpy(Path,DefString);
              return(changelock(duplock));
      case 4: if (Eintraege<=10) return(0);     /* PropGad    */
              modulo=propInfo.VertPot*(Eintraege-10)/0xffff;
              show(dir);
     }
     return(0);
controlMouse:
   MouseX=message->MouseX;
   MouseY=message->MouseY;
   toggle=1-toggle;
   if (MouseX<260 && MouseY>13 && MouseY<108
       && (speicher=(MouseY-14)/9+modulo)<Eintraege)
      {
      if (dir[speicher][DIRGROESSE-1]==0)         /* ParentDir */
         {
         oldMouseY=MouseY;
         if (toggle==0 || Path[strlen(Path)-1]==':'
             || Path[0]==0) return(0);
         if ((duplock=ParentDir(lock))==0)
              {
              DisplayBeep(wi->WScreen);
              return(0);
              }
         for (var=strlen(Path)-1;var>0 && Path[var]!=':'
             && Path[var]!='/';var--);
         Path[var+1]=0;
         if (Path[var]=='/') Path[var]=0;
         else if (var<=0) Path[0]=0;
         strcpy (DefString,Path);
         return(changelock(duplock));
         }
      if (dir[speicher][DIRGROESSE-1]>0)         /* Dir */
         {
         oldMouseY=MouseY;
         if (toggle==0) return(0);
         Laenge=strlen(Path);
         if (Laenge>0 && Path[Laenge-1]!=':'
             && Path[Laenge-1]!='/') strcat(Path,"/");
         strcat(Path,&dir[speicher][0]);
         if ((duplock=Lock(Path,SHARED_LOCK))==0)
              {
              Path[Laenge]=0;
              DisplayBeep(wi->WScreen);
              return(0);
              }
         strcpy (DefString,Path);
         return(changelock(duplock));
         }
         if (MouseY-oldMouseY<5 && oldMouseY-MouseY<5)
               { oldMouseY=0;return(0); }
         zurueck=speicher;
         Laenge=strlen(&dir[zurueck][0]);
         if (Laenge>25) Laenge=25;
         Move (RPort,15,148);
         Text (RPort,&dir[zurueck][0],Laenge);
         Text (RPort,"                         ",25-Laenge);
         oldMouseY=MouseY;
      }
   return(0);
}

show()
{
   short l,Laenge;
   if (modulo+10>Eintraege) modulo=Eintraege-10;
   if (modulo<0) modulo=0;
   for (l=0;l<10;l++)
      {
      Move (RPort,10,20+l*9);
      Laenge = strlen(&dir[modulo+l][0]);
      if (Laenge>25) Laenge=25;
      Text (RPort,&dir[modulo+l][0],Laenge);
      if (dir[modulo+l][DIRGROESSE-1]>0)
         {
         if (Laenge>21) {Move (RPort,218,20+9*l); Laenge=19;}
         Text (RPort," (Dir)",6);
         Laenge+=6;
         }
      Text (RPort,"                         ",25-Laenge);
      }
}

changelock(duplock)
ULONG duplock;
{
   UnLock(lock);
   lock=duplock;
   Eintraege=0;modulo=0;zurueck=-1;
   SetAPen(RPort,0);
   RectFill(RPort,10,10,260,105);
   RectFill(RPort,11,141,288,151);
   SetAPen(RPort,3);
   ModifyProp(&PropGadget,wi,0,FREEVERT | AUTOKNOB,0,0,0,0xffff);
   return(-1);
}
