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

/* Structures for window */
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! */
extern struct GfxBase *GfxBase;
static struct TextAttr ta={NULL,0,0,0};
static struct Gadget *gl;    /* Gadget list */
static char StatusText[]="Active Tools: 00"; /* Text gadget text */
static struct Gadget *tlvg;                  /* 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 TPButtonText[]="Top";            /* Move tool to top gadget text */
static struct Gadget *tpbg;
#define TPGAD_ID  2
static char UPButtonText[]="Up";             /* Move tool one up gadget text */
static struct Gadget *upbg;
#define UPGAD_ID  3
static char DNButtonText[]="Down";           /* Move tool one down gad. text */
static struct Gadget *dnbg;
#define DNGAD_ID  4
static char BMButtonText[]="Bottom";         /* Move tool to bottom gad. text */
static struct Gadget *bmbg;
#define BMGAD_ID  5
static char NTButtonText[]="New";            /* New tool gadget text */
#define NTGAD_ID  6
static char ETButtonText[]="Edit";           /* Edit tool gadget text */
static struct Gadget *etbg;
#define ETGAD_ID  7
static char RTButtonText[]="Remove";         /* Remove tool gadget text */
static struct Gadget *rtbg;
#define RTGAD_ID  8
static char ENButtonText[]="Enable";         /* Enable broker gadget text */
static BOOL BrokerState;
static struct Gadget *ebbg;
#define ENGAD_ID  9
static char HKButtonText[]="HotKeys";        /* HotKeys gadget text */
static struct Gadget *hkbg;
#define HKGAD_ID 10
static char DIButtonText[]="Disable";        /* Disable broker gadget text */
static struct Gadget *dbbg;
#define DIGAD_ID 11
static char ODButtonText[]="Dock On";        /* Dock on gadget text */
static struct Gadget *odbg;
#define ODGAD_ID 12
static char DOButtonText[]="Dock H/V";       /* Dock orientation text */
static struct Gadget *dobg;
#define DOGAD_ID 13
static char CDButtonText[]="Dock Off";       /* Dock off gadget text */
static struct Gadget *cdbg;
#define CDGAD_ID 14
static char SCButtonText[]="Save";           /* Save config gadget text */
#define SCGAD_ID 15
static char HIButtonText[]="Hide";           /* Hide gadget text */
#define HIGAD_ID 16
static char QUButtonText[]="Quit";           /* Quit gadget text */
#define QUGAD_ID 17

