/*
 * toollist.c   V1.4
 *
 * tool list handling
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* Add one program to tool list */
BOOL AddToolNode(struct ConfigBlock *cb, BPTR fl)
{
 register struct ToolNode *tn;
 BOOL ndummy;

 /* This limitation exists because of AppAddMenuItem */
 if (ToolCount>=99) goto e1; /* Not more than 99 Tools :-) possible */

 /* Get memory for ToolNode */
 if (!(tn=malloc(sizeof(struct ToolNode))))
  goto e1;

 /* Initialize the other parameters */
 tn->tn_Type=cb->cb_Type;
 tn->tn_Flags=cb->cb_Flags;
 tn->tn_Stack=cb->cb_Stack;
 if (tn->tn_Stack<STACKMIN) tn->tn_Stack=STACKMIN; /* Sanity check */
 ndummy=tn->tn_Type!=TNTYPE_DUMMY;

 /* No alias? */
 if (cb->cb_Alias[0]=='\0')
  {
   /* Yes, copy real name and set real name to null */
   strcpy(cb->cb_Alias,cb->cb_RealName);
   if (cb->cb_Alias[0]=='\0') goto e2;   /* Empty name --> error */
   cb->cb_RealName[0]='\0';
  }

 /* Get memory for menu item name and copy it */
 if (!(tn->tn_Node.ln_Name=strdup(cb->cb_Alias)))
  goto e2;

 /* Does the program have a real name? */
 if (ndummy && (cb->cb_RealName[0]!='\0'))
  {
   /* Get memory for real program name and copy it */
   if (!(tn->tn_RealName=strdup(cb->cb_RealName)))
    goto e3;
  }
 else
  tn->tn_RealName=NULL; /* Otherwise: menu item name == real program name */

 /* Does the user want a hotkey for the tool? */
 if (ndummy && (cb->cb_HotKey[0]!='\0'))
  {
   /* Get memory for hot key string and copy it */
   if (!(tn->tn_HotKey=strdup(cb->cb_HotKey)))
    goto e4;

   /* Build the commodities object from the hot key string */
   if (!(tn->tn_CxObj=HotKey(tn->tn_HotKey,MyBrokerPort,(ULONG) tn)))
    goto e5;

   /* Attach it to to our broker */
   AttachCxObj(MyBroker,tn->tn_CxObj);
   if (CxObjError(MyBroker)) goto e6;
  }
 else
  {
   tn->tn_HotKey=NULL;
   tn->tn_CxObj=NULL;
  }

 /* If the user wants a menu, add new menu entry, ID == Address of ToolNode */
 if (tn->tn_Flags&TNFLAGS_MENU)
  {
   if (!(tn->tn_MenuItem=AddAppMenuItem((ULONG) tn,NULL,tn->tn_Node.ln_Name,
                                        MyMP,TAG_DONE)))
    goto e6;
  }
 else tn->tn_MenuItem=NULL;

 /* User supplied working directory? */
 if (ndummy && (cb->cb_WorkDir[0]!='\0'))
  {
   if (!(tn->tn_WorkDir=strdup(cb->cb_WorkDir)))
    goto e7;

   tn->tn_DirLock=Lock(tn->tn_WorkDir,ACCESS_READ);
  }
 else
  {
   tn->tn_WorkDir=NULL;
   tn->tn_DirLock=NULL;
  }

 /* Valid directory? No --> duplicate supplied DirLock */
 if (!tn->tn_DirLock && !(tn->tn_DirLock=DupLock(fl)))
  goto e8;

 /* If the user wants an icon, add new AppIcon, ID == Address of ToolNode */
 if (ndummy && (tn->tn_Flags&TNFLAGS_ICON))
  {
   BPTR oldfl;
   char *cp;

   /* Go to tools directory */
   oldfl=CurrentDir(tn->tn_DirLock);

   /* Get icon file name */
   tn->tn_IconFile=NULL;
   if (cb->cb_IconFile[0]!='\0')
    {
     if (!(cp=tn->tn_IconFile=strdup(cb->cb_IconFile)))
      goto e9;
    }
   else if (tn->tn_RealName) cp=tn->tn_RealName;
   else cp=tn->tn_Node.ln_Name;

   /* Get icon data */
   if (tn->tn_Flags&TNFLAGS_DOBJ)
    tn->tn_Icon=GetDiskObject(cp);
   else tn->tn_Icon=LoadIFFIcon(cp);

   /* Go back to old directory */
   CurrentDir(oldfl);

   /* Icon data loaded? */
   if (!tn->tn_Icon)
    goto e10;

   /* Create AppIcon */
   tn->tn_Icon->do_CurrentX=cb->cb_IconX;
   tn->tn_Icon->do_CurrentY=cb->cb_IconY;
   if (!(tn->tn_AppIcon=AddAppIcon((ULONG) tn,NULL,tn->tn_Node.ln_Name,MyMP,
                                   NULL,tn->tn_Icon,TAG_DONE)))
    goto e11;
  }
 else
  {
   tn->tn_IconFile=NULL;
   tn->tn_Icon=NULL;
   tn->tn_AppIcon=NULL;
  }

 /* Add node to tool list */
 ToolCount++;           /* Increment active tool count */
 DetachToolList();      /* Detach list from ListView gadget */
 AddTail(&ToolList,(struct Node *) tn);
 AttachToolList();      /* Attach list to ListView gadget */

 /* Node successfully added to list! */
 return(TRUE);

 /* Something went wrong.... */
e11: if (tn->tn_Icon)
      if (tn->tn_Flags&TNFLAGS_DOBJ)
       FreeDiskObject(tn->tn_Icon);
      else
       FreeIFFIcon(tn->tn_Icon);
e10:  if (tn->tn_IconFile) free(tn->tn_IconFile);
e9:  UnLock(tn->tn_DirLock);
e8:  if (tn->tn_WorkDir) free(tn->tn_WorkDir);
e7:  if (tn->tn_MenuItem) RemoveAppMenuItem(tn->tn_MenuItem);
e6:  if (tn->tn_CxObj)
      {
       DeleteCxObjAll(tn->tn_CxObj);
/*       ClearCxObjError(MyBroker); */   /* reset error flag */
      }
e5:  if (tn->tn_HotKey) free(tn->tn_HotKey);
e4:  if (tn->tn_RealName) free(tn->tn_RealName);
e3:  free(tn->tn_Node.ln_Name);
e2:  free(tn);
e1:  return(FALSE);
}

