#include <stdlib.h>
#include <stdio.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/alib_protos.h>
#include <exec/nodes.h>
#include <exec/lists.h>

#include "vbrowse.h"

struct Library *GadToolsBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *Screen;

struct List list;

struct MsgPort *myport;

#define BREITE 600
#define HOEHE  100
#define LINKS  10
#define OBEN   10

struct NewWindow nw={LINKS,OBEN,BREITE,HOEHE,     /* left,top,width,height    */
                     0,1,               /* pens                     */
                     IDCMP_NEWSIZE|IDCMP_REFRESHWINDOW|LISTVIEWIDCMP|
                     GADGETUP|GADGETDOWN|CLOSEWINDOW,   /*  IDCMP   */
                     /* flags   */
                     WFLG_SIZEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|
                     WFLG_CLOSEGADGET|WFLG_SIMPLE_REFRESH|WFLG_ACTIVATE,
                     0,0,               /* FirstGadget,CheckMark    */
                     (UBYTE*)"vbrowse", /* title                    */
                     0,0,               /* screen,SuperBitmap       */
                     70,70,32767,32767,     /* MinWidth, etc.           */
                     WBENCHSCREEN       /* type                     */
};

struct NewGadget listview={70,30,300,320,      /* left,top,width,height    */
                     0,
                     0,                 /* font                     */
                     2,                 /* GadgetID                 */
                     0,0,0              /* flags,VInfo,UserData     */
};

struct EasyStruct easy={sizeof(struct EasyStruct),0,"vbrowse",0,"OK"};


struct Window *Window;
struct Gadget *Gadget,*GadgetList;
struct VisualInfo *VisualInfo;

struct TextAttr ta;

struct IntuiMessage *IMsg;
struct Message *msg;

int fhoehe,scrollwidth,count;

char *call_editor="ged line %d %s",*call_error="showerr %d";

void closethings(void)
{
    if(myport) DeletePort(myport);
    if(Screen) UnlockPubScreen(0,Screen);
    if(Window) CloseWindow(Window);
    if(GadgetList) FreeGadgets(GadgetList);
    if(VisualInfo) FreeVisualInfo(VisualInfo);
    if(GadToolsBase) CloseLibrary(GadToolsBase);
    if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
    if(GfxBase) CloseLibrary((struct Library *)GfxBase);
    exit(0);
}

void error(char *text)
{
    easy.es_TextFormat=text;
    EasyRequest(0,&easy,0);
}
void openthings(void)
{
    struct TextFont *defaultf;

    if(!(IntuitionBase=(struct IntuitionBase *)OpenLibrary((UBYTE*)"intuition.library",36)))
        closethings();
    if(!(GadToolsBase=OpenLibrary((UBYTE*)"gadtools.library",39)))
        closethings();
    if(!(GfxBase=(struct GfxBase *)OpenLibrary((UBYTE*)"graphics.library",0)))
        closethings();
    Forbid();
    if(FindPort(PORTNAME)){Permit();error("vbrowse already running");exit(EXIT_SUCCESS);}
    Permit();
    if(!(myport=CreatePort(PORTNAME,0)))
        {error("Could get no port");closethings();}
    defaultf=GfxBase->DefaultFont;
    ta.ta_Name=defaultf->tf_Message.mn_Node.ln_Name;
    ta.ta_YSize=defaultf->tf_YSize;
    ta.ta_Style=defaultf->tf_Style;
    ta.ta_Flags=defaultf->tf_Flags;
    if(!(Screen=LockPubScreen(0)))  /*  Workbench   */
        {error("Could not lock screen");closethings();}
    fhoehe=Screen->Font->ta_YSize;
    scrollwidth=fhoehe>12?fhoehe+4:16;
    listview.ng_LeftEdge=10;
    listview.ng_TopEdge=10+fhoehe;
    listview.ng_Width=nw.Width-36;
    listview.ng_Height=nw.Height-20-fhoehe;
    NewList(&list);

    if(!(VisualInfo=GetVisualInfo(Screen,TAG_END)))
        {error("No visual info");closethings();}
    if(!(Gadget=CreateContext(&GadgetList)))
        {error("No context");closethings();}
    /*  hier werden die Gadgets initialisiert   */
    listview.ng_VisualInfo=VisualInfo;    /*  VisualInfo und Font eintragen   */
    listview.ng_TextAttr=&ta;
    Gadget=CreateGadget(LISTVIEW_KIND,Gadget,&listview,GTLV_Labels,&list,
                        GTLV_ScrollWidth,scrollwidth,GTLV_ShowSelected,0,TAG_END);
    if(!Gadget) {error("No gadget");closethings();}

    nw.FirstGadget=GadgetList;
    if(!(Window=OpenWindow(&nw)))
        {error("No window");closethings();}
    GT_RefreshWindow(Window,0);
}