/* Structures for window menu */
static struct Menu *wmn=NULL;
#define NCMENU_ID   1
#define OCMENU_ID   2
#define ACMENU_ID   3
#define SCMENU_ID   4
#define SAMENU_ID   5
#define HIMENU_ID   6
static char ABMenuText[]="About...";
#define ABMENU_ID   7
#define QUMENU_ID   8
#define STMENU_ID   9
#define STMENU_NUM FULLMENUNUM(1,0,0)
#define NTMENU_ID  10
#define ETMENU_ID  11
#define ETMENU_NUM FULLMENUNUM(1,2,0)
#define RTMENU_ID  12
#define RTMENU_NUM FULLMENUNUM(1,3,0)
#define TPMENU_ID  13
#define TPMENU_NUM FULLMENUNUM(1,5,0)
#define UPMENU_ID  14
#define UPMENU_NUM FULLMENUNUM(1,6,0)
#define DNMENU_ID  15
#define DNMENU_NUM FULLMENUNUM(1,7,0)
#define BMMENU_ID  16
#define BMMENU_NUM FULLMENUNUM(1,8,0)
#define ENMENU_ID  17
#define ENMENU_NUM FULLMENUNUM(2,0,0)
#define DIMENU_ID  18
#define DIMENU_NUM FULLMENUNUM(2,1,0)
#define HLMENU_ID  19
#define HLMENU_NUM FULLMENUNUM(2,2,0)
#define ODMENU_ID  20
#define ODMENU_NUM FULLMENUNUM(3,0,0)
#define DOMENU_ID  21
#define DOMENU_NUM FULLMENUNUM(3,1,0)
#define CDMENU_ID  22
#define CDMENU_NUM FULLMENUNUM(3,2,0)
static struct NewMenu mdata[]={
      {NM_TITLE,"Project"   ,NULL,0,~0,NULL},
       {NM_ITEM,NTButtonText,"N",0,~0,NCMENU_ID},
       {NM_ITEM,"Open..."   ,"O",0,~0,OCMENU_ID},
       {NM_ITEM,"Append..." ,NULL,0,~0,ACMENU_ID},
       {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL},
       {NM_ITEM,SCButtonText,"S",0,~0,SCMENU_ID},
       {NM_ITEM,"Save As...","A",0,~0,SAMENU_ID},
       {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL},
       {NM_ITEM,HIButtonText,"H",0,~0,HIMENU_ID},
       {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL},
       {NM_ITEM,ABMenuText  ,NULL,0,~0,ABMENU_ID},
       {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL},
       {NM_ITEM,QUButtonText,"Q",0,~0,QUMENU_ID},
      {NM_TITLE,"Tools",NULL,0,~0,NULL},
       {NM_ITEM,"Start"     ,"G",0,~0,STMENU_ID},
       {NM_ITEM,NTButtonText,NULL,0,~0,NTMENU_ID},
       {NM_ITEM,ETButtonText,"E",0,~0,ETMENU_ID},
       {NM_ITEM,RTButtonText,NULL,0,~0,RTMENU_ID},
       {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL},
       {NM_ITEM,TPButtonText,"T",0,~0,TPMENU_ID},
       {NM_ITEM,UPButtonText,"<",0,~0,UPMENU_ID},
       {NM_ITEM,DNButtonText,">",0,~0,DNMENU_ID},
       {NM_ITEM,BMButtonText,"B",0,~0,BMMENU_ID},
      {NM_TITLE,HKButtonText,NULL,0,~0,NULL},
       {NM_ITEM,ENButtonText,NULL,0,~0,ENMENU_ID},
       {NM_ITEM,DIButtonText,NULL,0,~0,DIMENU_ID},
       {NM_ITEM,"List"      ,"L",0,~0,HLMENU_ID},
      {NM_TITLE,"Dock",NULL,0,~0,NULL},
       {NM_ITEM,"Open"      ,NULL,0,~0,ODMENU_ID},
       {NM_ITEM,"H/V"       ,NULL,0,~0,DOMENU_ID},
       {NM_ITEM,"Close"     ,"C",0,~0,CDMENU_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";
struct EasyStruct AboutES={sizeof(struct EasyStruct),0,ABMenuText,AboutText,
                           "Ok"};

/* Data for dock window */
extern BOOL DockVertical;

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

/* Set Menu state depending on Broker state */
void SetBrokerMenuState(void)
{
 /* Broker on or off */
 if (BrokerState)
  {
   OffMenu(w,ENMENU_NUM);
   OnMenu(w,DIMENU_NUM);
   OnMenu(w,HLMENU_NUM);
  }
 else
  {
   OnMenu(w,ENMENU_NUM);
   OffMenu(w,DIMENU_NUM);
   OffMenu(w,HLMENU_NUM);
  }
}

/* Set Menu state depending on editwinsig/selection state */
void SetToolMenuState(BOOL state)
{
 if (state)
  { /* Deactivate menu entries */
   OffMenu(w,STMENU_NUM);
   OffMenu(w,ETMENU_NUM);
   OffMenu(w,RTMENU_NUM);
   OffMenu(w,TPMENU_NUM);
   OffMenu(w,UPMENU_NUM);
   OffMenu(w,DNMENU_NUM);
   OffMenu(w,BMMENU_NUM);
  }
 else
  { /* Activate menu entries */
   OnMenu(w,STMENU_NUM);
   OnMenu(w,ETMENU_NUM);
   OnMenu(w,RTMENU_NUM);
   OnMenu(w,TPMENU_NUM);
   OnMenu(w,UPMENU_NUM);
   OnMenu(w,DNMENU_NUM);
   OnMenu(w,BMMENU_NUM);
  }
}

/* Set Menu state depending on ShowDock state */
void SetDockMenuState(BOOL open)
{
 if (!open && DockCount)
  OnMenu(w,ODMENU_NUM);
 else
  OffMenu(w,ODMENU_NUM);

 if (open && DockCount)
  {
   OnMenu(w,DOMENU_NUM);
   OnMenu(w,CDMENU_NUM);
  }
 else
  {
   OffMenu(w,DOMENU_NUM);
   OffMenu(w,CDMENU_NUM);
  }
}

/* Create all status window gadgets & menus */
static BOOL CreateGadgets(void)
{
 struct NewGadget ng;
 struct Gadget *g;
 struct TextFont *f;
 struct RastPort tmprp;
 UWORD wg,width,fheight,fwidth;
 UWORD leftedge,topborder,gadtop;
 BOOL disgad=editwinsig || (lvord<0);

 if (!(f=OpenFont(pubsc->Font))) goto cg1;  /* Open window font */
 topborder=pubsc->WBorTop+f->tf_YSize+1;    /* Top border offset */

 /* Calculate length of window title */
 InitRastPort(&tmprp);
 SetFont(&tmprp,f);
 ww=TextLength(&tmprp,wtb,strlen(wtb))+WDRAGBARLEN;
 CloseFont(f);                              /* Close font */

 f=GfxBase->DefaultFont;                   /* System Default Font */
 ta.ta_Name=f->tf_Message.mn_Node.ln_Name;
 ta.ta_YSize=fheight=f->tf_YSize;          /* Font height */
 fwidth=f->tf_XSize;                       /* Font width */
 leftedge=pubsc->WBorLeft+INTERWIDTH/2;

 /* Calculate window & gadget width */
 wg=(sizeof(DOButtonText)-1)*fwidth+INTERWIDTH;
 if ((width=4*wg+5*INTERWIDTH)>ww) ww=width;

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

 /*  1. gadget: Text, status line */
 PrintStatusLine();
 width=(sizeof(StatusText)-1)*fwidth+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=&ta;
 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;
 ng.ng_TopEdge+=fheight+INTERHEIGHT;
 ng.ng_Width=ww-wg-2*INTERWIDTH;
 ng.ng_Height=10*fheight;
 ng.ng_GadgetText=NULL;
 ng.ng_GadgetID=LVGAD_ID;
 if (!(tlvg=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;
 gadtop=ng.ng_TopEdge+10*fheight+INTERHEIGHT;

 /*  3. gadget: Button, move tool to top */
 ng.ng_LeftEdge=ww-wg;
 ng.ng_TopEdge+=(5*fheight-7*INTERHEIGHT)/2;
 ng.ng_Width=wg;
 ng.ng_Height=fheight+INTERHEIGHT;
 ng.ng_GadgetText=TPButtonText;
 ng.ng_GadgetID=TPGAD_ID;
 if (!(tpbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,disgad,
                           TAG_DONE)))
  goto cg2;

 /*  4. gadget: Button, move tool one up */
 ng.ng_TopEdge+=fheight+2*INTERHEIGHT;
 ng.ng_GadgetText=UPButtonText;
 ng.ng_GadgetID=UPGAD_ID;
 if (!(upbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,disgad,
                           TAG_DONE)))
  goto cg2;

 /*  5. gadget: Button, move tool one down */
 ng.ng_TopEdge+=fheight+2*INTERHEIGHT;
 ng.ng_GadgetText=DNButtonText;
 ng.ng_GadgetID=DNGAD_ID;
 if (!(dnbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,disgad,
                           TAG_DONE)))
  goto cg2;

 /*  6. gadget: Button, move tool to bottom */
 ng.ng_TopEdge+=fheight+2*INTERHEIGHT;
 ng.ng_GadgetText=BMButtonText;
 ng.ng_GadgetID=BMGAD_ID;
 if (!(bmbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,disgad,
                           TAG_DONE)))
  goto cg2;

