/*
 * statuswindow.c   V1.4
 *
 * status window
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* Structures for window */
extern char WBScreenName[];
static char wtbc[]=DEFPROGNAME ": HotKey=";
static char *wtb;
extern struct NewWindow nw;
static struct Window *w;
static struct AppWindow *aw;
static struct MsgPort *wp;
static ULONG wl=20,wt=20;    /* Window leftedge & topedge */
static ULONG ww,wh;          /* Window width & height */
static struct Screen *pubsc; /* Workbench screen */

/* Structures for window gadgets */
static void *vi;             /* Visual information is a *PRIVATE* data field! */
static struct Gadget *gl;    /* Gadget list */
static char StatusText[]="Active Tools: 00"; /* Text gadget text */
static struct Gadget *lvgad;                 /* ListView gadget */
WORD lvord=-1;                               /* LV gadget ordinal number */
static WORD lvtop=0;                         /* LV gadget top item number */
static ULONG oldsecs=0,oldmicros=0;          /* LV double click check */
#define LVGAD_ID 1
static char NTButtonText[]="New";            /* New Tool gadget text */
#define NTGAD_ID 2
static char ETButtonText[]="Edit";           /* Edit Tool gadget text */
#define ETGAD_ID 3
static char STButtonText[]="Start";          /* Start Tool gadget text */
#define STGAD_ID 4
static char RTButtonText[]="Remove";         /* Remove Tool gadget text */
#define RTGAD_ID 5
static char SCButtonText[]="Save";           /* Save config gadget text */
#define SCGAD_ID 6
static char ENButtonText[]="Enable";         /* Enable broker gadget text */
#define ENGAD_ID 7
static char DIButtonText[]="Disable";        /* Disable broker gadget text */
#define DIGAD_ID 8
static char QUButtonText[]="Quit";           /* Quit gadget text */
#define QUGAD_ID 9

/* Structures for window menu */
static struct Menu *wmn=NULL;
#define HIMENU_ID  1
static char ABMenuText[]="About";
#define ABMENU_ID  2
#define QUMENU_ID  3
#define ENMENU_ID  4
#define DIMENU_ID  5
#define STMENU_ID  6
#define NTMENU_ID  7
#define ETMENU_ID  8
#define SCMENU_ID  9
#define RTMENU_ID 10
static struct NewMenu mdata[]={
      {NM_TITLE,MyName,NULL,0,~0,NULL},
       {NM_ITEM,"Hide"      ,"H",0,~0,HIMENU_ID},
       {NM_ITEM,ABMenuText  ,NULL,0,~0,ABMENU_ID},
       {NM_ITEM,QUButtonText,"Q",0,~0,QUMENU_ID},
      {NM_TITLE,"HotKeys",NULL,0,~0,NULL},
       {NM_ITEM,ENButtonText,"A",0,~0,ENMENU_ID},
       {NM_ITEM,DIButtonText,"D",0,~0,DIMENU_ID},
      {NM_TITLE,"Tools",NULL,0,~0,NULL},
       {NM_ITEM,STButtonText,"S",0,~0,STMENU_ID},
       {NM_ITEM,NTButtonText,"N",0,~0,NTMENU_ID},
       {NM_ITEM,ETButtonText,"E",0,~0,ETMENU_ID},
       {NM_ITEM,SCButtonText,"C",0,~0,SCMENU_ID},
       {NM_ITEM,RTButtonText,"R",0,~0,RTMENU_ID},
      {NM_END,NULL,NULL,0,~0,NULL}};

/* Data for "About" requester */
static UBYTE AboutText[]="ToolManager V" TM_VERSION " (" TM_DATE ")\n"\
                         "© " TM_CRYEAR "  Stefan Becker\n"\
                         "This program is freely distributable";

static struct EasyStruct AboutES={sizeof(struct EasyStruct),0,ABMenuText,
                                  AboutText,"Ok"};


/* Create status line */
static void PrintStatusLine(void)
{
 StatusText[14]=ToolCount/10+'0'; /* Hack */
 StatusText[15]=ToolCount%10+'0';
}

