/************************************************************************

vJet V1.0 © 1992 Jan Pfeil · fileviewer for AMIGA
Last changes:   15.04.92

vJet main part

************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <exec/memory.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
#include <libraries/dos.h>
#include <libraries/gadtools.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/utility.h>

#include "extern.h"

/*global*/
struct Library *IconBase = NULL;
struct Library *UtilityBase;
struct GadToolsBase *GadToolsBase = NULL;
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct vJet *vjet = NULL;

UBYTE scrTitle[] = "vJet V1.0 © 1992 Jan Pfeil · file viewing utility · release date " __DATE__ "," __TIME__;
UBYTE defWinTitle[] = "get ready ...";

#define V(x) ((void *)x)

struct NewMenu mynewmenu[] = {
    { NM_TITLE, "Project",       0  , 0, 0, 0,},
    {  NM_ITEM, "Open...",      "O" , 0, 0, 0,},
    {  NM_ITEM, NM_BARLABEL,    0   , 0, 0, 0,},
    {  NM_ITEM, "About...",     0   , 0, 0, 0,},
    {  NM_ITEM, NM_BARLABEL,    0   , 0, 0, 0,},
    {  NM_ITEM, "Quit",         "Q" , 0, 0, 0,},

    { NM_TITLE, "Search",        0   , 0, 0, 0,},
    {  NM_ITEM, "Find...",      "F" , 0, 0, V(0),},
    {  NM_ITEM, " Find Next",    "N" ,0, 0, V(1),},
    {  NM_ITEM, " Find Previous","P" ,0, 0, V(2),},

    { NM_TITLE, "Tools",        0   , 0, 0, 0,},
    {  NM_ITEM, "Goto line...","G"  , 0, 0, V(0),},
    {  NM_ITEM, "CSI interpreter",0 , CHECKED|CHECKIT|MENUTOGGLE, 0, V(1),},
 //   {  NM_ITEM, "show CSI",     0   , CHECKIT|MENUTOGGLE|NM_ITEMDISABLED, 0, V(2),},

    { NM_TITLE, "Buffers",      0   , 0, 0, 0,},
    {  NM_ITEM, "file 1",      "1"  , 0, 0, V(0),},
    {  NM_ITEM, "file 2",      "2"  , 0, 0, V(1),},
    {  NM_ITEM, "file 3",      "3"  , 0, 0, V(2),},
    {  NM_ITEM, "file 4",      "4"  , 0, 0, V(3),},
    {  NM_ITEM, "file 5",      "5"  , 0, 0, V(4),},

    {NM_END, NULL,           0   , 0, 0, 0,}
};

void cleanExit(int returnValue )
{
if(vjet) {
    unLoadFile(vjet);
    if(vjet->win->FirstGadget) RemoveGList(vjet->win,vjet->vProp,(UWORD)-1);
    if(vjet->rightArr) FreeMem(vjet->rightArr,sizeof(struct Gadget));
    if(vjet->leftArr) FreeMem(vjet->leftArr,sizeof(struct Gadget));
    if(vjet->downArr) FreeMem(vjet->downArr,sizeof(struct Gadget));
    if(vjet->upArr) FreeMem(vjet->upArr,sizeof(struct Gadget));
    if(vjet->rightImage) DisposeObject(vjet->rightImage);
    if(vjet->leftImage) DisposeObject(vjet->leftImage);
    if(vjet->downImage) DisposeObject(vjet->downImage);
    if(vjet->upImage) DisposeObject(vjet->upImage);
    if(vjet->hProp) DisposeObject(vjet->hProp);
    if(vjet->vProp) DisposeObject(vjet->vProp);
    if(vjet->menu) ClearMenuStrip(vjet->win);
    if(vjet->win) CloseWindow(vjet->win);
    if(vjet->menu) FreeMenus(vjet->menu);
    if(vjet->dI) FreeScreenDrawInfo(vjet->scr,vjet->dI);
    if(vjet->vI) FreeVisualInfo(vjet->vI);
    if(vjet->scr && vjet->customScreen) CloseScreen(vjet->scr);
    FreeMem(vjet,sizeof(struct vJet));
    }
if(IconBase) CloseLibrary(IconBase);
if(UtilityBase) CloseLibrary((struct Library *)UtilityBase);
if(GadToolsBase) CloseLibrary((struct Library *)GadToolsBase);
if(GfxBase ) CloseLibrary( (struct Library *)GfxBase );
if(IntuitionBase ) CloseLibrary( (struct Library *)IntuitionBase );
exit(returnValue);
}