 /*  7. gadget: Button, new tool */
 ng.ng_LeftEdge=leftedge;
 ng.ng_TopEdge=gadtop;
 ng.ng_GadgetText=NTButtonText;
 ng.ng_GadgetID=NTGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

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

 /*  9. gadget: Button, remove tool */
 ng.ng_LeftEdge=ww-wg;
 ng.ng_GadgetText=RTButtonText;
 ng.ng_GadgetID=RTGAD_ID;
 if (!(rtbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,disgad,
                           TAG_DONE)))
  goto cg2;

 /* 10. gadget: Button, enable broker */
 ng.ng_LeftEdge=leftedge;
 ng.ng_TopEdge+=fheight+3*INTERHEIGHT;
 ng.ng_GadgetText=ENButtonText;
 ng.ng_GadgetID=ENGAD_ID;
 if (!(ebbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,BrokerState,
                           TAG_DONE)))
  goto cg2;

 /* 11. gadget: Button, HotKeys */
 ng.ng_LeftEdge=leftedge+(ww-wg)/2;
 ng.ng_GadgetText=HKButtonText;
 ng.ng_GadgetID=HKGAD_ID;
 if (!(hkbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,!BrokerState,
                           TAG_DONE)))
  goto cg2;

 /* 12. gadget: Button, disable broker */
 ng.ng_LeftEdge=ww-wg;
 ng.ng_GadgetText=DIButtonText;
 ng.ng_GadgetID=DIGAD_ID;
 if (!(dbbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,!BrokerState,
                           TAG_DONE)))
  goto cg2;

 /* 13. gadget: Button, Dock on */
 ng.ng_LeftEdge=leftedge;
 ng.ng_TopEdge+=fheight+3*INTERHEIGHT;
 ng.ng_GadgetText=ODButtonText;
 ng.ng_GadgetID=ODGAD_ID;
 if (!(odbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,ShowDock || !DockCount,
                           TAG_DONE)))
  goto cg2;

 /* 14. gadget: Button, Dock H/V */
 ng.ng_LeftEdge=leftedge+(ww-wg)/2;
 ng.ng_GadgetText=DOButtonText;
 ng.ng_GadgetID=DOGAD_ID;
 if (!(dobg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,!ShowDock || !DockCount,
                           TAG_DONE)))
  goto cg2;

 /* 15. gadget: Button, Dock off */
 ng.ng_LeftEdge=ww-wg;
 ng.ng_GadgetText=CDButtonText;
 ng.ng_GadgetID=CDGAD_ID;
 if (!(cdbg=g=CreateGadget(BUTTON_KIND,g,&ng,
                           GA_Disabled,!ShowDock || !DockCount,
                           TAG_DONE)))
  goto cg2;

 /* 16. gadget: Button, save config */
 ng.ng_LeftEdge=leftedge;
 ng.ng_TopEdge+=fheight+3*INTERHEIGHT;
 ng.ng_GadgetText=SCButtonText;
 ng.ng_GadgetID=SCGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /* 17. gadget: Button, Hide */
 ng.ng_LeftEdge=leftedge+(ww-wg)/2;
 ng.ng_GadgetText=HIButtonText;
 ng.ng_GadgetID=HIGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto cg2;

 /* 18. gadget: Button, Quit */
 ng.ng_LeftEdge=ww-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+fheight+2*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;

 return(TRUE);        /* All gadgets created! */

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