/* Create all status window gadgets & menus */
static BOOL CreateGadgets(void)
{
 struct NewGadget ng;
 struct Gadget *g;
 struct TextFont *f;              /* Window font */
 struct RastPort tmprp;           /* RastPort for font-sensitive trick */
 UWORD wg,width,fheight;
 UWORD leftedge,topborder;
 UWORD lvright;

 /* Open window font */
 if (!(f=OpenFont(pubsc->Font))) goto cg1;
 fheight=f->tf_YSize; /* Font height */
 leftedge=pubsc->WBorLeft;
 topborder=pubsc->WBorTop+fheight+1;

 /* Initialize temporary RastPort */
 InitRastPort(&tmprp);
 SetFont(&tmprp,f);

 /* Calculate window & gadget width */
 ww=TextLength(&tmprp,wtb,strlen(wtb))+WDRAGBARLEN;
 wg=TextLength(&tmprp,DIButtonText,sizeof(DIButtonText)-1)+INTERWIDTH;
 width=TextLength(&tmprp,RTButtonText,sizeof(RTButtonText)-1)+INTERWIDTH;
 if (width>wg) wg=width;
 if ((width=3*wg+4*INTERWIDTH)>ww) ww=width;

 /* Create gadget list */
 gl=NULL;
 g=CreateContext(&gl);

 /*  1. gadget: Text, status line */
 PrintStatusLine();
 width=TextLength(&tmprp,StatusText,sizeof(StatusText)-1)+INTERWIDTH;
 ng.ng_LeftEdge=leftedge+(ww-width)/2;
 ng.ng_TopEdge=topborder+INTERHEIGHT;
 ng.ng_Width=width;
 ng.ng_Height=fheight;
 ng.ng_GadgetText=StatusText;
 ng.ng_TextAttr=pubsc->Font;
 ng.ng_Flags=PLACETEXT_IN;
 ng.ng_VisualInfo=vi;
 ng.ng_UserData=0;
 if (!(g=CreateGadget(TEXT_KIND,g,&ng,TAG_DONE))) goto cg2;
 g->GadgetText->DrawMode=JAM2; /* Argh, why doesn't exist a tag for this? */

 /*  2. gadget: ListView, tool list */
 ng.ng_LeftEdge=leftedge+INTERWIDTH/2;
 ng.ng_TopEdge+=g->Height+INTERHEIGHT;
 ng.ng_Width=ww-INTERWIDTH;
 ng.ng_Height=7*fheight;
 ng.ng_GadgetText=NULL;
 ng.ng_GadgetID=LVGAD_ID;
 if (!(lvgad=g=CreateGadget(LISTVIEW_KIND,g,&ng,
                            GTLV_Labels,&ToolList,
                            /* If an item was selected, use it as top item */
                            GTLV_Top,lvtop,
                            GTLV_ShowSelected,NULL,
                            GTLV_Selected,lvord,
                            TAG_DONE))) goto cg2;
 lvright=ng.ng_LeftEdge+g->Width;

 /*  3. gadget: Button, new tool */
 ng.ng_TopEdge+=g->Height+fheight+2*INTERHEIGHT;
 ng.ng_Width=wg;
 ng.ng_Height=fheight+INTERHEIGHT;
 ng.ng_GadgetText=NTButtonText;
 ng.ng_GadgetID=NTGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  4. gadget: Button, edit tool definition */
 ng.ng_LeftEdge=leftedge+(ww-wg)/2;
 ng.ng_GadgetText=ETButtonText;
 ng.ng_GadgetID=ETGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  5. gadget: Button, start tool */
 ng.ng_LeftEdge=lvright-wg;
 ng.ng_GadgetText=STButtonText;
 ng.ng_GadgetID=STGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  6. gadget: Button, remove tool */
 ng.ng_LeftEdge=leftedge+INTERWIDTH/2;
 ng.ng_TopEdge+=g->Height+INTERHEIGHT;
 ng.ng_GadgetText=RTButtonText;
 ng.ng_GadgetID=RTGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  7. gadget: Button, save config */
 ng.ng_LeftEdge=lvright-wg;
 ng.ng_GadgetText=SCButtonText;
 ng.ng_GadgetID=SCGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  8. gadget: Button, enable broker */
 ng.ng_LeftEdge=leftedge+INTERWIDTH/2;
 ng.ng_TopEdge+=g->Height+2*INTERHEIGHT;
 ng.ng_GadgetText=ENButtonText;
 ng.ng_GadgetID=ENGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /*  9. gadget: Button, disable broker */
 ng.ng_LeftEdge=leftedge+(ww-wg)/2;
 ng.ng_Width=wg;
 ng.ng_GadgetText=DIButtonText;
 ng.ng_GadgetID=DIGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /* 10. gadget: Button, Quit */
 ng.ng_LeftEdge=lvright-wg;
 ng.ng_GadgetText=QUButtonText;
 ng.ng_GadgetID=QUGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /* Calculate window height */
 wh=ng.ng_TopEdge+g->Height+INTERHEIGHT-topborder;

 /* Create menus */
 if (!(wmn=CreateMenus(mdata,
                       GTMN_FullMenu,TRUE,
                       TAG_DONE))) goto cg2;

 /* Layout menus */
 if (!LayoutMenus(wmn,vi,TAG_DONE)) goto cg3;

 CloseFont(f);        /* Close window font */
 return(TRUE);        /* All gadgets created! */

 /* Something went wrong.... */
cg3: FreeMenus(wmn);
cg2: FreeGadgets(gl);
     CloseFont(f);
cg1: return(FALSE);
}

