/**************************************************************************/
/*                                                                        */
/*  Multitool II   -   DOS-Hilfsprogramm                Version 1.3r001   */
/*                                                                        */
/*  ©1992 Boris Jakubaschk                                                */
/*                                                                        */
/*  Modul 1 - Einlesen und Ausgeben von Verzeichnislisten                 */
/*                                                                        */
/**************************************************************************/

#include "MToolDefs.h"

/* Datenbereiche für Verzeichnislisten */

struct ExAllData *VL_Data[2];
char   VL_Active = 0;
char   VL_OldAct = 0;
char  *VL_Name[2];
char   VL_Name1[130] = "";
char   VL_Name2[130] = "";
ULONG  VL_NumEntry[2];
ULONG  VL_OldFI[2];
char   VL_Valid[2] = 0;
char  *VL_Select[2];
ULONG  VL_OldCS[2];
char   VL_OldSM[2];
short  MaxLen[2] = 0;
short  VL_XPos[2];
char   VL_Archiv = ~0; 
char   VL_OldArc = ~0; 
ULONG  VL_BytSel = 0;
ULONG  VL_BlkSel = 0;
ULONG  VL_StatFree[2];
ULONG  VL_Marked[2] = 0;
char  *VL_StatStat[2];

/* GetDir     : Verzeichnis einlesen und sortiert anzeigen
    Act         0=linkes, 1=rechtes Dateienfenster
    Dir         Verzeichnisname */

LONG GetDir( char Act, char *Dir )
    {
    struct FileLock *FL;
    struct ExAllControl *EAC;
    struct ExAllData *EAD, *EAD2;
    
    WaitPointer( Wnd );
    SetAPen( Wnd->RPort, 0 );
    RectFill( Wnd->RPort, LY_LXOffset[Act], LY_TopList+2, LY_LXOffset[Act]+LY_LXS-6, LY_TopList+LY_LYS+1 );

    if (VL_Archiv==Act)
        {
        VL_Archiv=~0;
        GT_SetGadgetAttrs(Gadgets[1+Act*14], Wnd, 0, GTST_String, VL_Name[Act], GA_Disabled, FALSE, TAG_DONE);
        };

    GetStat( Act );

    MB_FreeID( 0x1000+Act );
    VL_NumEntry[Act]=0;

    if (VL_Data[Act]=(struct ExAllData *)MB_Alloc( 4096, 0, 0x1000+Act ))
        {
        VL_Data[Act]->ed_Next = 0;
        VL_Data[Act]->ed_Name = 0;

        if ( VL_Valid[Act] )
            {
            if ( EAC = (struct ExAllControl *)AllocDosObject(DOS_EXALLCONTROL, NULL) )
                {
                EAC->eac_LastKey = 0;
                if ( FL = (struct FileLock *)Lock(Dir, ACCESS_READ) )
                    {
                    EAD = VL_Data[Act];
                    while (ExAll((BPTR)FL, EAD, 4096, ED_PROTECTION, EAC))
                        {
                        VL_NumEntry[Act]+=EAC->eac_Entries;
                        EAD2=EAD;
                        while (EAD2->ed_Next != NULL) EAD2 = EAD2->ed_Next;
                        EAD = (struct ExAllData *)MB_Alloc( 4096, 0, 0x1000+Act );
                        EAD2->ed_Next = EAD;
                        };
                    UnLock((BPTR)FL);
                    VL_NumEntry[Act]+=EAC->eac_Entries;
                    VL_Select[Act] = (char *)MB_Alloc( VL_NumEntry[Act]+200, MEMF_CLEAR, 0x1000+Act );
                    VL_Marked[Act] = 0;
                    VL_OldFI[Act] = 0;
                    GT_SetGadgetAttrs(Gadgets[16*Act], Wnd, 0, GTSC_Total, VL_NumEntry[Act], GTSC_Top, 0, TAG_DONE);
                    SortDir(Act);
                    ClrSelect( Act ); /* Übernimmt auch die Anzeige */
                    }
                else ErrorReq();
                FreeDosObject(DOS_EXALLCONTROL, EAC);
                }
            else ErrorReq();
            };
        };
    StdPointer( Wnd );
    }