/* Open status window */
void OpenStatusWindow(BOOL tofront)
{
 if (!(pubsc=LockPubScreen(WBScreenName))) /* Lock Workbench screen */
  goto osw1;

 /* Window already open? */
 if (statwinsig)
  {
   /* Yes. Move it to front and activate it */
   WindowToFront(w);
   ActivateWindow(w);

   /* Move Screen to front if needed */
   if (tofront) ScreenToFront(pubsc);
   return;
  }

 /* Create window title */
 if (!(wtb=malloc(strlen(MyName)+strlen(PopUpHotKey)+10)))
  goto osw2;
 strcpy(wtb,MyName);
 strcat(wtb,": HotKey=");
 strcat(wtb,PopUpHotKey);

 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 */

 /* 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;
 SetBrokerMenuState();
 SetToolMenuState(editwinsig || (lvord<0));
 SetDockMenuState(ShowDock);

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

 /* Window open! */
 UnlockPubScreen(NULL,pubsc);
 statwinsig=1L<<wp->mp_SigBit;
 globalsigs|=statwinsig;
 return;

 /* Something went wrong.... */
osw7: ClearMenuStrip(w);
osw6: CloseWindow(w);
osw5: FreeMenus(wmn);
      FreeGadgets(gl);
osw4: FreeVisualInfo(vi);
osw3: free(wtb);
osw2: UnlockPubScreen(NULL,pubsc);
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);
   globalsigs&=~statwinsig;
   statwinsig=0;
  }
}

