#include "global.h"

struct Library *WhatIsBase;
struct Library *IntuitionBase;
struct Library *WorkbenchBase;
struct Library *IconBase;
struct Library *AslBase;

#define CONFIG_TEMPLATE (APTR)"TYPE/K/A,ACTION/K/A"
#define CT_TYPE         0
#define CT_ACTION       1
#define CT_LENGTH       2
LONG ConfigLine[CT_LENGTH];

#define COMMAND_TEMPLATE (APTR)"FILE,ICON/S,MENU/S,ICONNAME/K,MENUNAME/K"
#define CO_FILE         0
#define CO_ICON         1
#define CO_MENU         2
#define CO_ICONNAME     3
#define CO_MENUNAME     4
#define CO_LENGTH       5
LONG CommandLine[CO_LENGTH];

#define BUFSIZE 512                                                                 
#define ACTIONFILE "s:FileActions"
#define PNAME "MegaView"
#define ABOUT "MegaView V1.0\nŠ 1993 DIgital DImensions\nVersion 1.0"

char win[256];

char pbuf[512];
BOOL wbrun=FALSE;
BOOL IconMode=FALSE, MenuMode=FALSE;
char IconName[50];
char MenuName[50];

LONG ix=0,iy=0;

#define ICONID 4711L

char FileName[256];

struct TagItem witags[] = {
    WI_Deep, DEEPTYPE,
    WI_FIB, 0,
    TAG_DONE, 0L
};

struct TagItem atags[] = {
    ASL_Hail,   0L,
    TAG_DONE,   0L
};


UWORD MegaViewI1Data[] =
{
/* Plane 0 */
    0x0000,0x0000,0x0000,0x3F80,0x0000,0x0000,0x0000,0x60E0,
    0x0000,0x0000,0x0001,0xF830,0x0000,0x0000,0x001F,0xFF98,
    0x0000,0x0000,0x0020,0x0058,0x0000,0x0000,0x0027,0x9E58,
    0x0AAA,0xAAFE,0xAAA7,0x9E58,0x2822,0xAAEE,0xAAA7,0x9E70,
    0x22A8,0x0000,0x02A0,0x0060,0x2AA8,0x0000,0x03A0,0x0040,
    0x2AA8,0x00E0,0x03A0,0x0040,0x2AA8,0x07F8,0x03A0,0x0040,
    0x2AA8,0x3FF0,0x03A0,0x0040,0x2AA8,0x7FEF,0x03A0,0x0040,
    0x2AA8,0xFFFF,0x03A2,0xAA40,0x2AA8,0x73FE,0x03AA,0xAAC0,
    0x2AA8,0x01DF,0xC3AA,0xAAC0,0x2AA8,0x000F,0xE3AA,0xAC00,
    0x2AA8,0x0000,0x63AA,0xAC00,0x2AA8,0x0000,0x03AA,0xAC00,
    0x2AA8,0x0000,0x03AA,0xAC00,0x2AA7,0xFFFF,0xFFCA,0xAC00,
    0x0AAA,0xBEAA,0xBEAA,0x8C00,0x0000,0x0000,0x0000,0x0C00,
    0x0000,0x0000,0x0000,0x0C00,0x7FFF,0xFFFF,0xFFFF,0xFC00,
    0x0000,0x0000,0x0000,0x0000,
/* Plane 1 */
    0x0000,0x0000,0x0000,0x4000,0x0000,0x0000,0x0000,0x8100,
    0x0000,0x0000,0x0002,0x0040,0x0000,0x0000,0x0000,0x0020,
    0xFFFF,0xFFFF,0xFFDF,0xFFA0,0xD555,0x5555,0x5558,0x61A0,
    0xD000,0x0100,0x0018,0x61A0,0xC7D8,0x0110,0x0018,0x6180,
    0xCC03,0xFFFF,0xFC1F,0xFF80,0xC003,0xFFFF,0xFC1F,0xFF80,
    0xC003,0xFFDF,0xFC1F,0xFF80,0xC003,0xFFE7,0xFC1F,0xFF80,
    0xC003,0xFCCF,0xFC1F,0xFF80,0xC003,0xF19E,0xFC1F,0xFF80,
    0xC003,0xE76C,0xFC1D,0x5580,0xC003,0x8F99,0xFC15,0x5500,
    0xC003,0xFE3F,0xBC15,0x5500,0xC003,0xFFF0,0xDC00,0x1000,
    0xC003,0xFFFF,0x9C00,0x1000,0xC003,0xFFFF,0xFC00,0x1000,
    0xC003,0xFFFF,0xFC00,0x1000,0xC008,0x0000,0x0000,0x1000,
    0xD000,0x4000,0x4000,0x5000,0xD555,0x5555,0x5555,0x5000,
    0xD555,0x5555,0x5555,0x5000,0x8000,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,
};