GetArcList( char Act, char *ArcName )
    {
    struct FileHandle *FH;
    char   Buffer[130];
    struct ExAllData *EAD;
    char   *StrEntry;
    short i, len;

    VL_Archiv=Act;

    GetStat( VL_Active );

    WaitPointer( Wnd );
    SetAPen( Wnd->RPort, 0 );
    RectFill( Wnd->RPort, LY_LXOffset[Act], LY_TopList+2, LY_LXOffset[Act]+LY_LXS-6, LY_TopList+LY_LYS+1 );
    GT_SetGadgetAttrs(Gadgets[1+Act*14], Wnd, 0, GTST_String, ArcName, GA_Disabled, TRUE, TAG_DONE);
    strcpy( VL_Name[Act], ArcName );
    if ( FH=(struct FileHandle *)Open( "T:MT_Temp", MODE_OLDFILE ) )
        {
        MB_FreeID( 0x1000+Act );
        VL_NumEntry[Act] = 0;
        if (VL_Data[Act]=(struct ExAllData *)MB_Alloc( 4096, MEMF_CLEAR, 0x1000+Act ))
            {
            EAD = VL_Data[Act];
            StrEntry = ((char *)EAD) + 4096;

            while (FGets( (BPTR)FH, Buffer, 130 ) && Buffer[0]!='-');

            while (FGets( (BPTR)FH, Buffer, 130 ))
                {
                if (strlen(Buffer)>1 & Buffer[0]=='-') break;
                if (strlen(Buffer)>1 & Buffer[0]!=':')
                    {
                    if (StrEntry<((char *)EAD)+150)
                        {
                        EAD--;
                        if (NOT(EAD->ed_Next = (struct ExAllData *)MB_Alloc( 4096, MEMF_CLEAR, 0x1000+Act ))) break;
                        EAD = EAD->ed_Next;
                        StrEntry = ((char *)EAD) + 4096;
                        };
                    VL_NumEntry[Act]++;
                    StrEntry = StrEntry - strlen(Buffer) - 1;
                    strcpy( StrEntry, Buffer );
                    StrEntry[strlen(StrEntry)-1]='\0';
                    EAD->ed_Name = StrEntry;
                    FGets( (BPTR)FH, Buffer, 130 );
                    sscanf( Buffer, "%d", &(EAD->ed_Size) );
                    EAD->ed_Prot = 0;
                    for( i=0; i<4; i++ )
                        if (Buffer[49-i]=='-') EAD->ed_Prot = EAD->ed_Prot | (1<<i);
                    for( i=4; i<8; i++ )
                        if (Buffer[49-i]!='-') EAD->ed_Prot = EAD->ed_Prot | (1<<i);
                    EAD->ed_Type = -1;
                    EAD->ed_Next = EAD+1;
                    EAD++;
                    };
                };
            };
        Close((BPTR)FH);
        EAD--;
        EAD->ed_Next = NULL;
        RemMT_Temp();
        VL_Select[Act] = (char *)MB_Alloc( VL_NumEntry[Act]+200, MEMF_CLEAR, 0x1000+Act );
        GT_SetGadgetAttrs(Gadgets[16*Act], Wnd, 0, GTSC_Total, VL_NumEntry[Act], GTSC_Top, 0, TAG_DONE);
        MaxLen[Act] = 5;
        EAD = VL_Data[Act];
        for (i=0; i<VL_NumEntry[Act]; i++)
            {
            len=strlen(EAD->ed_Name);
            MaxLen[Act] = ( len>MaxLen[Act] ) ? len : MaxLen[Act];
            EAD = EAD->ed_Next;
            };
        VL_Marked[Act] = 0;
        VL_OldFI[Act] = 0;
        GT_SetGadgetAttrs(Gadgets[19+Act], Wnd, 0, GTSC_Total, MaxLen[Act]+18, GTSC_Top, 0, TAG_DONE);
        ClrSelect( Act ); /* Übernimmt die Anzeige */
        };
    StdPointer( Wnd );
    }

/* SortDir     : interne Funktion von GetDir; Verzeichnisliste sortieren
                 (Bubblesort, da einfach verkettete Liste)
    Act          0=linkes, 1=rechtes Dateienfenster */

