/**************************************************************************/
/*                                                                        */
/*  Multitool II   -   DOS-Hilfsprogramm                Version 1.3r000   */
/*                                                                        */
/*  ©1992 Boris Jakubaschk                                                */
/*                                                                        */
/*  Modul 4 - Analyse: Datei analysieren und Typ bestimmen/aufschlüsseln  */
/*                                                                        */
/**************************************************************************/

#include "MToolDefs.h"

/* Datenbereich für Analyse */

struct Node Ana_Nodes[80];
struct MinList Ana_List;
char Ana_Strings[1000];
ULONG Ana_StrEntry = 0l;
ULONG Ana_NumEntry = 0l;
char *Ana_Command[40];
char *Ana_Prefs = 0l;
LONG  Ana_Len = 0l;

struct TagItem    AreqWindowTags[] = {
    WA_Left,          0,
    WA_Top,           0,
    WA_Width,         0,
    WA_Height,        0,
    WA_IDCMP,         IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_GADGETDOWN|IDCMP_GADGETUP|IDCMP_CLOSEWINDOW|IDCMP_INTUITICKS|IDCMP_REFRESHWINDOW|IDCMP_VANILLAKEY,
    WA_Flags,         WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
    WA_Gadgets,       0l,
    WA_Title,         0l,
    WA_ScreenTitle,   0l,
    WA_PubScreen,     NULL,
    TAG_DONE };


Analyse( Act )
    {
    int i;
    long Exit = 0 ;
    struct ExAllData *EAD;
    struct TextFont *Font;

    if (TestSelect( Act ))
        {
        OpenAnalyseReq();

        if (Font=(struct TextFont *)OpenDiskFont( &GadgetFont ))
           SetFont( AreqWnd->RPort, Font );

        EAD = VL_Data[Act];

        for (i=0; i<VL_NumEntry[Act] & Exit!=1 ; i++)
            {
            if ( VL_Select[Act][i] & EAD->ed_Type<0 )
                {
                Exit = AnalyseObj( Act, EAD->ed_Name );
                VL_Select[Act][i]=0;
                if ( i>=VL_OldFI[Act] & i<VL_OldFI[Act]+LY_LNumLines )
                    {
                    ShowDirLine( Act, VL_OldFI[Act], i-VL_OldFI[Act] );
                    };
                };
            EAD = EAD->ed_Next;
            };

        if ( Font ) CloseFont( Font );
        CloseAnalyseReq();
        GetDir( Act, VL_Name[Act] );
        };
    }


