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

/* Structures for window */
extern UBYTE WindowTitle[];
extern struct NewWindow nw;
#define WDRAGBARLEN 60       /* Width of Close & Drag gadget */
static struct Window *w=NULL;
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 */
static WORD lvord=-1;                        /* LV gadget ordinal number */
static WORD lvtop=0;                         /* LV gadget top item number */
#define LVGAD_ID 1
static char ETButtonText[]="Edit Tool Definition"; /* Edit Tool gadget text */
#define ETGAD_ID 2
static char RTButtonText[]="Remove Tool";    /* Remove Tool gadget text */
#define RTGAD_ID 3
char SCButtonText[]="Save Configuration";    /* Save config gadget text */
#define SCGAD_ID 4

/* Create & handle edit window */
static BOOL EditToolWindow(struct ToolNode *tn)
{
 struct NewGadget ng;
 struct Gadget *g,*gl=NULL;
 static struct TextAttr ta={"topaz.font",8,0,0};
 struct TextFont *f;              /* Window font */
 UWORD topborder,fheight;
 ULONG wh;
 struct Window *ew;
 struct MsgPort *wp;
 BOOL rc=TRUE,end=TRUE;
 char buf[BUFLEN];

 if (!(pubsc=LockPubScreen("Workbench"))) /* Lock Workbench screen */
  goto e1;

 if (!(f=OpenFont(pubsc->Font))) goto e2; /* Open window font */
 topborder=pubsc->WBorTop+f->tf_YSize+1;
 CloseFont(f);                            /* Close font */

 if (!(f=OpenFont(&ta))) goto e2;         /* Open window font */
 fheight=f->tf_YSize;                     /* Font height */
 CloseFont(f);                            /* Close font */

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

 /* Create edit gadget */
 BuildConfigLine(tn,buf);
 ng.ng_LeftEdge=pubsc->WBorLeft+INTERWIDTH;
 ng.ng_TopEdge=topborder+INTERHEIGHT;
 ng.ng_Height=fheight+INTERHEIGHT+2;
 ng.ng_Width=ww;
 ng.ng_TextAttr=&ta;
 ng.ng_GadgetText=NULL;
 ng.ng_Flags=PLACETEXT_IN;
 ng.ng_VisualInfo=vi;
 ng.ng_UserData=0;
 if (!(g=CreateGadget(STRING_KIND,g,&ng,
                      GTST_String,buf,
                      GTST_MaxChars,BUFLEN-1,
                      TAG_DONE)))
  goto e3;

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

 /* Open window */
 if (!(ew=OpenWindowTags(&nw,
                         WA_Left,w->LeftEdge-INTERWIDTH,
                         WA_Top,w->TopEdge+4*wh,
                         WA_InnerWidth,ww+2*INTERWIDTH,
                         WA_InnerHeight,wh,
                         WA_PubScreen,pubsc,
                         WA_AutoAdjust,TRUE,
                         WA_Title,ETButtonText,
                         TAG_DONE)))
  goto e3;

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

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

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

 /* All OK */
 rc=FALSE;

 while (end)
  {
   struct IntuiMessage *msg;

   WaitPort(wp);

   while (msg=GT_GetIMsg(wp))
    {
     switch (msg->Class)
      {
       case INTUITICKS:           /* Intuition tick received */
        break;
       case CLOSEWINDOW:          /* User clicked the close gadget */
        end=FALSE;                /* Yes, close window */
        break;
       case REFRESHWINDOW:        /* Window must be refreshed */
        GT_BeginRefresh(ew);
        GT_EndRefresh(ew,TRUE);
        break;
       case GADGETUP:             /* User released the gadget */
        /* Config line changed? */
        if (strcmp(buf,((struct StringInfo *) g->SpecialInfo)->Buffer))
         {
          /* Yes, copy new config line */
          strcpy(buf,((struct StringInfo *) g->SpecialInfo)->Buffer);

          /* Build new ToolNode */
          DetachToolList();
          if (ScanConfigLine(buf,tn->tn_DirLock))
           {                        /* ToolNode created? */
            RemToolNode(tn);        /* Yes, remove old tool */
            lvord=-1;               /* Invalidate ordinal number */
            end=FALSE;              /* Close window */
           }
          else                      /* No, reactivate Gadget */
           {
            DisplayBeep(NULL);
            ActivateGadget(g,ew,NULL);
           }

          AttachToolList();
         }
        else end=FALSE; /* Definition not changed, but close edit window */
        break;
      }
     GT_ReplyIMsg(msg);
    }
  }

    CloseWindow(ew);
e3: FreeGadgets(gl);
e2: if (pubsc) UnlockPubScreen(NULL,pubsc);
e1: return(rc);
}

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