SortDir( char Act )
    {
    struct ExAllData *EAD;
    char   Swapped = 1;
    char   *a, *b;
    short  i;
    short  len;
    
    MaxLen[Act] = 5;
    while (Swapped)
        {
        EAD = VL_Data[Act] ;
        Swapped=0;
        for (i=0; EAD->ed_Next!=0; i++)
            {
            if (EAD->ed_Type<0 & EAD->ed_Next->ed_Type>=0)
                {
                Swapped=1;
                SwapEAD( EAD, EAD->ed_Next);
                }
            else if (EAD->ed_Type == EAD->ed_Next->ed_Type)
                {
                a=EAD->ed_Name;
                b=EAD->ed_Next->ed_Name;
                if ( stricmp(a, b)>0 )
                    {
                    Swapped=1;
                    SwapEAD( EAD, EAD->ed_Next);
                    };
                };
            EAD = EAD->ed_Next;
            };
        EAD = VL_Data[Act] ;
        for (i=0; i<VL_NumEntry[Act]; i++)
            {
            len=strlen(EAD->ed_Name);
            MaxLen[Act] = ( len>MaxLen[Act] ) ? len : MaxLen[Act];
            EAD = EAD->ed_Next;
            };
        GT_SetGadgetAttrs(Gadgets[19+Act], Wnd, 0, GTSC_Total, MaxLen[Act]+18, GTSC_Top, 0, TAG_DONE);
        VL_XPos[Act] = 0;
        };
    }


/* SwapEAD     : interne Funktion von SortDir, vertauschen zweier Listenelemente
    EAD1, EAD2   Zeiger auf Listenelemente */

SwapEAD( struct ExAllData *EAD1, struct ExAllData *EAD2 )
    {
    LONG   Puffer1;
    ULONG  Puffer2;
    UBYTE *Puffer3;

    Puffer1 = EAD1->ed_Type;
    EAD1->ed_Type = EAD2->ed_Type;
    EAD2->ed_Type = Puffer1;
    Puffer2 = EAD1->ed_Size;
    EAD1->ed_Size = EAD2->ed_Size;
    EAD2->ed_Size = Puffer2;
    Puffer3 = EAD1->ed_Name;
    EAD1->ed_Name = EAD2->ed_Name;
    EAD2->ed_Name = Puffer3;
    Puffer2 = EAD1->ed_Prot;
    EAD1->ed_Prot = EAD2->ed_Prot;
    EAD2->ed_Prot = Puffer2;
    }


/* ShowDir     : Anzeige eines Dateienfensters
    Act          0=linkes, 1=rechtes Dateienfenster
    FirstItem    erstes Element im Fenster (scrolling) */