BOOL handleMenu(struct vJet *vjet,UWORD code)
{
BOOL flag = FALSE;
ULONG menuNum,itemNum;
struct MenuItem *item;
ULONG IDCMPFlags = vjet->win->IDCMPFlags;

ModifyIDCMP(vjet->win,NULL);    //disable IDCMP messages

while(code != MENUNULL) {
    item = ItemAddress(vjet->menu, code);
    menuNum = MENUNUM(code);
    itemNum = ITEMNUM(code);
    switch( menuNum ) {
        case 0:
            switch(itemNum) {
                case 0: openFile(vjet,"");
                        break;
                case 2: about(vjet);
                        break;
                case 4: flag = TRUE;
                        break;
                default:break;
                }
            break;
        case 1:
            switch((int)GTMENUITEM_USERDATA(item)) {
                case 0: findReq(vjet,vjet->find);
                        break;
                case 1: findNext(vjet);
                        break;
                case 2: findPrevious(vjet);
                        break;
                default:break;
                }
            break;
        case 2:
            switch((int)GTMENUITEM_USERDATA(item)) {
                case 0: gotoLine(vjet);
                        break;
                case 1: vjet->handleCSI = (item->Flags & CHECKED);
                        setDefaultStyle(vjet);
                        displayWholePage(vjet);
                        break;
//                case 2: //showCSI()
//                        break;
                default:break;
                }
            break;
        case 3:
            switch((int)GTMENUITEM_USERDATA(item)) {
                case 0: vjet->pathNum = 0;
                        openFile(vjet,vjet->path[vjet->pathNum]);
                        break;
                case 1: vjet->pathNum = 1;
                        openFile(vjet,vjet->path[vjet->pathNum]);
                        break;
                case 2: vjet->pathNum = 2;
                        openFile(vjet,vjet->path[vjet->pathNum]);
                        break;
                case 3: vjet->pathNum = 3;
                        openFile(vjet,vjet->path[vjet->pathNum]);
                        break;
                case 4: vjet->pathNum = 4;
                        openFile(vjet,vjet->path[vjet->pathNum]);
                        break;
                default:break;
                }
            break;
        default:
            break;
        }
    code = item->NextSelect;
    }

ModifyIDCMP(vjet->win,IDCMPFlags);      //enable IDCMP port

return(flag);
}