long AnalyseObj( Act, *Name )
    {
    char Exit = 0;
    char i;
    LONG Typ;
    char *Buffer;
    char FileName[130];
    short y1;
    ULONG Protect;
    ULONG ProtChng = 0l;
    struct FileHandle *FH;
    struct FileInfoBlock *FIB;
    struct DateTime DT;
    char *Key = LS[MSG_4_T_Keys];
    ULONG  GClass;
    USHORT GCode;
    struct Gadget *GList;

    Ana_List.mlh_Head = (struct Node *)&Ana_List.mlh_Tail;
    Ana_List.mlh_Tail = (struct Node *)0l;
    Ana_List.mlh_TailPred = (struct Node *)&Ana_List.mlh_Head;
    Ana_StrEntry = 0l;
    Ana_NumEntry = 0l;
    DT.dat_Format = FORMAT_DOS;
    DT.dat_Flags = 0;

    y1 = Scr->BarHeight+4;
    SetAPen( AreqWnd->RPort, 0 );
    RectFill( AreqWnd->RPort, 12, y1+1, AreqWnd->RPort->TxWidth*50-12, y1+1+LY_GFontH );
    SetAPen( AreqWnd->RPort, 1 );
    Move( AreqWnd->RPort, 14, y1+AreqWnd->RPort->TxBaseline+1 );
    Text( AreqWnd->RPort, Name, strlen(Name) );

    if( FIB=AllocMem( sizeof(struct FileInfoBlock), MEMF_ANY ) )
        {
        if( Buffer=AllocMem( 256, MEMF_ANY ) )
            {
            strcpy( FileName, VL_Name[Act] );
            AddPart( FileName, Name, 130 );

            if( FH=(struct FileHandle *)Open( FileName, MODE_OLDFILE ) )
                {
                ExamineFH( (BPTR)FH, FIB );
                Protect = FIB->fib_Protection;
                for (i=0; i<4; i++)
                    GT_SetGadgetAttrs(AreqGadgets[4+i], AreqWnd, 0, GTCB_Checked, (Protect & (1<<(7-i)))!=0, TAG_DONE);
                for (i=4; i<8; i++)
                    GT_SetGadgetAttrs(AreqGadgets[4+i], AreqWnd, 0, GTCB_Checked, (Protect & (1<<(7-i)))==0, TAG_DONE);

                sprintf( Buffer, LS[MSG_4_T_FileSize], FIB->fib_Size );
                AddListEntry( Buffer );
                if (FIB->fib_NumBlocks == 1)
                    {
                    sprintf( Buffer, LS[MSG_4_T_1Block] );
                    }
                else
                    sprintf( Buffer, LS[MSG_4_T_Blocks], FIB->fib_NumBlocks );
                AddListEntry( Buffer );
                AddListEntry( "" );

                DT.dat_StrDay = Buffer+130;
                DT.dat_StrDate = Buffer+150;
                DT.dat_StrTime = Buffer+170;
                DT.dat_Stamp.ds_Days = FIB->fib_Date.ds_Days;
                DT.dat_Stamp.ds_Minute = FIB->fib_Date.ds_Minute;
                DT.dat_Stamp.ds_Tick = FIB->fib_Date.ds_Tick;
                if ( DateToStr( &DT ) )
                    {
                    sprintf( Buffer, LS[MSG_4_T_Time], Buffer+130, Buffer+150, Buffer+170 );
                    AddListEntry( Buffer );
                    AddListEntry( "" );
                    };

                Typ = AnalyzeBuffer( FH, Buffer );
                Close( (BPTR)FH );

                if ((Typ==0 & strnicmp( FileName + strlen(FileName) - 4, ".mod", 4 )==0) ||
                    (Typ==0 & strnicmp( Name, "mod.", 4 )==0 ))
                    {
                    AddListEntry( LS[MSG_4_T_MODFile] );
                    Typ = 4;
                    };

                GT_SetGadgetAttrs(AreqGadgets[0], AreqWnd, 0, GTLV_Labels, &Ana_List, TAG_DONE);

                for(;Exit==0;)
                    {
                    Wait(1 << AreqWnd->UserPort->mp_SigBit);
                    while ( msg = (struct IntuiMessage *) GT_GetIMsg(AreqWnd->UserPort))
                        {
                        GClass  = msg->Class;
                        GCode   = msg->Code;
                        if (GClass & (GADGETDOWN | GADGETUP | MOUSEMOVE) )
                            GList   = (struct Gadget *) msg->IAddress;
                        GT_ReplyIMsg(msg);
                        switch (GClass)
                            {
                            case CLOSEWINDOW :
                                Exit=1;
                                break;
                            case GADGETDOWN  :
                            case GADGETUP    :
                                switch (GList->GadgetID)
                                    {
                                    case AGD_Abbruch:
                                        Exit=1;
                                        break;
                                    case AGD_Weiter:
                                        Exit=2;
                                        break;
                                    case AGD_Mon:
                                        FileAktion( FileName, 6 );
                                        break;
                                    case AGD_Hide:
                                    case AGD_Script:
                                    case AGD_Pure:
                                    case AGD_Archive:
                                    case AGD_Read:
                                    case AGD_Write:
                                    case AGD_Execute:
                                    case AGD_Delete:
                                        ProtChng = ProtChng ^ ( 1 << (12 - GList->GadgetID) );
                                        break;
                                    case AGD_Aktion:
                                        FileAktion( FileName, Typ );
                                        break;
                                    };
                                break;
                            case VANILLAKEY  :
                                for (i=0; i<12 & Key[i]!=GCode; i++);
                                if (i<4)
                                    {
                                    ProtChng = ProtChng ^ ( 1 << (7 - i) );
                                    GT_SetGadgetAttrs(AreqGadgets[4+i], AreqWnd, 0, GTCB_Checked, ((Protect ^ ProtChng) & (1<<(7-i)))!=0, TAG_DONE);
                                    }
                                else if (i<8)
                                    {
                                    ProtChng = ProtChng ^ ( 1 << (7 - i) );
                                    GT_SetGadgetAttrs(AreqGadgets[4+i], AreqWnd, 0, GTCB_Checked, ((Protect ^ ProtChng) & (1<<(7-i)))==0, TAG_DONE);
                                    }
                                else if (i==8)
                                    {
                                    Exit=1;
                                    }
                                else if (i==9)
                                    {
                                    Exit=2;
                                    }
                                else if (i==10)
                                    {
                                    FileAktion( FileName, 6 );
                                    }
                                else if (i==11)
                                    {
                                    FileAktion( FileName, Typ );
                                    };
                            };
                        };
                    };
                if (Exit==2)
                    {
                    if (ProtChng)
                        {
                        SetProtection( FileName, Protect^ProtChng );
                        };
                    };
                GT_SetGadgetAttrs(AreqGadgets[0], AreqWnd, 0, GTLV_Labels, 0, TAG_DONE);
                };
            FreeMem( Buffer, 256 );
            };
        FreeMem( FIB, sizeof(struct FileInfoBlock) );
        }
    return(Exit);
    }