ShowDir( char Act, ULONG FirstItem, char Force )
    {
    ULONG i;
    short j;
    char Dummy[120];
    char DMask[25];
    char FMask[25];
    struct ExAllData *EAD;
    if (FirstItem==VL_OldFI[Act]+1 & !Force)
        {
        ScrollRaster( Wnd->RPort, 0, LY_LFontH, LY_LXOffset[Act], LY_TopList+2, LY_LXOffset[Act]+LY_LXS-6, LY_TopList+LY_LYS+1 );
        ShowDirLine( Act, FirstItem, LY_LNumLines-1 );
        if (VL_Marked[Act] > 0) ShowDirLine( Act, FirstItem, VL_Marked[Act]-1 );
        ShowDirLine( Act, FirstItem, VL_Marked[Act] );
        }
    else if (FirstItem==VL_OldFI[Act]-1 & !Force)
        {
        ScrollRaster( Wnd->RPort, 0, -LY_LFontH, LY_LXOffset[Act], LY_TopList+2, LY_LXOffset[Act]+LY_LXS-6, LY_TopList+LY_LYS+1 );
        ShowDirLine( Act, FirstItem, 0 );
        if (VL_Marked[Act] < LY_LNumLines-1) ShowDirLine( Act, FirstItem, VL_Marked[Act]+1 );
        ShowDirLine( Act, FirstItem, VL_Marked[Act] );
        }
    else if (FirstItem!=VL_OldFI[Act] | Force)
        {
        sprintf( DMask, "%%-%ds  HSPARWED", MaxLen[Act]+8 );
        sprintf( FMask, "%%-%ds%%8d  HSPARWED", MaxLen[Act] );
        EAD = VL_Data[Act];
        for (i=0; i<FirstItem; i++) EAD = EAD->ed_Next;
        for (i=0; i<VL_NumEntry[Act] & i<LY_LNumLines; i++)
            {
            SetAPen( Wnd->RPort, (EAD->ed_Type<0) ? 1 : 2 );
            if (EAD->ed_Type<0 | EAD->ed_Size!=0)
                {
                sprintf(Dummy, FMask, EAD->ed_Name, EAD->ed_Size);
                }
            else
                {
                sprintf(Dummy, DMask, EAD->ed_Name);
                };
            for (j=7; j>=4; j--) 
                {
                if ( NOT(EAD->ed_Prot & (1<<j)))
                    Dummy[MaxLen[Act]+17-j]='-';
                };
            for (j=3; j>=0; j--) 
                {
                if (EAD->ed_Prot & (1<<j))
                    Dummy[MaxLen[Act]+17-j]='-';
                };
            SetBPen( Wnd->RPort, (VL_Select[Act][FirstItem+i]==0) ? 0 : 3 );
            SetSoftStyle( Wnd->RPort, (i==VL_Marked[Act]) ? FSF_BOLD : 0, FSF_BOLD );
            Move( Wnd->RPort, LY_LXOffset[Act], LY_TopList+LY_LFontH*i+LY_LBaseLine+2 );
            Text( Wnd->RPort, &Dummy[VL_XPos[Act]], (LY_LNumChars>MaxLen[Act]+18) ? MaxLen[Act]+18 : LY_LNumChars );
            EAD = EAD->ed_Next;
            };
        };
    VL_OldFI[Act]=FirstItem;
    SetBPen( Wnd->RPort, 0 );
    SetSoftStyle( Wnd->RPort, 0, FSF_BOLD );
    }


/* ShowDirLine : Anzeige einer Zeile eines Dateienfensters
    Act          0=linkes, 1=rechtes Dateienfenster
    FirstItem    erstes Element im Fenster (scrolling)
    Pos          Position der Zeile von oben */

ShowDirLine( char Act, ULONG FirstItem, char Pos )
    {
    ULONG i;
    short j;
    char Dummy[80];
    char Mask[25];
    struct ExAllData *EAD;
    
    if (FirstItem+Pos<VL_NumEntry[Act] && Pos<LY_LNumLines)
        {
        EAD = VL_Data[Act];
        for (i=0; i<FirstItem+Pos & EAD->ed_Next!=0; i++) EAD = EAD->ed_Next;
        if (i==FirstItem+Pos)
            {
            SetAPen( Wnd->RPort, (EAD->ed_Type<0) ? 1 : 2 );
            if (EAD->ed_Type<0 | EAD->ed_Size!=0)
                {
                sprintf( Mask, "%%-%ds%%8d  HSPARWED", MaxLen[Act] );
                sprintf(Dummy, Mask, EAD->ed_Name, EAD->ed_Size);
                }
            else
                {
                sprintf( Mask, "%%-%ds  HSPARWED", MaxLen[Act]+8 );
                sprintf(Dummy, Mask, EAD->ed_Name);
                };
            for (j=7; j>=4; j--) 
                {
                if ( NOT(EAD->ed_Prot & (1<<j)))
                    Dummy[MaxLen[Act]+17-j]='-';
                };
            for (j=3; j>=0; j--) 
                {
                if (EAD->ed_Prot & (1<<j))
                    Dummy[MaxLen[Act]+17-j]='-';
                };
            SetBPen( Wnd->RPort, (VL_Select[Act][FirstItem+Pos]==0) ? 0 : 3 );
            SetSoftStyle( Wnd->RPort, (Pos==VL_Marked[Act]) ? FSF_BOLD : 0, FSF_BOLD );
            Move( Wnd->RPort, LY_LXOffset[Act], LY_TopList+LY_LFontH*Pos+LY_LBaseLine+2 );
            Text( Wnd->RPort, &Dummy[VL_XPos[Act]], (LY_LNumChars>MaxLen[Act]+18) ? MaxLen[Act]+18 : LY_LNumChars );
            SetSoftStyle( Wnd->RPort, 0, FSF_BOLD );
            };
        VL_OldFI[Act]=FirstItem;
        SetBPen( Wnd->RPort, 0 );
        }
    }
