/*
 * hotkeyswindow.c   V1.5
 *
 * HotKeys list window
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* Structures for window */
static char WindowTitle[]=DEFPROGNAME " HotKey List"; /* Window title */
extern struct NewWindow nw;
static struct Window *w;
static struct MsgPort *wp;
static ULONG wh,ww;                       /* Window height, width */
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 struct Gadget *lvgad;

/* miscellaneous */
static struct List HotKeysList;
static struct HotKeyNode {
                          struct Node      hkn_Node;
                          struct ToolNode *hkn_ToolNode; /* Pointer to tool */
                         };

/* Free one HotKeyNode */
static void FreeHotKeyNode(struct HotKeyNode *hkn)
{
 /* Remove node from list */
 Remove((struct Node *) hkn);

 /* Free memory */
 free(hkn->hkn_Node.ln_Name);
 free(hkn);
}

/* Free HotKeys list */
static void FreeHotKeysList(void)
{
 struct HotKeyNode *hkn1,*hkn2=GetHead(&HotKeysList); /* Begin of list */

 while (hkn1=hkn2)
  {
   hkn2=GetSucc((struct ToolNode *) hkn1);
   FreeHotKeyNode(hkn1);
  }
}

/* Build one HotKeyNode */
static BOOL BuildHotKeyNode(struct ToolNode *tn)
{
 struct HotKeyNode *hkn;
 char *tnp,*hkp,*np;

 /* Get memory for the node */
 if (!(hkn=malloc(sizeof(struct HotKeyNode)))) return(FALSE);

 /* Get memory for node name */
 tnp=tn->tn_Node.ln_Name;
 hkp=tn->tn_HotKey;
 if (!(np=malloc(strlen(tnp)+strlen(hkp)+4)))
  {
   free(hkn);
   return(FALSE);
  }

 /* Build node name */
 strcpy(np,hkp);
 strcat(np," : ");
 strcat(np,tnp);

 /* Initialize node */
 hkn->hkn_Node.ln_Name=np;
 hkn->hkn_ToolNode=tn;

 /* Add node to the list */
 AddHead(&HotKeysList,(struct Node *) hkn);
 return(TRUE);
}

/* Build list of all available HotKeys */
static BOOL BuildHotKeysList(void)
{
 struct ToolNode *tn,tmtn;

 /* Initialize HotKeys list */
 NewList(&HotKeysList);

 /* Add ToolManager pop up HotKey */
 tmtn.tn_Node.ln_Name=MyName;
 tmtn.tn_HotKey=PopUpHotKey;
 if (!BuildHotKeyNode(&tmtn)) return(FALSE);

 /* Scan tool list */
 tn=GetHead(&ToolList); /* Begin of list */
 while (tn)
  {
   /* Does the tool have a HotKey? Yes, add a new HotKeyNode */
   if (tn->tn_CxObj && !BuildHotKeyNode(tn))
    {
     FreeHotKeysList();
     return(FALSE);
    }

   tn=GetSucc(tn); /* Next in list */
  }

 return(TRUE);
}

/* Create gadgets */
static BOOL CreateGadgets(void)
{
 struct NewGadget ng;
 struct Gadget *g;
 struct TextFont *f;
 UWORD topborder;
 char buf[BUFLEN];

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

 f=GfxBase->DefaultFont;                    /* System Default Font */
 ta.ta_Name=f->tf_Message.mn_Node.ln_Name;
 ta.ta_YSize=f->tf_YSize;

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

 /* Calculate window values */
 ww=50*f->tf_XSize+INTERWIDTH;

 /* 1. Gadget: ListView, HotKeys */
 ng.ng_LeftEdge=pubsc->WBorLeft+INTERWIDTH/2;
 ng.ng_TopEdge=topborder+INTERHEIGHT;
 ng.ng_Width=ww-INTERWIDTH;
 ng.ng_Height=10*f->tf_YSize+INTERHEIGHT;
 ng.ng_GadgetText=NULL;
 ng.ng_GadgetID=0;
 ng.ng_TextAttr=&ta;
 ng.ng_Flags=PLACETEXT_IN;
 ng.ng_VisualInfo=vi;
 ng.ng_UserData=0;
 if (!(lvgad=g=CreateGadget(LISTVIEW_KIND,g,&ng,
                            GTLV_Labels,&HotKeysList,
                            GTLV_ReadOnly,TRUE,
                            TAG_DONE)))
  goto cge2;

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

 /* Something went wrong... */
cge2: FreeGadgets(gl);
cge1: return(FALSE);
}

/* Open HotKeys window */
void OpenHotKeysWindow(ULONG left, ULONG top)
{

 if (hkeywinsig) return;                  /* Already opened? */

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

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

 if (!BuildHotKeysList())                 /* Build list of all HotKeys */
  goto ow3;

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

 /* Open window */
 if (!(w=OpenWindowTags(&nw,
                        WA_Left,left-INTERWIDTH,
                        WA_Top,top+20,
                        WA_InnerWidth,ww,
                        WA_InnerHeight,wh,
                        WA_RMBTrap,TRUE,
                        WA_Title,WindowTitle,
                        WA_PubScreen,pubsc,
                        WA_AutoAdjust,TRUE,
                        TAG_DONE)))
  goto ow5;

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

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

 /* Something went wrong.... */
ow5: FreeGadgets(gl);
ow4: FreeHotKeysList();
ow3: FreeVisualInfo(vi);
ow2: UnlockPubScreen(NULL,pubsc);
ow1: return;
}

/* Close HotKeys window */
void CloseHotKeysWindow(void)
{
 if (hkeywinsig)
  {
   CloseWindow(w);
   FreeGadgets(gl);
   FreeHotKeysList();
   FreeVisualInfo(vi);
   globalsigs&=~hkeywinsig;
   hkeywinsig=0;
  }
}

/* Refresh HotKeys window */
void RefreshHotKeysWindow(struct ToolNode *tn, BOOL add)
{
 /* Is the window open and has the tool a HotKey? */
 if (hkeywinsig && tn->tn_CxObj)
  {
   /* Detach HotKeys list from list view gadget */
   GT_SetGadgetAttrs(lvgad,w,NULL,GTLV_Labels,-1,TAG_DONE);

   /* Add or remove a Hotkey? */
   if (add) BuildHotKeyNode(tn); /* Add a new one */
   else
    { /* Remove an old one */
     struct HotKeyNode *hkn=GetHead(&HotKeysList);

     /* Find corresponding HotKeyNode */
     while (hkn)
      {
       if (hkn->hkn_ToolNode==tn) break; /* Found it! */

       hkn=GetSucc((struct ToolNode *) hkn); /* Next in list */
      }

     /* Remove node from list and free it */
     if (hkn) FreeHotKeyNode(hkn);
    }

   /* Attach HotKeys list to list view gadget */
   GT_SetGadgetAttrs(lvgad,w,NULL,GTLV_Labels,&HotKeysList,
                                  GTLV_Top,0,
                                  TAG_DONE);
  }
}

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

 while ((msg=GT_GetIMsg(wp)) /* && !clwin */)
  {
   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;
    }
   GT_ReplyIMsg(msg);
  }

 if (clwin) CloseHotKeysWindow();
}