struct Image MegaViewI1 =
{
    0, 0,                       /* Upper left corner */
    61, 27, 2,                  /* Width, Height, Depth */
    MegaViewI1Data,             /* Image data */
    0x0003, 0x0000,             /* PlanePick, PlaneOnOff */
    NULL                        /* Next image */
};

struct DiskObject MegaView =
{
    WB_DISKMAGIC,               /* Magic Number */
    WB_DISKVERSION,             /* Version */
    {                           /* Embedded Gadget Structure */
        NULL,                   /* Next Gadget Pointer */
        0, 0, 61, 27,           /* Left,Top,Width,Height */
        GADGIMAGE | GADGHCOMP,  /* Flags */
        RELVERIFY,              /* Activation Flags */
        BOOLGADGET,             /* Gadget Type */
        (APTR)&MegaViewI1,      /* Render Image */
        NULL,                   /* Select Image */
        NULL,                   /* Gadget Text */
        NULL,                   /* Mutual Exclude */
        NULL,                   /* Special Info */
        100,                    /* Gadget ID */
        (APTR) 0x0001,          /* User Data (Revision) */
    },
    WBTOOL,                     /* Icon Type */
    NULL,                       /* Default Tool */
    NULL,                       /* Tool Type Array */
    NO_ICON_POSITION,           /* Current X */
    NO_ICON_POSITION,           /* Current Y */
    NULL,                       /* Drawer Structure */
    NULL,                       /* Tool Window */
    4096                                /* Stack Size */
};


BOOL FileRequest(void) {

    struct FileRequester *request;
    BOOL result;

    atags[0].ti_Data=(ULONG)"Select file to view...";
    request=(struct FileRequester *)AllocAslRequest(ASL_FileRequest,atags);

    if (request==NULL)
        return(FALSE);
    result = AslRequest(request,NULL);
    if (result==FALSE) {
        FreeAslRequest(request);
        return FALSE;
    }
    strncpy(FileName,(char *)(request->rf_Dir),256);
    AddPart((STRPTR)FileName,request->rf_File,256);
    return(TRUE);
}

long ShowRequest(char *text, char *gads) {
    struct EasyStruct es;
    es.es_StructSize=sizeof(struct EasyStruct);
    es.es_Flags=0;
    es.es_Title=(UBYTE *)PNAME " Request";
    es.es_TextFormat=(UBYTE *)text;
    es.es_GadgetFormat=(UBYTE *)gads;
    return EasyRequestArgs(NULL,&es,NULL,NULL);
}

void print(char *s) {
    if (wbrun==FALSE) printf("%s\n",s);
    else ShowRequest(s,"OK");
}                       

void CloseAll(char *s) {
    if (s) printf("%s\n",s);
    if (WhatIsBase)     CloseLibrary(WhatIsBase);
    if (IntuitionBase)  CloseLibrary(IntuitionBase);
    if (WorkbenchBase)  CloseLibrary(WorkbenchBase);
    if (IconBase)       CloseLibrary(IconBase);
    if (AslBase)        CloseLibrary(AslBase);
    exit(0L);
}

void OpenAll(void) {
    strcpy(FileName,"\0");
    WhatIsBase      =   OpenLibrary((APTR)"whatis.library",0L);
    if (!WhatIsBase)    CloseAll("Need whatis.library");
    IntuitionBase   =   OpenLibrary((APTR)"intuition.library",37L);
    if (!IntuitionBase) CloseAll("need intuition library V37");
    WorkbenchBase   =   OpenLibrary((APTR)"workbench.library",37L);
    if (!WorkbenchBase) CloseAll("Need workbench library V37");
    IconBase        =   OpenLibrary((APTR)"icon.library",37L);
    if (!IconBase)      CloseAll("Need icon library V37");
    AslBase         =   OpenLibrary((APTR)"asl.library",37L);
    if (!AslBase)       CloseAll("Need asl library V37");
}