/* Scan Workbench parameters and add them to tool list */
BOOL WBAddToolNode(struct WBArg *wbarg, int numargs)
{
 struct ConfigBlock *cb;
 int i;
 BOOL rc=TRUE;
 BPTR fl;
 struct DiskObject *dobj;

 /* Get memory */
 if (!(cb=malloc(sizeof(struct ConfigBlock)))) return(rc);

 /* Init config block */
 InitConfigBlock(cb);

 for (i=numargs; i; i--,wbarg++)            /* Scan all parameters */
  /* Sanity check */
  if (wbarg->wa_Lock && wbarg->wa_Name && (strlen(wbarg->wa_Name)!=0))
   {
    /* Change to icon's directory */
    fl=CurrentDir(wbarg->wa_Lock);

    /* Get name of directory */
    if (!NameFromLock(wbarg->wa_Lock,cb->cb_WorkDir,BUFLEN))
     cb->cb_WorkDir[0]='\0'; /* No directory found */

    if (dobj=GetDiskObject(wbarg->wa_Name)) /* Get icon data */
     {
      switch (dobj->do_Type) /* Perform action depending on icon type */
       {
        case WBTOOL:    /* Icon is a Tool or */
        case WBPROJECT: /* Icon is a Project, add it as WB tool, no HotKey  */
         cb->cb_Type=TNTYPE_WB;
         strncpy(cb->cb_Alias,wbarg->wa_Name,BUFLEN-1);
         rc&=AddToolNode(cb,wbarg->wa_Lock);
         break;
        default:        /* Every other icon type is erroneous */
         rc&=FALSE;
         break;
       }
      FreeDiskObject(dobj); /* Release icon data */
     }
    else /* Can't get icon data, so we add it as a CLI tool, no HotKey */
     {
      cb->cb_Type=TNTYPE_CLI;
      strncpy(cb->cb_Alias,wbarg->wa_Name,BUFLEN-1);
      rc&=AddToolNode(cb,wbarg->wa_Lock);
     }

    CurrentDir(fl); /* Change to old directory */
   }
  else
   rc&=FALSE; /* Error: Bad Workbench parameter */

 free(cb);
 return(rc); /* Return TRUE if no error */
}

/* Remove ONE node from the tool list */
void RemToolNode(struct ToolNode *tn)
{
 Remove((struct Node *) tn);                 /* Remove node from list */

 /* Free Icon stuff */
 if (tn->tn_Flags&TNFLAGS_ICON)
  {
   if (tn->tn_AppIcon) RemoveAppIcon(tn->tn_AppIcon); /* Remove AppIcon */
   if (tn->tn_Flags&TNFLAGS_DOBJ)            /* Free icon data */
    FreeDiskObject(tn->tn_Icon);
   else
    FreeIFFIcon(tn->tn_Icon);
   if (tn->tn_IconFile) free(tn->tn_IconFile); /* Free icon file name */
  }

 if (tn->tn_WorkDir) free(tn->tn_WorkDir);   /* Free directory name */
 UnLock(tn->tn_DirLock);                     /* Free directory lock */
 if (tn->tn_MenuItem) RemoveAppMenuItem(tn->tn_MenuItem); /* Rem. menu entry */

 /* Free HotKey stuff */
 if (tn->tn_CxObj)
  {
   DeleteCxObjAll(tn->tn_CxObj);             /* Free commodities objects */
   free(tn->tn_HotKey);                      /* Free HotKey string */
  }

 if (tn->tn_RealName) free(tn->tn_RealName); /* Free memory */
 free(tn->tn_Node.ln_Name);
 free(tn);
 ToolCount--;                                /* decrement active tool count */
}

/* Remove ALL nodes from the tool list */
void RemoveTools(void)
{
 struct ToolNode *tn1,*tn2=GetHead(&ToolList); /* Begin of list */

 while (tn1=tn2)
  {
   tn2=GetSucc(tn1); /* Next in list */
   RemToolNode(tn1); /* Remove node */
  }
}