/* Refresh status window gadgets if window is open */
void RefreshStatusWindow(void)
{
 if (statwinsig)
  {
   PrintStatusLine();         /* Print new status line */
   RefreshGList(gl,w,NULL,2); /* Refresh only the first two gadgets */
  }
}

/* Set Broker state and gadgets */
void SetBrokerState(BOOL state)
{
 /* Set new state */
 BrokerState=state;
 ActivateCxObj(MyBroker,state);

 /* Status window open? */
 if (statwinsig)
  {
   /* Yes, set new gadget state */
   GT_SetGadgetAttrs(ebbg,w,NULL,GA_Disabled,state,TAG_DONE);
   GT_SetGadgetAttrs(dbbg,w,NULL,GA_Disabled,!state,TAG_DONE);
   GT_SetGadgetAttrs(hkbg,w,NULL,GA_Disabled,!state,TAG_DONE);

   /* Set new menu state */
   SetBrokerMenuState();
  }
}

/* If the window is open, detach tool list from ListView gadget */
void DetachToolList(void)
{
 if (statwinsig) GT_SetGadgetAttrs(tlvg,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(tlvg,w,NULL,
                                   GTLV_Labels,&ToolList,
                                   /* If an item was selected, use it as
                                      top item */
                                   GTLV_Top,lvtop,
                                   GTLV_Selected,lvord,
                                   TAG_DONE);
}

/* Set activation status of tool gadgets/menus */
static void DisableToolGads(BOOL state)
{
 /* Gadgets */
 GT_SetGadgetAttrs(tpbg,w,NULL,GA_Disabled,state,TAG_DONE);
 GT_SetGadgetAttrs(upbg,w,NULL,GA_Disabled,state,TAG_DONE);
 GT_SetGadgetAttrs(dnbg,w,NULL,GA_Disabled,state,TAG_DONE);
 GT_SetGadgetAttrs(bmbg,w,NULL,GA_Disabled,state,TAG_DONE);
 GT_SetGadgetAttrs(etbg,w,NULL,GA_Disabled,state,TAG_DONE);
 GT_SetGadgetAttrs(rtbg,w,NULL,GA_Disabled,state,TAG_DONE);

 /* Menus */
 SetToolMenuState(state);
}

/* Set gadget and menu state */
void StatWinDockState(BOOL open)
{
 /* Status window open? */
 if (statwinsig)
  {
   /* Yes, set gadget & menu attributes */
   SetDockMenuState(open);
   GT_SetGadgetAttrs(odbg,w,NULL,GA_Disabled,open || !DockCount,TAG_DONE);
   GT_SetGadgetAttrs(dobg,w,NULL,GA_Disabled,!open || !DockCount,TAG_DONE);
   GT_SetGadgetAttrs(cdbg,w,NULL,GA_Disabled,!open || !DockCount,TAG_DONE);
  }
}

/* Re-activate gadget after editing */
void StatWinEndEditing(void)
{
 if (statwinsig) DisableToolGads(FALSE);
 StatWinDockState(ShowDock);
}

/* Find tool with lvord */
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);
}