BOOL Scan(char *type, APTR buf, ULONG bufsize) {
    BPTR fh=NULL;
    APTR cs;
    int line=0;
    int c=0;
    UBYTE *cur;
    BOOL res=TRUE;
    struct RDArgs *myargs=NULL,*ap;
    fh=Open((APTR) ACTIONFILE,MODE_OLDFILE);
    if (!fh) CloseAll("Missing file " ACTIONFILE);
    cs= AllocVec(BUFSIZE,MEMF_CLEAR|MEMF_PUBLIC);
    if (!cs) {
        Close(fh);
        return FALSE;
    }
    myargs=(struct RDArgs *)AllocDosObject(DOS_RDARGS,TAG_DONE);
    if (!myargs) {
        Close(fh);
        FreeVec(cs);
        return FALSE;
    }
    do {
        line++;
        cur=(UBYTE *)FGets(fh,(STRPTR)cs,BUFSIZE);
        if (!cur) {
            res=FALSE;
            break;
        }
        c=0;
        c=strlen(cur);
        if (*cur==';') continue;
        if (*cur=='\n') continue;
        if (cur[c-1]!='\n') {
            print("Missing NEWLINE at end of " ACTIONFILE );
            res=FALSE;
            break;
        }
        myargs->RDA_Flags |= RDAF_NOPROMPT;
        myargs->RDA_Source.CS_Buffer = cs;
        myargs->RDA_Source.CS_Length = c;
        myargs->RDA_Source.CS_CurChr = 0L;
        ap=ReadArgs(CONFIG_TEMPLATE,ConfigLine,myargs);
        if (!ap) {
            res=FALSE;
            Fault(IoErr(),NULL, cs, BUFSIZE);
            sprintf(pbuf,"Parse error in line %ld: %d", line, (char *)cs);
            print(pbuf);
            break;
        }
        if (stricmp(type,(char *)ConfigLine[CT_TYPE])==0) {
            strncpy((char *)buf,(char *)ConfigLine[CT_ACTION],bufsize);
            res=TRUE;
            if (bufsize<strlen((char *)ConfigLine[CT_ACTION])) res=FALSE;
            break;
        }
    } while (1);
    if (fh) Close(fh);
    if (cs) FreeVec(cs);
    if (myargs) FreeDosObject(DOS_RDARGS,myargs);
    return res;
}