/* Open status window */
void OpenStatusWindow(void)
{
 if (statwinsig) return;

 /* Create window title */
 if (!(wtb=malloc(strlen(wtbc)+strlen(PopUpHotKey)+1)))
  goto osw1;
 strcpy(wtb,wtbc);
 strcat(wtb,PopUpHotKey);

 if (!(pubsc=LockPubScreen(WBScreenName))) /* Lock Workbench screen */
  goto osw2;

 if (!(vi=GetVisualInfo(pubsc,TAG_DONE))) /* Get visual information */
  goto osw3;

 if (!CreateGadgets())                    /* Create Gadgets */
  goto osw4;

 /* Open window */
 if (!(w=OpenWindowTags(&nw,
                        WA_Left,wl,
                        WA_Top,wt,
                        WA_InnerWidth,ww,
                        WA_InnerHeight,wh,
                        WA_Title,wtb,
                        WA_PubScreen,pubsc,
                        WA_AutoAdjust,TRUE,
                        TAG_DONE)))
  goto osw5;

 wp=w->UserPort; /* Retrieve window port */

 /* Circumvent an intuition.library bug. See AutoDocs for LockPubScreen() */
 UnlockPubScreen(NULL,pubsc);
 pubsc=NULL;

 /* Add gadget list to window */
 AddGList(w,gl,(UWORD) -1,(UWORD) -1,NULL);
 RefreshGList(gl,w,NULL,(UWORD) -1);
 GT_RefreshWindow(w,NULL);

 /* Add menu to window */
 if (!SetMenuStrip(w,wmn))
  goto osw6;

 /* Notify Workbench about window */
 if (!(aw=AddAppWindow(NULL,NULL,w,MyMP,TAG_DONE)))
  goto osw7;

 /* Window open! */
 statwinsig=1L<<wp->mp_SigBit;
 return;

 /* Something went wrong.... */
osw7: ClearMenuStrip(w);
osw6: CloseWindow(w);
osw5: FreeMenus(wmn);
      FreeGadgets(gl);
osw4: FreeVisualInfo(vi);
osw3: if (pubsc) UnlockPubScreen(NULL,pubsc);
osw2: free(wtb);
osw1: return;
}

/* Close status window */
void CloseStatusWindow(void)
{
 if (statwinsig)
  {
   wl=w->LeftEdge;      /* Retreive window parameters for next open */
   wt=w->TopEdge;
   RemoveAppWindow(aw);
   ClearMenuStrip(w);
   CloseWindow(w);
   FreeMenus(wmn);      /* Release allocated resources */
   FreeGadgets(gl);
   FreeVisualInfo(vi);
   free(wtb);
   statwinsig=0;
  }
}

/* Refresh status window gadgets */
void RefreshStatusWindow(void)
{
 PrintStatusLine();
 RefreshGList(gl,w,NULL,2); /* Refresh only the first two gadgets */
}

/* Find tool with lvord */
static struct ToolNode *FindTool(void)
{
 if (lvord>=0)             /* Is the ordinal number valid? */
  {                        /* Yes, search tool */
   struct ToolNode *tn;
   WORD i=0;               /* Counter */

   /* Scan tool list until the ordinal number is reached */
   for (tn=GetHead(&ToolList); tn; tn=GetSucc(tn),i++)
    if (i>=lvord) break;

   return(tn);
  }
 return(NULL);
}

/* If the window is open, detach tool list from ListView gadget */
void DetachToolList(void)
{
 if (statwinsig) GT_SetGadgetAttrs(lvgad,w,NULL,GTLV_Labels,-1,TAG_DONE);
}

/* If the window is open, attach tool list to ListView gadget */
void AttachToolList(void)
{
 if (statwinsig) GT_SetGadgetAttrs(lvgad,w,NULL,
                                   GTLV_Labels,&ToolList,
                                   /* If an item was selected, use it as
                                      top item */
                                   GTLV_Top,lvtop,
                                   GTLV_Selected,lvord,
                                   TAG_DONE);
}

/* Create new empty tool */
static void AddEmptyTool(void)
{
 struct ConfigBlock *cb;

 /* Get memory */
 if (cb=malloc(sizeof(struct ConfigBlock)))
  {
   /* Initialize config block */
   InitConfigBlock(cb);
   cb->cb_Type=TNTYPE_DUMMY;
   strcpy(cb->cb_Alias,"New Tool");

   /* Add tool */
   if (AddToolNode(cb,StartupCD))
    {
     /* Refresh Gadgets */
     RefreshStatusWindow();

     /* Set new tool as active ListView item */
     if (!editwinsig)
      {
       DetachToolList();
       lvtop=lvord=ToolCount-1;
       AttachToolList();
      }
    }
   else DisplayBeep(NULL);

   /* Free memory */
   free(cb);
  }
}