int main(int argc,char **argv)
{
    long lastn=0,currentn;int i;char *mem;
    ULONG lasts=0,lastm=0,currents=0,currentm=0;
    for(i=1;i<argc;i++){
        if(!strcmp(argv[i],"editor")&&i<argc) call_editor=argv[++i];
        if(!strcmp(argv[i],"error")&&i<argc) call_error=argv[++i];
        if(!strcmp(argv[i],"width")&&i<argc) nw.Width=atoi(argv[++i]);
        if(!strcmp(argv[i],"height")&&i<argc) nw.Height=atoi(argv[++i]);
        if(!strcmp(argv[i],"left")&&i<argc) nw.LeftEdge=atoi(argv[++i]);
        if(!strcmp(argv[i],"top")&&i<argc) nw.TopEdge=atoi(argv[++i]);
    }
    openthings();
    while(1){
        Wait((1<<Window->UserPort->mp_SigBit)|(1<<myport->mp_SigBit));

        while(IMsg=GT_GetIMsg(Window->UserPort)){
            switch(IMsg->Class){
            case IDCMP_CLOSEWINDOW:
                GT_ReplyIMsg(IMsg);
                closethings();

            case IDCMP_REFRESHWINDOW:

                GT_BeginRefresh(Window);
                GT_EndRefresh(Window,TRUE);
                break;

            case IDCMP_GADGETUP:
                CurrentTime(&currents,&currentm);
                GT_GetGadgetAttrs(Gadget,Window,0,GTLV_Selected,&currentn,TAG_END);
                if(currentn==lastn&&DoubleClick(lasts,lastm,currents,currentm)){
                    struct Node *p;int errorn,line;char file[256];
                    *file='\"';
                    p=list.lh_Head;
                    lastn=currentn;
                    while(lastn){p=p->ln_Succ;lastn--;}
                    if(sscanf(p->ln_Name,"error %d",&errorn,)==1||
                       sscanf(p->ln_Name,"warning %d",&errorn)==1){

/*                        printf("vbr:errorn=%d\n",errorn);*/
                        mem=malloc(strlen(call_error)+100);
                        sprintf(mem,call_error,errorn);
                        system(mem);
                        free(mem);
                    }else{
                        if(*p->ln_Name=='>'&&p->ln_Succ){
                            p=p->ln_Succ;
                            if(sscanf(p->ln_Name,"error %d in line %d of \" %[^\"]",&errorn,&line,file+1)==3||
                               sscanf(p->ln_Name,"warning %d in line %d of \" %[^\"]",&errorn,&line,file+1)==3){

                                strcat(file,"\"");
/*                                printf("vbr:file=%s, line=%d\n",file,line);*/
                                mem=malloc(strlen(call_error)+strlen(file)+100);
                                sprintf(mem,call_editor,line,file);
                                system(mem);
                                free(mem);
                            }
                        }else error("You have to click on an error/warning message");
                    }
                }
                lastn=currentn;lasts=currents;lastm=currentm;
                break;

            case IDCMP_GADGETDOWN:
/*                printf("GadgetDown (%d)\n",((struct Gadget *)IMsg->IAddress)->GadgetID);*/
                break;

            case IDCMP_NEWSIZE:
                {
                int top,selected;
                GT_GetGadgetAttrs(Gadget,Window,0,GTLV_Top,&top,GTLV_Selected,&selected,TAG_END);
                RemoveGList(Window,GadgetList,-1);
                if(GadgetList) FreeGadgets(GadgetList);
                if(VisualInfo) FreeVisualInfo(VisualInfo);
                GadgetList=0;
                VisualInfo=0;
                listview.ng_LeftEdge=10;
                listview.ng_TopEdge=10+fhoehe;
                listview.ng_Width=Window->Width-36;
                listview.ng_Height=Window->Height-20-fhoehe;
                if(!(VisualInfo=GetVisualInfo(Screen,TAG_END)))
                    closethings();
                if(!(Gadget=CreateContext(&GadgetList)))
                    closethings();
                /*  hier werden die Gadgets initialisiert   */
                listview.ng_VisualInfo=VisualInfo;    /*  VisualInfo und Font eintragen   */
                listview.ng_TextAttr=&ta;
                Gadget=CreateGadget(LISTVIEW_KIND,Gadget,&listview,GTLV_Labels,&list,
                                    GTLV_ScrollWidth,scrollwidth,GTLV_ShowSelected,0,
                                    GTLV_Selected,selected,GTLV_Top,top,TAG_END);
                    if(!Gadget) closethings();
                AddGList(Window,GadgetList,100,-1,0);
                SetRast(Window->RPort,0);
                RefreshGList(GadgetList,Window,0,-1);

                GT_RefreshWindow(Window,0);

                RefreshWindowFrame(Window);

/*                puts("NEWSIZE");*/
                }
                break;
            }
            GT_ReplyIMsg(IMsg);
        }
        while(msg=GetMsg(myport)){
            struct Node *p;int l;char *text;
            text=((struct mymsg *)msg)->text;count++;
/*            printf("Message received: %s\n",text);*/
            l=strlen(text);
            p=malloc(sizeof(struct Node));
            if(!p) closethings();
            p->ln_Name=malloc(l+1);
            if(!p->ln_Name) closethings();
            strcpy(p->ln_Name,text);
            p->ln_Type=0;
            p->ln_Pri=0;
/*                printf("adding %s\n",p->ln_Name);*/
            GT_SetGadgetAttrs(Gadget,Window,0,GTLV_Labels,~0,TAG_END);
            AddTail(&list,p);
            GT_SetGadgetAttrs(Gadget,Window,0,GTLV_Labels,&list,GTLV_Top,count,TAG_END);
            ReplyMsg(msg);
        }

    }
}