BOOL handleIDCMP(void)
{
BOOL flag = FALSE;
USHORT code, qualif;
struct Window *win;
struct IntuiMessage *msg = NULL;
APTR iadr;
ULONG class;

while(msg = GT_GetIMsg(vjet->win->UserPort) ) {
    class = msg->Class;
    code = msg->Code;
    qualif = msg->Qualifier;
    win = (struct Window *)msg->IDCMPWindow;
    iadr = msg->IAddress;
    GT_ReplyIMsg(msg);

    switch( class ) {

/*
//very slow for scrolling
        case IDCMP_INTUITICKS:
                            if(vjet->upArr->Flags&SELECTED)
                                movePageVert(vjet,-1);
                            else if(vjet->downArr->Flags&SELECTED)
                                movePageVert(vjet,1);
                            else if(vjet->leftArr->Flags&SELECTED)
                                movePageHoriz(vjet,-1);
                            else if(vjet->rightArr->Flags&SELECTED)
                                movePageHoriz(vjet,1);
                            else
                                titleWin(vjet,"unknown INTUITICKS message !");
                            break;

//enable this code by simply removing the /* and */
//don't forget to modify vgads.c too
*/
        case IDCMP_MOUSEMOVE:
                            if(vjet->vProp->Flags&SELECTED)
                                getVSlider(vjet);
                            else if(vjet->hProp->Flags&SELECTED)
                                    getHSlider(vjet);
                            break;
        case IDCMP_VANILLAKEY:
                            flag = handleVanilla(vjet,code,qualif);
                            break;
        case IDCMP_RAWKEY:
                            flag = handleRaw(vjet,code,qualif);
                            break;
        case IDCMP_GADGETDOWN:
                            handleDGad(vjet,(struct Gadget *)iadr);
                            break;
        case IDCMP_GADGETUP:
                            handleUGad(vjet,(struct Gadget *)iadr);
                            break;
        case IDCMP_NEWSIZE: checkWinSize(vjet);
                            displayWholePage(vjet);
                            setVSlider(vjet);
                            setHSlider(vjet);
                            break;
        case MENUPICK:      flag = handleMenu(vjet,code);
                            break;
        case IDCMP_CLOSEWINDOW:
                            flag = TRUE;
                            break;
        default:            titleWin(vjet,"unresolved msg->class");
                            break;
        } /* end switch class */

    if(flag)                        /* return immediatly */
        return(flag);
    }
return(flag);
} /*end handleIDCMP()*/


void OpenGen(void)
{
if(!(IntuitionBase =(struct IntuitionBase *)OpenLibrary("intuition.library",INTUITION_VER)))
    cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
if(!(GfxBase =(struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_VER)))
    cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
if(!(GadToolsBase =(struct GadToolsBase *)OpenLibrary("gadtools.library",GADTOOLS_VER)))
    cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
if(!(UtilityBase = (struct Library *)OpenLibrary("utility.library",UTILITY_VER)))
    cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
if(!(vjet = AllocMem(sizeof(struct vJet),MEMF_PUBLIC|MEMF_CLEAR)))
    cleanExit(ERROR_NO_FREE_STORE);
}

VOID titleWin(struct vJet* vjet,char *string)
{
sprintf(vjet->winTitle,"%4d/%4d %3d% - file %d: %s",
    vjet->topline+1,vjet->maxline,
    100*(vjet->topline+vjet->linesPerPage)/max(1,vjet->maxline),
    vjet->pathNum+1,string);
SetWindowTitles(vjet->win,vjet->winTitle,(UBYTE *)-1);
}


VOID createWindow(struct vJet *vjet,struct TagItem *windowTags)
{
struct TagItem *tag = NULL;
struct Screen scrBuf;

vjet->vI = GetVisualInfo(vjet->scr,TAG_END);
vjet->dI = GetScreenDrawInfo(vjet->scr);

tag = FindTagItem(WA_CustomScreen,windowTags);
tag->ti_Data = (ULONG)vjet->scr;
tag = FindTagItem(WA_Top,windowTags);
tag->ti_Data = vjet->scr->BarHeight+1;

if(vjet->customScreen) {
    tag = FindTagItem(WA_Width,windowTags);
    tag->ti_Data = vjet->scr->Width;
    tag = FindTagItem(WA_Height,windowTags);
    tag->ti_Data = vjet->scr->Height - vjet->scr->BarHeight-1;

    tag = FindTagItem(WA_PubScreen,windowTags);
    tag->ti_Data = TAG_IGNORE;
    }
else {
    GetScreenData(&scrBuf,sizeof(struct Screen),WBENCHSCREEN,NULL);

    tag = FindTagItem(WA_Width,windowTags);
    tag->ti_Data = scrBuf.Width;
    tag = FindTagItem(WA_Height,windowTags);
    tag->ti_Data = scrBuf.Height -(vjet->scr->BarHeight+1);

    tag = FindTagItem(WA_PubScreen,windowTags);
    tag->ti_Data = (ULONG)vjet->scr;
    }

if(!(vjet->win = OpenWindowTagList(NULL,windowTags)))
    cleanExit(ERROR_NO_FREE_STORE);

vjet->stA = vjet->scr->Font;
}