/* AnalyzeBuffer: Analysiert die zum Filehandle gehörende Datei, fügt die
                  ermittelten Informationen in die Nodelist für Listview
                  ein und gibt den generellen Typ zurück.
    FH            FileHandle der zu untersuchenden Datei
    Buffer        Zeiger auf einen 256 Bytes großen Pufferbereich
    Rückgabewert: Art der Datei; 0=unbekannt, 1=IFF-ILBM, 2=IFF-SMUS,
                  6=ASCII, 100=unbek. IFF */


LONG AnalyzeBuffer( struct FileHandle *FH, char *Buffer )
    {
    char String[40];
    short i,j;
    ULONG *Cmp;
    LONG Typ;
    LONG BytesRead;
    struct IFF_Hunk
           { char iff_HunkName[4];
             ULONG   iff_HunkLen;
           } *HUNK;

    struct IFF_BMHD
           { short   BMHD_Width;
             short   BMHD_Height;
             short   BMHD_XPos;
             short   BMHD_YPos;
             char    BMHD_Depth;
             char    BMHD_Mask;
             char    BMHD_Compress;
             char    BMHD_1;
             short   BMHD_2;
             char    BMHD_3;
             char    BMHD_4;
             short   BMHD_SWidth;
             short   BMHD_SHeight;
           } *BMHD;

    struct IFF_CAMG
           { long    CAMG_Modes;
           } *CAMG;

    BytesRead=Read( (BPTR)FH, Buffer, 256 );

    if( BytesRead==0 )
        {
        AddListEntry( LS[MSG_4_T_EmptyFile] );
        Typ = 0;
        }
    else if( BytesRead>=12 )
        {
        Cmp = (ULONG *)Buffer;

        if (strncmp( Buffer, "FORM", 4 )==0)
            {
            strcpy( &String[0], LS[MSG_4_T_IFFFile] );
            strncpy( &String[18], &Buffer[8], 4 );
            if ( strncmp( &Buffer[8], "ILBM", 4 )==0 )
                {
                Typ = 1;
                }
            else if ( strncmp( &Buffer[8], "SMUS", 4 )==0 )
                {
                Typ = 2;
                }
            else if ( strncmp( &Buffer[8], "ANIM", 4 )==0 )
                {
                Typ = 5;
                }
            else
                Typ = 100;
            AddListEntry( String );
            AddListEntry( "" );
            AddListEntry( LS[MSG_4_T_HunkList] );
            HUNK = (struct IFF_Hunk *) Buffer;
            Seek( (BPTR)FH, 12, OFFSET_BEGINNING );
            while ( BytesRead=Read( (BPTR)FH, Buffer, 8 ) )
                {
                sprintf( String, LS[MSG_4_T_HunkLen], HUNK->iff_HunkLen );
                strncpy( &String[0], &(HUNK->iff_HunkName[0]), 4 );
                AddListEntry( String );
                if (strncmp( &(HUNK->iff_HunkName[0]), "BMHD", 4 )==0)
                    {
                    Read( (BPTR)FH, Buffer, HUNK->iff_HunkLen );
                    BMHD = (struct IFF_BMHD *)Buffer;
                    sprintf( String, LS[MSG_4_T_Resolution], BMHD->BMHD_Width, BMHD->BMHD_Height );
                    AddListEntry( String );
                    sprintf( String, LS[MSG_4_T_ScreenRes], BMHD->BMHD_SWidth, BMHD->BMHD_SHeight );
                    AddListEntry( String );
                    sprintf( String, LS[MSG_4_T_Colors], BMHD->BMHD_Depth, 1<<(BMHD->BMHD_Depth) );
                    AddListEntry( String );
                    if( BMHD->BMHD_Compress==0 )
                        AddListEntry( LS[MSG_4_T_Compress] );
                    }
                else if (strncmp( &(HUNK->iff_HunkName[0]), "CAMG" , 4)==0)
                    {
                    Read( (BPTR)FH, Buffer, HUNK->iff_HunkLen );
                    CAMG = (struct IFF_CAMG *)Buffer;
                    sprintf( String, LS[MSG_4_T_VPModes], CAMG->CAMG_Modes );
                    AddListEntry( String );
                    }
                else Seek( (BPTR)FH, ((HUNK->iff_HunkLen+1)>>1)<<1, OFFSET_CURRENT );
                };
            }
        else if( *Cmp==0xe3100001 )
            {
            AddListEntry( LS[MSG_4_T_Icon] );
            }
        else if( *Cmp==0xf34c0012 )
            {
            AddListEntry( LS[MSG_4_T_Info] );
            }
        else if( *Cmp==0x000003f3 )
            {
            AddListEntry( LS[MSG_4_T_LoadSeg1] );
            AddListEntry( LS[MSG_4_T_LoadSeg2] );
            }
        else if( *Cmp==0x00034746 )
            {
            AddListEntry( LS[MSG_4_T_GFABugsick] );
            }
        else if( *Cmp==0x07231992 )
            {
            AddListEntry( LS[MSG_4_T_PPM2] );
            }
        else if( *Cmp==0x07231988 )
            {
            AddListEntry( LS[MSG_4_T_PPM1] );
            }
        else if( strncmp(Buffer+2, "-lh0-", 5)==0 )
            {
            AddListEntry( LS[MSG_4_T_LHA0] );
            Typ = 10;
            }
        else if( strncmp(Buffer+2, "-lh5-", 5)==0 )
            {
            AddListEntry( LS[MSG_4_T_LHA5] );
            Typ = 10;
            }
        else if( strncmp(Buffer+2, "-lh", 3)==0 && Buffer[6]=='-' )
            {
            AddListEntry( LS[MSG_4_T_LHA1] );
            Typ = 10;
            }
        else
            {
            j = 0;
            for (i=0; i<BytesRead; i++)
                if ( (Buffer[i]>31 & Buffer[i]<127) || Buffer[i]=='\n' || Buffer[i]=='\t' ) j++;
            if ( j*10 > i*8 )
                {
                AddListEntry( LS[MSG_4_T_Text] );
                Typ = 3;
                }
            else
                {
                AddListEntry( LS[MSG_4_T_Unknown] );
                Typ = 0;
                };
            };
        };
    return (Typ);
    };