void HandleFile(char *fname) {
    BOOL bl;
    char cln[512];
    BPTR lock;
    APTR Buffer;
    BPTR window;
    FileType ft;
    struct FileInfoBlock *fib;
    Buffer=AllocVec(BUFSIZE,MEMF_CLEAR);
    if (Buffer) {
        lock=Lock((APTR)fname, SHARED_LOCK);
        if (lock) {
            fib=(struct FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
            if (fib) {
                Examine(lock,fib);
                witags[1].ti_Data=(ULONG)fib;
                ft=WhatIs(fname,witags);
                if (CmpFileType(ft,TYPE_UNKNOWNFILETYPE)==0)
                    print("Unknown filetype");
                else {
                    bl=Scan(GetIDString(ft),Buffer,BUFSIZE);
                    if (bl==FALSE) {
                        sprintf(cln,"Error: No ACTION for %s filetype",GetIDString(ft));
                        print(cln);
                    } else {
                        sprintf(cln,(char *)Buffer,fname);
                        window=Open((STRPTR)win,MODE_READWRITE);
                        Execute((STRPTR)cln,NULL,window);
                        Close(window);
                    }
                }
                UnLock(lock);
                FreeDosObject(DOS_FIB,fib);
            } else print("Unable to create FileInfoBlock");
        } else print("Unable to lock file");
        FreeVec(Buffer);
    } else print("Cannot allocate buffer");
}

void SetUpAndHandleIcon(char *IconName) {
    struct DiskObject *dobj;
    struct AppIcon *ai;
    struct MsgPort *port;
    struct AppMessage *msg;
    char fname[512];
    int i;
    BOOL loaded=FALSE;
    BPTR oldlock;
    BOOL running=TRUE;
    BOOL flg=FALSE;
    dobj=GetDiskObject((STRPTR)IconName);
    if (dobj==NULL) dobj=&MegaView;
    else loaded=TRUE;
    if (ix==0) dobj->do_CurrentX=NO_ICON_POSITION; else dobj->do_CurrentX=ix;
    if (iy==0) dobj->do_CurrentY=NO_ICON_POSITION; else dobj->do_CurrentY=iy;
    port=CreatePort(NULL,0L);
    if (port) {
        ai=AddAppIconA(ICONID,0L,(STRPTR)IconName,port,
                NULL,dobj,NULL);
        if (ai) {
            while (running) {
                Wait(1<<port->mp_SigBit);
                while (msg=(struct AppMessage *)GetMsg(port)) {
                    if (msg->am_Type!=MTYPE_APPICON) {
                        ReplyMsg((struct Message *)msg);
                        continue;
                    }
                    if (msg->am_NumArgs==0) {
                        i=ShowRequest(ABOUT,"Quit|Select|Continue");
                        switch(i) {
                        case 0:
                            break;
                        case 1:
                            running=FALSE;
                            break;
                        case 2:
                            flg=FileRequest();
                            if (flg==FALSE) break;
                            HandleFile(FileName);
                            break;
                        }
                    } else {
                        for (i=0; i<msg->am_NumArgs; i++) {
                            strcpy(fname,(char *)(msg->am_ArgList[i].wa_Name));
                            oldlock=CurrentDir(msg->am_ArgList[i].wa_Lock);
                            HandleFile(fname);
                            CurrentDir(oldlock);
                        }
                    }
                    ReplyMsg((struct Message *)msg);
                }
            }
            while (msg=(struct AppMessage *)GetMsg(port)) {
                ReplyMsg((struct Message *)msg);
            }
            RemoveAppIcon(ai);
        } else print("Cannot AddAppIcon()");
        DeletePort(port);
    } else print("Cannot CreatePort()");
    if (loaded==TRUE) {
        FreeDiskObject(dobj);
    }
}


void SetUpAndHandleMenu(char *MenuName) {
    struct AppMenuItem *ai;
    struct MsgPort *port;
    struct AppMessage *msg;
    char fname[512];
    int i;
    BPTR oldlock;
    BOOL running=TRUE;
    BOOL flg=FALSE;
    port=CreatePort(NULL,0L);
    if (port) {
        ai=AddAppMenuItemA(ICONID,0L,(STRPTR)MenuName,port,NULL);
        if (ai) {
            while (running) {
                Wait(1<<port->mp_SigBit);
                while (msg=(struct AppMessage *)GetMsg(port)) {
                    if (msg->am_Type!=MTYPE_APPMENUITEM) {
                        ReplyMsg((struct Message *)msg);
                        continue;
                    }
                    if (msg->am_NumArgs==0) {
                        i=ShowRequest(ABOUT,"Quit|Select|Continue");
                        switch(i) {
                        case 0:
                            break;
                        case 1:
                            running=FALSE;
                            break;
                        case 2:
                            flg=FileRequest();
                            if (flg==FALSE) break;
                            HandleFile(FileName);
                            break;
                        }
                    } else {
                        for (i=0; i<msg->am_NumArgs; i++) {
                            strcpy(fname,(char *)(msg->am_ArgList[i].wa_Name));
                            oldlock=CurrentDir(msg->am_ArgList[i].wa_Lock);
                            HandleFile(fname);
                            CurrentDir(oldlock);
                        }
                    }
                    ReplyMsg((struct Message *)msg);
                }
            }
            while (msg=(struct AppMessage *)GetMsg(port)) {
                ReplyMsg((struct Message *)msg);
            }
            RemoveAppMenuItem(ai);
        } else print("Cannot AddAppMenuItem()");
        DeletePort(port);
    } else print("Cannot CreatePort()");
}

void HandleWBStartup(char **argv) {
    int i;
    BPTR oldlock;
    struct WBStartup *wbs;
    char fname[256];
    UBYTE **ta, *s;
    struct DiskObject *dob;
    struct WBArg *wba;
    wbs=(struct WBStartup *)argv;
    wbrun=TRUE;
    wba=wbs->sm_ArgList;
    strcpy(IconName,PNAME);
    strcpy(MenuName,PNAME);
    if (wbs->sm_NumArgs>1) { /* Display Files */
        for (i=1; i<wbs->sm_NumArgs; i++) {
            strcpy(fname,(char *)(wbs->sm_ArgList[i].wa_Name));
            oldlock=CurrentDir(wbs->sm_ArgList[i].wa_Lock);
            HandleFile(fname);
            CurrentDir(oldlock);
        }
    } else { /* Use ToolsTypes */
        if (wba->wa_Name) {
            dob=GetDiskObject((STRPTR)(wba->wa_Name));
            if (dob) {
                ta = (UBYTE  **)dob->do_ToolTypes;
                if (s=FindToolType(ta,(UBYTE *)"WINDOW"))   strcpy(win,s);
                if (s=FindToolType(ta,(UBYTE *)"ICONNAME")) strcpy(IconName,s);
                if (s=FindToolType(ta,(UBYTE *)"MENUNAME")) strcpy(MenuName,s);
                if (s=FindToolType(ta,(UBYTE *)"MODE")) {
                    if (MatchToolValue(s,(UBYTE *)"Icon")) IconMode=TRUE;
                    if (MatchToolValue(s,(UBYTE *)"Menu")) MenuMode=TRUE;
                }
                if (s=FindToolType(ta,(UBYTE *)"ICON_X")) ix=atoi(s);
                if (s=FindToolType(ta,(UBYTE *)"ICON_Y")) iy=atoi(s);
                FreeDiskObject(dob);
                if (IconMode && MenuMode) {
                    print("Error: Mutual Excluding ToolTypes MENU and ICON set");
                } else {
                    if (IconMode==TRUE) SetUpAndHandleIcon(IconName);
                    if (MenuMode==TRUE) SetUpAndHandleMenu(MenuName);
                    if (MenuMode==FALSE && IconMode==FALSE) {
                        print("MegaView V1.0\nŠ 1993 by DIgital DImensions\n"
                              "Usage from Workbench:\nDouble Click icon together with\n"
                              "shift-selected Icons to show them, or use as Default Tool\n"
                              "in Project Icons.\nToolTypes:\n"
                              "MODE=Icon|Menu              Display Icon or Menu (watch case!)\n"
                              "ICONNAME=<string>           Name of icon to use\n"
                              "MENUNAME=<string>           Text for MenuItem\n"
                              "WINDOW=<window string>      stdout window description");
                    }
                }
            } else print("Error opening Icon");
        } else print("What's that??");
    }
}

void main(int argc, char **argv) {
    struct RDArgs *rda;
    char fname[256];
    OpenAll();
    if (argc==0) {
        HandleWBStartup(argv);
        CloseAll(NULL);
    }
    rda=ReadArgs(COMMAND_TEMPLATE,CommandLine,NULL);
    if (rda==NULL) {
        PrintFault(IoErr(),NULL);
        CloseAll(NULL);
    }
    FreeArgs(rda);
    if (CommandLine[CO_FILE]) {
        strcpy(fname,(char *)CommandLine[CO_FILE]);
    } else {
        strcpy(fname,"");
    }
    if (CommandLine[CO_ICON]) {
        if (CommandLine[CO_ICONNAME]) strncpy(IconName,(char *)CommandLine[CO_ICONNAME],50);
        else strcpy(IconName,"MegaView");
        SetUpAndHandleIcon(IconName);
        CloseAll(NULL);
    }
    if (CommandLine[CO_MENU]) {
        if (CommandLine[CO_MENUNAME]) strncpy(MenuName,(char *)CommandLine[CO_MENUNAME],50);
        else strcpy(MenuName,"MegaView");
        SetUpAndHandleMenu(MenuName);
        CloseAll(NULL);
    }
    if (fname[0]=='\0') {
        if (CommandLine[CO_ICON]==0 || CommandLine[CO_MENU]==0) {
            print("Need a filename");
        }
    } else HandleFile(fname);
    CloseAll(NULL);      
}