VOID createScreen(struct vJet *vjet,struct TagItem *screenTags)
{
struct Screen *ps = NULL;
ULONG vpMode;
struct TagItem *tag = NULL;
UWORD pens = ~0;

ps = LockPubScreen("Workbench");
vjet->dI = GetScreenDrawInfo(ps);
vpMode = GetVPModeID(&ps->ViewPort);
if(vjet->depth < 1 || vjet->depth > 4)      //user specified strange depth
    vjet->depth = vjet->dI->dri_Depth;      //clone WorkBench depth
UnlockPubScreen(NULL,ps);

tag = FindTagItem(SA_Depth,screenTags);
tag->ti_Data = vjet->depth;
tag = FindTagItem(SA_Pens,screenTags);
tag->ti_Data = (ULONG)&pens;
tag = FindTagItem(SA_DisplayID,screenTags);
tag->ti_Data = vpMode;
if(!(vjet->scr = OpenScreenTagList(NULL,screenTags)))
    cleanExit(ERROR_NO_FREE_STORE);
}

VOID createMenus(struct vJet *vjet)
{
vjet->menu = CreateMenus(mynewmenu,
        GTMN_FullMenu,TRUE,
        TAG_DONE);
LayoutMenus(vjet->menu, vjet->vI,
        GTMN_TextAttr, vjet->stA,
        GTMN_NewLookMenus, TRUE,
        TAG_DONE);
GT_RefreshWindow(vjet->win, NULL);
SetMenuStrip(vjet->win,vjet->menu);
}


