#include "Open.h"

char *OpenDisk (MyScreen, Pos_x, Pos_y, Titel)
struct Screen *MyScreen;
short Pos_x,Pos_y;
UBYTE Titel[];
{
  static char Filename[232],*Char_ptr;
  char *strrchr();
  struct Lock *Dir;
  short int i,Anzahl, ReadDir(), Y, LastCount;
  struct Gadget *Gad_ptr;
  USHORT Gad_ID;
  void Fill_in(),ENDE(),getdisks(), movmem();
  long int help;

  if (!(DOSBase = (struct DosLibrary *)OpenLibrary ("dos.library",0L)))
    ENDE (DISK_ERR);
  if (!(IntuitionBase = OpenLibrary ("intuition.library",0L))) 
    ENDE (INTUI_ERR);
  MyNewWindow.LeftEdge = Pos_x;
  MyNewWindow.TopEdge  = Pos_y;
  MyNewWindow.Screen   = MyScreen;
  MyNewWindow.Type = (MyScreen == NULL) ? WBENCHSCREEN : CUSTOMSCREEN;
  if ( !(MyWindow = OpenWindow (&MyNewWindow))) ENDE (WIN_ERR);
  OpenTitle.IText = Titel;
  OpenGad_7_Info.Flags = AUTOKNOB | FREEVERT;
  OpenGad_7_Info.VertPot = 0;
  OpenGad_7_Info.VertBody = 0xFFFF;
  getdisks();
  if (!Drive1) OpenGad [12].Flags |= GADGDISABLED;
  if (!DriveH) OpenGad [14].Flags |= GADGDISABLED;
  OpenGad_6_Image.ImageData = AllocMem (20L, MEMF_CHIP);
  OpenGad_8_Image.ImageData = AllocMem (20L, MEMF_CHIP);
  if (OpenGad_6_Image.ImageData == NULL || OpenGad_6_Image.ImageData == NULL)
    ENDE (MEM_ERR);
  movmem (OpenGad_6_Image_Data, OpenGad_6_Image.ImageData, 20L);
  movmem (OpenGad_8_Image_Data, OpenGad_8_Image.ImageData, 20L);
  if ( !(Request( &Open_Rqst, MyWindow))) ENDE (RQST_ERR);

  Anzahl = ReadDir (OG_10_Buf);

  ReqChanged = FALSE;
  Count = 0;
  do 
  {
    Wait ( 1L << MyWindow->UserPort->mp_SigBit );
    while (IMessage = (struct IntuiMessage*) GetMsg ( MyWindow->UserPort ))
    {
      MessageClass = IMessage->Class;
      Gad_ptr = (struct Gadget *)IMessage->IAddress;
      ReplyMsg (IMessage);
 
      if (MessageClass == GADGETUP)
      {
        Gad_ID = Gad_ptr->GadgetID;
        switch (Gad_ID)
        {
          case 0:;
          case 1:;
          case 2:;
          case 3:;
          case 4:;
          case 5:if (Gad_ID > Anzahl) break;
                 if (Daten [Count + Gad_ID].Typ > 0L)
                 {
                   if ( OG_10_Buf [ strlen (OG_10_Buf) - 1 ] != ':' )
                     strcat ( OG_10_Buf, "/");
                   strcat (OG_10_Buf, Daten [Count + Gad_ID].Name);
                   Anzahl = ReadDir (OG_10_Buf);
                 }
                 else
                 {
                   strcpy (OG_9_Buf, Daten [Count + Gad_ID].Name);
                   RefreshGadgets ( &OpenGad [10], MyWindow, &Open_Rqst);
                 }
                 break;
          case 6:if (Count > 0)
                 {
                   Count--;
                   OpenGad_7_Info.VertPot -= 0xFFFF / Anzahl;
                   Fill_in (Anzahl);
                 }
                 break;
          case 7:break;
          case 8:if (Count <  Anzahl - 6)
                 {
                   Count++;
                   OpenGad_7_Info.VertPot += 0xFFFF / Anzahl;
                   Fill_in (Anzahl);
                 }
                 break;
          case 9:break;
          case 10:if (!(Anzahl =  ReadDir (OG_10_Buf)))
                    DisplayBeep (MyScreen);
                  break;
          case 11:;
          case 12:;
          case 13:;
          case 14:strcpy (OG_10_Buf, OpenGad_Text [Gad_ID].IText);
                  if (!(Anzahl =  ReadDir (OG_10_Buf)))
                    DisplayBeep (MyScreen);
                  break;
          case 15:if (Char_ptr = strrchr (OG_10_Buf, (long)'/'))
                    *Char_ptr = '\0';
                  else if (Char_ptr = strrchr (OG_10_Buf, (long)':'))
                    *(Char_ptr + 1) = '\0';
                  else
                    strcpy (OG_10_Buf, ":");
                  if (!(Anzahl =  ReadDir (OG_10_Buf)))
                    DisplayBeep (MyScreen);
                  break;
          case 100:ReqChanged = TRUE;
                     break;
          default:break;
        } /* switch */
      } /* if */
      else if (MessageClass == GADGETDOWN && Anzahl > 6)
      {
        if (OpenGad_7_Info.Flags & KNOBHIT)
        {
          ModifyIDCMP (MyWindow, MOUSEMOVE | DELTAMOVE | GADGETUP);
          do
          {
            Wait ( 1L << MyWindow->UserPort->mp_SigBit );
            while ((IMessage=(struct IntuiMessage*)GetMsg(MyWindow->UserPort))
                     && (MessageClass = IMessage->Class) != GADGETUP)
            {
              Y = IMessage->MouseY;
              ReplyMsg (IMessage);
              if ( Y == 0 ) continue;
              LastCount = Count;
              help = (long)OpenGad_7_Info.VertPot * (long)Anzahl;
              Count = (short)(help >> 16);
              if (Count > Anzahl - 6) Count = Anzahl - 6;
              if (Count != LastCount) Fill_in (Anzahl);
            } /* while */
          } /* do */
          while (MessageClass != GADGETUP);
        } /* if */
        ModifyIDCMP (MyWindow, REQCLEAR | GADGETDOWN | GADGETUP);
        help = (long)OpenGad_7_Info.VertPot * (long)Anzahl;
        Count = (short)(help >> 16);
        if (Count > Anzahl - 6) Count = Anzahl - 6;
        Fill_in (Anzahl);
      } /* else if */               
    } /* while */
  } /* do */
  while (MessageClass != REQCLEAR);
  CloseWindow (MyWindow);
  CloseLibrary (IntuitionBase);
  free (Daten);
  if (ReqChanged)
  {
    strcpy (Filename, OG_10_Buf);
    if ( Filename [strlen (Filename) -1] != ':') strcat (Filename, "/");
    strcat (Filename, OG_9_Buf);
    return (Filename);
  }
  else return ((char *)NULL);
}