/* Clear the configuration */
static BOOL ClearConfig(void)
{
 BOOL canceled;

 /* Put up safety requester if needed */
 canceled=ShowSaveConfigRequester(w);

 /* If config was saved, then delete all tools */
 if (!canceled)
  {
   /* Close windows */
   CloseEditWindow();
   CloseHotKeysWindow();
   CloseDockWindow();

   /* Delete all tools */
   DisableToolGads(TRUE);
   DetachToolList();
   lvord=-1;
   lvtop=0;
   RemoveTools();
   AttachToolList();
   StatWinDockState(FALSE);
   ConfigChanged=FALSE;
  }

 return(canceled);
}

/* Move tool to top of list */
static void MoveToolTop(void)
{
 struct ToolNode *tn=FindTool();

 if (tn)          /* Tool selected? */
  {
   /* We are changing the list */
   DetachToolList();

   /* Move tool node */
   Remove((struct Node *) tn);
   AddHead(&ToolList,(struct Node *) tn);
   lvord=lvtop=0;

   /* We have changed the list */
   AttachToolList();
  }
}

/* Move tool one up in list */
static void MoveToolUp(void)
{
 struct ToolNode *tn=FindTool();

 if (tn)          /* Tool selected? */
  {
   /* Get predecessor */
   struct ToolNode *ltn=GetPred(tn);

   if (ltn)       /* Got a predecessor? */
    {
     /* Yes, we are changing the list */
     DetachToolList();

     /* Move tool node */
     ltn=GetPred(ltn);
     Remove((struct Node *) tn);
     Insert(&ToolList,(struct Node *) tn,(struct Node *) ltn);
     lvtop=--lvord;

     /* We have changed the list */
     AttachToolList();
    }
  }
}

/* Move tool one down in list */
static void MoveToolDown(void)
{
 struct ToolNode *tn=FindTool();

 if (tn)          /* Tool selected? */
  {
   /* Get successor */
   struct ToolNode *ltn=GetSucc(tn);

   if (ltn)       /* Got a successor? */
    {
     /* Yes, we are changing the list */
     DetachToolList();

     /* Move tool node */
     Remove((struct Node *) tn);
     Insert(&ToolList,(struct Node *) tn,(struct Node *) ltn);
     lvtop=++lvord;

     /* We have changed the list */
     AttachToolList();
    }
  }
}

/* Move tool to bottom of list */
static void MoveToolBottom(void)
{
 struct ToolNode *tn=FindTool();

 if (tn)          /* Tool selected? */
  {
   /* We are changing the list */
   DetachToolList();

   /* Move tool node */
   Remove((struct Node *) tn);
   AddTail(&ToolList,(struct Node *) tn);
   lvord=lvtop=ToolCount-1;

   /* We have changed the list */
   AttachToolList();
  }
}

/* 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))
    {
     struct ToolNode *tn;

     /* We are changing the list */
     DetachToolList();

     /* Move new tool behind the selected tool */
     if (tn=FindTool())
      {
       struct ToolNode *ntn=RemTail(&ToolList);

       /* Insert it after the selected one */
       Insert(&ToolList,(struct Node *) ntn, (struct Node *) tn);
      }

     /* Refresh Gadgets */
     RefreshStatusWindow();

     /* Set new tool as active ListView item */
     if (!editwinsig)
      {
       /* Set new tool number */
       lvord=(lvord<0)?ToolCount-1:lvord+1;
       lvtop=(lvord>0)?lvord-1:0;

       /* Activate gadgets */
       DisableToolGads(FALSE);
      }

     /* We have changed the list */
     AttachToolList();
     ConfigChanged=TRUE;
    }
   else DisplayBeep(NULL);

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

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

 if (tn)          /* Tool selected? */
  {
   /* Disable gadgets */
   DisableToolGads(TRUE);

   /* Open window */
   OpenEditWindow(w->LeftEdge,w->TopEdge,ww,tn);
  }
}

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

 if (tn)          /* Tool selected? */
  {
   lvord=-1;         /* Invalidate ordinal number */

   /* Disable Gadgets */
   DisableToolGads(TRUE);

   /* Update the HotKeys window */
   RefreshHotKeysWindow(tn,FALSE);

   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);
}