/* main loop */
VOID main(int argc, char *argv[])
{
struct WBStartup *WBenchMsg;
struct DiskObject *dobj;
struct WBArg *wbarg;
struct RDArgs *readargs;
char *s, **toolarray;
LONG error = 0, i, olddir = -1;
LONG rargs[3] = {NULL,FALSE,NULL};
ULONG signalmask, signals;
BOOL done = FALSE;

UBYTE template[] = "[1;33mvJet V1.0 © 1991 Jan Pfeil · file viewing utility[0m\n"
                   "FILENAME,SCREEN/S,DEPTH/N";

struct TagItem screenTags[] = {
    SA_Left,0,
    SA_Top,0,
    SA_Width,STDSCREENWIDTH,
    SA_Height,STDSCREENHEIGHT,
    SA_Depth,2,
    SA_DetailPen,DETAILPEN,
    SA_BlockPen,BLOCKPEN,
    SA_Title,(ULONG *)scrTitle,
    SA_Type,CUSTOMSCREEN,
    SA_Behind,TRUE,
    SA_AutoScroll,TRUE,
    SA_DisplayID,NULL,
    SA_Pens,NULL,
    SA_FullPalette,TRUE,
    SA_SysFont,1,
    TAG_END,
    };

struct TagItem windowTags[] = {
    WA_Left,0,
    WA_Top,10,
    WA_Width,320,
    WA_Height,190,
    WA_MinWidth,150,
    WA_MinHeight,60,
    WA_MaxWidth,STDSCREENWIDTH,
    WA_MaxHeight,STDSCREENHEIGHT,
    WA_DetailPen,DETAILPEN,
    WA_BlockPen,BLOCKPEN,
    WA_Flags,WFLG_DRAGBAR+WFLG_CLOSEGADGET+WFLG_DEPTHGADGET+WFLG_SIZEGADGET+
        WFLG_SIZEBRIGHT+WFLG_SIZEBBOTTOM+WFLG_SMART_REFRESH,
    WA_GimmeZeroZero,TRUE,
    WA_IDCMP,IDCMP_CLOSEWINDOW+IDCMP_GADGETDOWN+IDCMP_RAWKEY+IDCMP_VANILLAKEY+
            IDCMP_GADGETUP+IDCMP_NEWSIZE+IDCMP_MENUPICK+IDCMP_MOUSEMOVE,
    WA_Title,(ULONG *)defWinTitle,
    WA_ScreenTitle,(ULONG *)scrTitle,
    WA_CustomScreen,NULL,
    WA_PubScreen,NULL,
    WA_NewLookMenus, TRUE,
    WA_PubScreenFallBack,TRUE,
    WA_AutoAdjust,TRUE,
    TAG_END,
    };

OpenGen();          /*Systemsachen öffnen (Libraries)*/

vjet->pathNum = 0;

//from WorkBench
if(argc == 0) {
    if(!(IconBase = OpenLibrary("icon.library",33)))
         cleanExit(RETURN_FAIL);
    WBenchMsg = (struct WBStartup *)argv;
    wbarg=WBenchMsg->sm_ArgList;
    for(i=0;i<WBenchMsg->sm_NumArgs;i++,wbarg++) {
        olddir = -1;
        if((wbarg->wa_Lock)&&(*wbarg->wa_Name))
            olddir = CurrentDir(wbarg->wa_Lock);    //now we can access file by name
        if((*wbarg->wa_Name) && (dobj=GetDiskObject(wbarg->wa_Name))) {
            toolarray = (char **)dobj->do_ToolTypes;
            if(s=(char *)FindToolType(toolarray,"SCREEN")) {
                if(MatchToolValue(s,"CUSTOMSCREEN")) {
                    vjet->customScreen = TRUE;
                    }
                else if(MatchToolValue(s,"WBENCHSCREEN")) {
                    vjet->customScreen = FALSE;
                    }
                }
            vjet->depth=atoi(FindToolType(toolarray,"DEPTH"));

            /* Free the diskobject we got */
            FreeDiskObject(dobj);
            }
        if((i>0)&&(*wbarg->wa_Name)) {
            NameFromLock(wbarg->wa_Lock,vjet->path[vjet->pathNum],FMSIZE-1);
            AddPart(vjet->path[vjet->pathNum],wbarg->wa_Name,FMSIZE-1);
            }
        if(olddir != -1) CurrentDir(olddir); /* CD back where we were */
        }
    if(IconBase) {
        CloseLibrary(IconBase);
        IconBase = NULL;
        }
    }
//from CLI
else {
    if(readargs = ReadArgs(template, rargs, NULL)) {
        if(rargs[0])            //to avoid illegal read access detected by enforcer
            strcpy(vjet->path[vjet->pathNum],(char *)rargs[0]);
        vjet->customScreen = (BOOL) rargs[1];
        if(rargs[2])            //to avoid illegal read access detected by enforcer
            vjet->depth = (WORD)*((LONG *)(rargs[2]));
        FreeArgs(readargs);
        }
    else
        error = IoErr();

    SetIoErr(error);
    if(error) {
        PrintFault(error, NULL);
        if(error = ERROR_BREAK)
            cleanExit(RETURN_WARN);
        else
            cleanExit(RETURN_FAIL);
        }
    }


vjet->dvF = GfxBase->DefaultFont;
vjet->dtA.ta_Name = vjet->dvF->tf_Message.mn_Node.ln_Name;
vjet->dtA.ta_YSize = vjet->dvF->tf_YSize;

//workbenchgleichen Editor-Screen öffnen (nur wenn SCREEN option)
if(vjet->customScreen) {
    createScreen(vjet,screenTags);
    createWindow(vjet,windowTags);
    }
else {
    vjet->scr = LockPubScreen(NULL);
    createWindow(vjet,windowTags);
    UnlockPubScreen(NULL,vjet->scr);
    }

createWindowGadgets(vjet);
AddGList(vjet->win,vjet->vProp,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(vjet->vProp,vjet->win,NULL,(UWORD)-1);

createMenus(vjet);

ScreenToFront(vjet->scr);
ActivateWindow(vjet->win);

openFile(vjet,vjet->path[vjet->pathNum]);

signalmask = 1L << vjet->win->UserPort->mp_SigBit;

while(!done) {
    signals = Wait(signalmask);
    if (signals & signalmask)
        done = handleIDCMP();
    }
cleanExit(RETURN_OK);
}

/*end of main*/