short int ReadDir (DirName)
char DirName[];
{
  struct Lock *DirLock;
  struct FileInfoBlock *FileInfo;
  short int i;
  long Fehler,help;
  long int Vergleich();
  char *calloc();
  void movmem();
  struct Inhalt *Help2;

  Daten = (struct Inhalt *)calloc ((long)sizeof(struct Inhalt), 50L);
  Count = 0;
  if (!(DirLock = Lock (DirName ,ACCESS_READ)))
    return (0);
  FileInfo = (struct FileInfoBlock*) AllocMem 
               ((long)sizeof(struct FileInfoBlock), MEMF_CLEAR);
  if (FileInfo == NULL) ENDE (MEM_ERR);
  if (!(Examine (DirLock, FileInfo))) return (0);
  for (i = 0; ExNext (DirLock, FileInfo) ; i++)
  {
    strncpy (Daten[i].Name , FileInfo->fib_FileName, 30L);
    Daten[i].Typ = FileInfo->fib_DirEntryType;
    if (i % 50  == 49) 
    {
      Help2 = (struct Inhalt *) calloc ((long)sizeof(struct Inhalt),i + 51);
      movmem (Daten, Help2, (long)(i + 1) * sizeof(struct Inhalt));
      if (Daten == NULL) ENDE (MEM_ERR);
    }
  }
  if ((Fehler = IoErr()) != ERROR_NO_MORE_ENTRIES) ENDE (DISK_ERR);
  UnLock (DirLock);
  FreeMem ( FileInfo, (long)sizeof(struct FileInfoBlock));
  if (i == 0)
  {
    OpenGad_7_Info.VertBody = 0xFFFF;
    OpenGad_7_Info.VertPot = 0;
  }
  else
  {  
    qsort (Daten, (long)i, (long)sizeof (struct Inhalt), Vergleich);
    help = 0xFFFFL * 6L / (long)i;
    OpenGad_7_Info.VertBody = (i > 6) ? (short)help : 0xFFFF;
    OpenGad_7_Info.VertPot = 0;
  }
  OG_9_Buf [0] = '\0';
  Fill_in (i);
  return (i);
}

void Fill_in (Max_Anz)
short int Max_Anz;
{
  short int i;

  for (i = 0 ; i < 6 ; i++)
  {
    if (i < Max_Anz) 
    {
      strcpy (DisplayString[i], Daten[Count + i].Name);
      strncat (DisplayString[i] , LeerString, 30L - strlen (DisplayString[i]));
      OpenGad_Text[i].IText = (UBYTE *)DisplayString [i];
      OpenGad_Text[i].FrontPen = (Daten[Count + i].Typ > 0L) ? 1 : 0;
    }
    else
      OpenGad_Text[i].IText = (UBYTE *)LeerString;
  }
  RefreshGadgets ( &OpenGad [10], MyWindow, &Open_Rqst);
}

long int Vergleich(a,b)
struct Inhalt *a,*b;
{
  extern int strcmp();

  if (a->Typ > 0L)
  {
    if (b->Typ > 0L) return (strcmp(a->Name,b->Name));
    else return (-1L);
  }
  else if (b->Typ > 0L) return (1L);
  else return (strcmp(a->Name,b->Name));
}

void btoc(bstring)
char *bstring;
{
 register UBYTE len,count,*cstring; 
 
 cstring = (UBYTE *) bstring;
 len = cstring[0];              
 for(count=0;count < len;count++)
  cstring[count] = cstring[count+1];
 cstring[count] = '\0';
}

void getdisks()
{
  struct RootNode                    *rnode; 
  struct DosInfo                    *dinfo;
  register struct DeviceNode          *dnode;
  char          *bname,aname[32];
  void btoc();

  rnode   = (struct RootNode *)  DOSBase->dl_Root;
  dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);
 
  Forbid();
  for(dnode = (struct DeviceNode *) BADDR(dinfo->di_DevInfo);BADDR(dnode);
         dnode = (struct DeviceNode *) BADDR(dnode->dn_Next))
  {
    if(!dnode->dn_Type && dnode->dn_Task && BADDR(dnode->dn_Name)) 
    {
      bname = (char *) BADDR(dnode->dn_Name);    
      movmem (bname,aname,(ULONG)bname[0]+1L);
      btoc(aname);
      if (strncmp (aname,"DF1",3L) == 0L) Drive1 = TRUE;
      if (strncmp (aname,"DH0",3L) == 0L) DriveH = TRUE;
    }
  }
  Permit(); 
}

void ENDE(nr)
short int nr;
{
  puts (errors[nr]);
  exit (nr);
}