/* Open dock window */
static void SWDockWindow(BOOL open)
{
 /* Set gadget and menu state */
 StatWinDockState(open);

 /* Open/close window */
 if (open)
  OpenDockWindow();
 else
  CloseDockWindow();
}

/* Change dock window orientation */
static void ChangeDock(void)
{
 /* Invert boolean variables */
 DockVertical=!DockVertical;

 /* Change window */
 if (ShowDock)
  {
   CloseDockWindow();
   OpenDockWindow();
  }
}

/* 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 IDCMP_CLOSEWINDOW:   /* User clicked the close gadget */
      clwin=TRUE;              /* Yes, close window */
      break;
     case IDCMP_REFRESHWINDOW: /* Window must be refreshed */
      GT_BeginRefresh(w);
      GT_EndRefresh(w,TRUE);
      break;
     case IDCMP_GADGETUP:      /* User released a gadget */
      switch(((struct Gadget *) msg->IAddress)->GadgetID)
       {
        case LVGAD_ID:         /* User selected ListView item */
         if (editwinsig)       /* Edit window open? */
          {
           /* Yes --> Ignore selection. Note: This is needed, because */
           /* GA_Disabled is NOT SUPPORTED for LISTVIEW_KIND!         */
           GT_SetGadgetAttrs(tlvg,w,NULL,GTLV_Selected,lvord,TAG_DONE);
          }
         else /* Edit window not open --> Normal selection */
          {
           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();
           else
            {
             /* No double click --> retrieve ordinal number of selected item */
             lvtop=lvord=msg->Code;

             /* Activate gadgets */
             DisableToolGads(FALSE);
            }

           /* Save current time */
           oldsecs=secs;
           oldmicros=micros;
          }
         break;
        case TPGAD_ID:         /* User selected move tool to top gadget */
         MoveToolTop();
         break;
        case UPGAD_ID:         /* User selected move tool one up gadget */
         MoveToolUp();
         break;
        case DNGAD_ID:         /* User selected move tool one down gadget */
         MoveToolDown();
         break;
        case BMGAD_ID:         /* User selected move tool to bottom gadget */
         MoveToolBottom();
         break;
        case NTGAD_ID:         /* User selected new tool gadget */
         AddEmptyTool();
         break;
        case ETGAD_ID:         /* User selected edit tool definition gadget */
         EditTool();
         break;
        case RTGAD_ID:         /* User selected remove tool gadget */
         SWRemoveTool();
         break;
        case ENGAD_ID:         /* User selected enable broker gadget */
         SetBrokerState(TRUE);
         break;
        case HKGAD_ID:         /* User selected HotKeys gadget */
         OpenHotKeysWindow(w->LeftEdge,w->TopEdge);
         break;
        case DIGAD_ID:         /* User selected enable broker gadget */
         SetBrokerState(FALSE);
         break;
        case ODGAD_ID:         /* User selected Dock on gadget */
         SWDockWindow(TRUE);
         break;
        case DOGAD_ID:         /* User selected Dock H/V gadget */
         ChangeDock();
         break;
        case CDGAD_ID:         /* User selected Dock Off gadget */
         SWDockWindow(FALSE);
         break;
        case SCGAD_ID:         /* User selected save config gadget */
         WriteConfigFile(w,FALSE);
         break;
        case HIGAD_ID:         /* User selected hide gadget */
         clwin=TRUE;
         break;
        case QUGAD_ID:         /* User selected quit gadget */
         if (!clwin)
          {
           SetQuitFlag();
           if (!running) clwin=TRUE;
          }
         break;
       }
      break;
     case IDCMP_MENUPICK:      /* User selected a menu */
      USHORT mnum=msg->Code;

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

        switch(GTMENUITEM_USERDATA(mi))
         {
          case NCMENU_ID:      /* User selected new config menu item */
           ClearConfig();
           break;
          case OCMENU_ID:      /* User selected open config menu item */
           BOOL OldShowDock=ShowDock;
           char *cp=ConfigName;

           /* Pop up load config file requester */
           if (!ShowFileRequester(w,"Load Configuration",&cp,FREQ_FILE))
            {
             if (!ClearConfig()) /* First clear old entrys */
              {
               /* Remove old program AppIcon */
               if (MyAppIcon) RemoveAppIcon(MyAppIcon);

               /* Set & read in new config file */
               SetConfigFileName(cp);
               ReadConfigFile(cp,TRUE);

               /* Init icon position */
               MyIcon->do_CurrentX=IconXPos;
               MyIcon->do_CurrentY=IconYPos;

               /* Display our icon? Yes, notify Workbench about icon */
               if (ShowIcon)
                MyAppIcon=AddAppIconA(NULL,NULL,IconName,MyMP,NULL,MyIcon,NULL);

               /* Open dock window? */
               if (OldShowDock)
                OpenDockWindow();
               else
                StatWinDockState(FALSE);
              }
             free(cp);
            }
           break;
          case ACMENU_ID:      /* User selected append config menu item */
           char *cp=ConfigName;

           /* Pop up file requester */
           if (!ShowFileRequester(w,"Append Configuration",&cp,FREQ_FILE))
            {
             /* Read in another config file */
             ReadConfigFile(cp,FALSE);
             free(cp);

             ConfigChanged=TRUE;
            }
           break;
          case SCMENU_ID:      /* User selected save config menu item */
           WriteConfigFile(w,TRUE);
           break;
          case SAMENU_ID:      /* User selected save config as menu item */
           WriteConfigFile(w,FALSE);
           break;
          case HIMENU_ID:      /* User selected hide menu item */
           clwin=TRUE;
           break;
          case ABMENU_ID:
           EasyRequest(w,&AboutES,NULL,"");
           break;
          case QUMENU_ID:      /* User selected quit menu item */
           if (!clwin)
            {
             SetQuitFlag();
             if (!running) clwin=TRUE;
            }
           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 def. menu item */
           EditTool();
           break;
          case RTMENU_ID:      /* User selected remove tool menu item */
           SWRemoveTool();
           break;
          case TPMENU_ID:      /* User selected move tool to top menu item */
           MoveToolTop();
           break;
          case UPMENU_ID:      /* User selected move tool one up menu item */
           MoveToolUp();
           break;
          case DNMENU_ID:      /* User selected move tool one down menu item */
           MoveToolDown();
           break;
          case BMMENU_ID:      /* User selected move tool to bottom menu item */
           MoveToolBottom();
           break;
          case ENMENU_ID:      /* User selected enable broker menu item */
           SetBrokerState(TRUE);
           break;
          case DIMENU_ID:      /* User selected disable broker menu item */
           SetBrokerState(FALSE);
           break;
          case HLMENU_ID:      /* User selected HotKeys list menu item */
           OpenHotKeysWindow(w->LeftEdge,w->TopEdge);
           break;
          case ODMENU_ID:      /* User selected Dock on menu item */
           SWDockWindow(TRUE);
           break;
          case DOMENU_ID:      /* User selected Dock H/V menu item */
           ChangeDock();
           break;
          case CDMENU_ID:      /* User selected Dock off menu item */
           SWDockWindow(FALSE);
           break;
         }

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

 if (clwin) CloseStatusWindow();
}