/* Create all status window gadgets */
static BOOL CreateWindowGadgets(void)
{
 struct NewGadget ng;
 struct Gadget *g;
 struct TextAttr *ta=pubsc->Font;
 struct TextFont *f;              /* Window font */
 struct RastPort tmprp;           /* RastPort for font-sensitive trick */
 UWORD width,fheight;
 UWORD leftedge,topborder;
 UWORD lvright;

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

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

 /* Calculate window width */
 ww=TextLength(&tmprp,WindowTitle,strlen(WindowTitle))+WDRAGBARLEN;

 /* 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=ta;
 ng.ng_Flags=PLACETEXT_IN;
 ng.ng_VisualInfo=vi;
 ng.ng_UserData=0;
 if (!(g=CreateGadget(TEXT_KIND,g,&ng,TAG_DONE))) goto e1;
 g->GadgetText->DrawMode=JAM2; /* Argh, why doesn't exist a tag for this? */

 /* 2. gadget: ListView, tool list */
 ng.ng_LeftEdge=leftedge+WDRAGBARLEN/2;
 ng.ng_TopEdge+=g->Height+INTERHEIGHT;
 ng.ng_Width=ww-WDRAGBARLEN;
 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 e1;
 lvright=ng.ng_LeftEdge+g->Width;

 /* 3. gadget: Button, edit tool definition */
 ng.ng_TopEdge+=g->Height+fheight+2*INTERHEIGHT;
 ng.ng_Width=TextLength(&tmprp,ETButtonText,sizeof(ETButtonText)-1)+INTERWIDTH;
 ng.ng_Height=fheight+INTERHEIGHT;
 ng.ng_GadgetText=ETButtonText;
 ng.ng_GadgetID=ETGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto e1;

 /* 4. gadget: Button, remove tool */
 width=TextLength(&tmprp,RTButtonText,sizeof(RTButtonText)-1)+INTERWIDTH;
 ng.ng_LeftEdge=lvright-width;
 ng.ng_Width=width;
 ng.ng_GadgetText=RTButtonText;
 ng.ng_GadgetID=RTGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto e1;

 /* 5. gadget: Button, save config */
 width=TextLength(&tmprp,SCButtonText,sizeof(SCButtonText)-1)+INTERWIDTH;
 ng.ng_LeftEdge=leftedge+(ww-width)/2;
 ng.ng_TopEdge+=g->Height+INTERHEIGHT;
 ng.ng_Width=width;
 ng.ng_GadgetText=SCButtonText;
 ng.ng_GadgetID=SCGAD_ID;
 if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE))) goto e1;

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

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

 /* Something went wrong.... */
e1: CloseFont(f);
    FreeGadgets(gl);
    return(FALSE);
}

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

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

 if (!CreateWindowGadgets())              /* Create Gadgets */
  goto osw3;

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

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

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

 /* Window open! */
 return(1L<<wp->mp_SigBit);

 /* Something went wrong.... */
osw5: CloseWindow(w);
      w=NULL;
osw4: FreeGadgets(gl);
osw3: FreeVisualInfo(vi);
osw2: if (pubsc) UnlockPubScreen(NULL,pubsc);
osw1: return(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 (w) 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 (w) 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);
}

/* Handle window events */
BOOL HandleWindowEvent(void)
{
 BOOL rc=FALSE;             /* True if window close event */
 struct IntuiMessage *msg;
 struct ToolNode *tn;

 while (msg=GT_GetIMsg(wp)) /* Pre-process Intuition messages */
  {
   switch (msg->Class)
    {
     case INTUITICKS:       /* Intuition tick received */
      break;
     case CLOSEWINDOW:      /* User clicked the close gadget */
      wl=w->LeftEdge;       /* Retreive window parameters for next open */
      wt=w->TopEdge;
      rc=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 a ListView item */
         lvtop=lvord=msg->Code; /* Retrieve the ordinal number of the item */
         break;
        case RTGAD_ID:      /* User selected the remove tool gadget */
         tn=FindTool();     /* Search tool */
         if (tn)            /* Tool found? */
          {
           lvord=-1;              /* Invalidate ordinal number */

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

           RefreshStatusWindow(); /* Refresh Gadgets */
          }
         break;
        case ETGAD_ID:      /* User selected the edit tool definition gadget */
         tn=FindTool();
         if (tn)
          if (EditToolWindow(tn)) DisplayBeep(NULL);
         break;
        case SCGAD_ID:      /* User selected the save config gadget */
         if (WriteConfigFile(w)) DisplayBeep(NULL);
         break;
       }
      break;
    }
   GT_ReplyIMsg(msg); /* Reply pre-processed message */
  }

 return rc;
}

/* Close status window */
void CloseStatusWindow(void)
{
 RemoveAppWindow(aw);
 CloseWindow(w);
 w=NULL;
 FreeGadgets(gl);     /* Release allocated resources */
 FreeVisualInfo(vi);
}