AddListEntry( char *Name )
    {
    if ( (Ana_NumEntry<80) && (strlen(Name)+Ana_StrEntry<998) )
        {
        strcpy( &Ana_Strings[Ana_StrEntry], Name );
        Ana_Nodes[Ana_NumEntry].ln_Name = &Ana_Strings[Ana_StrEntry];
        AddTail( &Ana_List, &Ana_Nodes[Ana_NumEntry] );
        Ana_StrEntry = Ana_StrEntry+strlen(Name)+2;
        Ana_NumEntry++;
        };
    };


long OpenAnalyseReq( void )
{
    struct NewGadget     ng;
    struct Gadget       *g;
    short  x1, y1, yg, yh;
    struct TextFont     *TestFont;

    yg = LY_GFontH + 5;
    y1 = Scr->BarHeight+2;
    x1 = Wnd->RPort->TxWidth;
    yh = ((12*yg+8)/LY_GFontH)*LY_GFontH+4;

    if ( TestFont=(struct TextFont *)OpenDiskFont( &GadgetFont ) )
        {
        x1 = TestFont->tf_XSize;
        CloseFont( TestFont );
        };

    AreqWindowTags[ 9 ].ti_Data = Scr;
    AreqWindowTags[ 0 ].ti_Data = (Scr->Width-50*x1)/2;
    AreqWindowTags[ 1 ].ti_Data = (Scr->Height-yh-y1-yg-6)/2;
    AreqWindowTags[ 2 ].ti_Data = 50*x1;
    AreqWindowTags[ 3 ].ti_Data = yh+y1+yg+6;
    AreqWindowTags[ 7 ].ti_Data = LS[MSG_4_T_AreqTitle];
    AreqWindowTags[ 8 ].ti_Data = LS[MSG_4_T_AreqTitle];

    if ( NOT( g = CreateContext( &AreqGList )))
        return( 3l );

    ng.ng_LeftEdge        =    10;
    ng.ng_TopEdge         =    y1+yg+2;
    ng.ng_Width           =    35*x1-10;
    ng.ng_Height          =    yh;
    ng.ng_GadgetText      =    0l;
    ng.ng_TextAttr        =    &GadgetFont;
    ng.ng_GadgetID        =    AGD_Liste;
    ng.ng_Flags           =    0;
    ng.ng_VisualInfo      =    VisualInfo;

    g = CreateGadget( LISTVIEW_KIND, g, &ng, GTLV_Labels, 0, GTLV_ReadOnly, TRUE, TAG_DONE );

    AreqGadgets[ 0 ] = g;

    ng.ng_LeftEdge        =    35*x1+4;
    ng.ng_TopEdge         =    y1+yh-3*yg-4;
    ng.ng_Width           =    15*x1-14;
    ng.ng_Height          =    yg;
    ng.ng_GadgetText      =    LS[MSG_4_T_Editor];
    ng.ng_GadgetID        =    AGD_Mon;
    ng.ng_Flags           =    PLACETEXT_IN;

    g = CreateGadget( BUTTON_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 1 ] = g;

    ng.ng_TopEdge         =    y1+yh-yg;
    ng.ng_GadgetText      =    LS[MSG_4_T_Cont];
    ng.ng_GadgetID        =    AGD_Weiter;

    g = CreateGadget( BUTTON_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 2 ] = g;

    ng.ng_TopEdge         =    y1+yh-2*yg-2;
    ng.ng_GadgetText      =    LS[MSG_4_T_Action];
    ng.ng_GadgetID        =    AGD_Aktion;

    g = CreateGadget( BUTTON_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 3 ] = g;

    ng.ng_TopEdge         =    y1+yg+2;
    ng.ng_GadgetText      =    "_Hide";
    ng.ng_GadgetID        =    AGD_Hide;
    ng.ng_Flags           =    PLACETEXT_RIGHT;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 4 ] = g;

    ng.ng_TopEdge         =    y1+2*yg+1;
    ng.ng_GadgetText      =    "_Script";
    ng.ng_GadgetID        =    AGD_Script;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 5 ] = g;

    ng.ng_TopEdge         =    y1+3*yg;
    ng.ng_GadgetText      =    "_Pure";
    ng.ng_GadgetID        =    AGD_Pure;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 6 ] = g;

    ng.ng_TopEdge         =    y1+4*yg-1;
    ng.ng_GadgetText      =    "_Archive";
    ng.ng_GadgetID        =    AGD_Archive;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 7 ] = g;

    ng.ng_TopEdge         =    y1+5*yg-2;
    ng.ng_GadgetText      =    "_Read";
    ng.ng_GadgetID        =    AGD_Read;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 8 ] = g;

    ng.ng_TopEdge         =    y1+6*yg-3;
    ng.ng_GadgetText      =    "_Write";
    ng.ng_GadgetID        =    AGD_Write;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 9 ] = g;

    ng.ng_TopEdge         =    y1+7*yg-4;
    ng.ng_GadgetText      =    "_Execute";
    ng.ng_GadgetID        =    AGD_Execute;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 10 ] = g;

    ng.ng_TopEdge         =    y1+8*yg-5;
    ng.ng_GadgetText      =    "_Delete";
    ng.ng_GadgetID        =    AGD_Delete;

    g = CreateGadget( CHECKBOX_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 11 ] = g;

    ng.ng_TopEdge         =    y1+yh+2;
    ng.ng_Width           =    15*x1-14;
    ng.ng_Height          =    yg;
    ng.ng_GadgetText      =    LS[MSG_4_T_Cancel];
    ng.ng_GadgetID        =    AGD_Abbruch;
    ng.ng_Flags           =    PLACETEXT_IN;

    g = CreateGadget( BUTTON_KIND, g, &ng, GT_Underscore, '_', TAG_DONE );

    AreqGadgets[ 12 ] = g;

    if ( NOT g )
        return( 4l );

    AreqWindowTags[ 6 ].ti_Data = AreqGList;

    if ( NOT( AreqWnd = OpenWindowTagList( 0l, AreqWindowTags )))
        return( 5l );

    if (LFont) SetFont( AreqWnd->RPort, LFont );

    GT_RefreshWindow( AreqWnd, 0l );

    DrawBevelBox( AreqWnd->RPort, 10, y1+1, 50*x1-18, yg-1, GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE );

    return( 0l );
}

CloseAnalyseReq( void )
{
    struct IntuiMessage *MyMsg;

    Forbid();
    while (MyMsg = GetMsg(AreqWnd->UserPort))
       {
       ReplyMsg(MyMsg);
       };

    ModifyIDCMP(AreqWnd,NULL);
    
    Permit();

    if ( AreqWnd        )
        RemoveGList( AreqWnd, AreqGList, -1 );
        CloseWindow( AreqWnd );

    if ( AreqGList      )
        FreeGadgets( AreqGList );
}