/* Open edit window */
static void EditTool(void)
{
 struct ToolNode *tn;

 if (!editwinsig)
  {
   tn=FindTool();
   if (tn) OpenEditWindow(w->LeftEdge,w->TopEdge,ww,tn);
  }
}

/* Remove tool */
static void SWRemoveTool(void)
{
 struct ToolNode *tn;

 if (!editwinsig)   /* Edit window not open? */
  {
   tn=FindTool();   /* Search tool */
   if (tn)          /* Tool found? */
    {
     lvord=-1;         /* Invalidate ordinal number */

     DetachToolList(); /* Remove tool from list */
     RemToolNode(tn);
     AttachToolList();

     RefreshStatusWindow(); /* Refresh Gadgets */
    }
  }
}

/* Start tool */
static void SWStartTool(void)
{
 struct ToolNode *tn;

 tn=FindTool();
 if (tn) StartTool(tn,NULL);
}

/* Handle window events */
void HandleStatWinEvent(void)
{
 BOOL clwin=FALSE; /* TRUE if window should be closed */
 struct IntuiMessage *msg;

 while (msg=GT_GetIMsg(wp)) /* Pre-process Intuition messages */
  {
   switch (msg->Class)
    {
     case CLOSEWINDOW:      /* User clicked the close gadget */
      clwin=TRUE;           /* Yes, close window */
      break;
     case REFRESHWINDOW:    /* Window must be refreshed */
      GT_BeginRefresh(w);
      GT_EndRefresh(w,TRUE);
      break;
     case GADGETUP:         /* User released a gadget */
      switch(((struct Gadget *) msg->IAddress)->GadgetID)
       {
        case LVGAD_ID:      /* User selected ListView item */
         struct ToolNode *tn;
         ULONG secs=msg->Seconds,micros=msg->Micros;

         /* If no edit window is open then check for double click */
         if ((lvord==msg->Code) && DoubleClick(oldsecs,oldmicros,secs,micros))
         /* User double clicked the LV gadget --> Start tool */
          SWStartTool();
         /* No double click --> retrieve the ordinal number of selected item */
         else lvtop=lvord=msg->Code;

         /* Save current time */
         oldsecs=secs;
         oldmicros=micros;
         break;
        case NTGAD_ID:      /* User selected new tool gadget */
         AddEmptyTool();
         break;
        case ETGAD_ID:      /* User selected edit tool definition gadget */
         EditTool();
         break;
        case STGAD_ID:      /* User selected start tool gadget */
         SWStartTool();
         break;
        case RTGAD_ID:      /* User selected remove tool gadget */
         SWRemoveTool();
         break;
        case SCGAD_ID:      /* User selected save config gadget */
         WriteConfigFile(w);
         break;
        case ENGAD_ID:      /* User selected enable broker gadget */
         ActivateCxObj(MyBroker,1);
         break;
        case DIGAD_ID:      /* User selected enable broker gadget */
         ActivateCxObj(MyBroker,0);
         break;
        case QUGAD_ID:      /* User selected quit gadget */
         if (!clwin)
          {
           SetQuitFlag();
           if (!running) clwin=TRUE;
          }
         break;
       }
      break;
     case MENUPICK:         /* User selected a menu */
      USHORT mnum=msg->Code;

      while (mnum!=MENUNULL) /* Scan all menus */
       {
        struct MenuItem *mi=ItemAddress(wmn,mnum);

        switch(GTMENUITEM_USERDATA(mi))
         {
          case HIMENU_ID:   /* User selected hide menu item */
           clwin=TRUE;
           break;
          case ABMENU_ID:
           EasyRequest(NULL,&AboutES,NULL,NULL);
           break;
          case QUMENU_ID:   /* User selected quit menu item */
           if (!clwin)
            {
             SetQuitFlag();
             if (!running) clwin=TRUE;
            }
           break;
          case ENMENU_ID:   /* User selected enable broker menu item */
           ActivateCxObj(MyBroker,1);
           break;
          case DIMENU_ID:   /* User selected disable broker menu item */
           ActivateCxObj(MyBroker,0);
           break;
          case STMENU_ID:   /* User selected start tool menu item */
           SWStartTool();
           break;
          case NTMENU_ID:   /* User selected new tool menu item */
           AddEmptyTool();
           break;
          case ETMENU_ID:   /* User selected edit tool definition menu item */
           EditTool();
           break;
          case SCMENU_ID:   /* User selected save config menu item */
           WriteConfigFile(w);
           break;
          case RTMENU_ID:   /* User selected remove tool menu item */
           SWRemoveTool();
           break;
         }

        /* Next selected menu */
        mnum=mi->NextSelect;
       }
      break;
    }
   GT_ReplyIMsg(msg); /* Reply pre-processed message */
  }

 if (clwin) CloseStatusWindow();
}
