/*
 * objects.c  V2.0
 *
 * TMObject managment routines
 *
 * (c) 1990-1992 Stefan Becker
 */

#include "ToolManagerLib.h"

static void *dummyfunc(void) {return(NULL);};

/* object functions arrays */
typedef struct TMObject *CreateFunc(struct TMHandle *, char *,
                                    struct TagItem *);
extern CreateFunc        CreateTMObjectExec;
extern CreateFunc        CreateTMObjectImage;
extern CreateFunc        CreateTMObjectSound;
extern CreateFunc        CreateTMObjectMenu;
extern CreateFunc        CreateTMObjectIcon;
extern CreateFunc        CreateTMObjectDock;
static CreateFunc       *CreateFuncTab[TMOBJTYPES]={CreateTMObjectExec,
                                                    CreateTMObjectImage,
                                                    CreateTMObjectSound,
                                                    CreateTMObjectMenu,
                                                    CreateTMObjectIcon,
                                                    CreateTMObjectDock};

typedef BOOL       DeleteFunc(struct TMObject *);
extern DeleteFunc  DeleteTMObjectExec;
extern DeleteFunc  DeleteTMObjectImage;
extern DeleteFunc  DeleteTMObjectSound;
extern DeleteFunc  DeleteTMObjectMenu;
extern DeleteFunc  DeleteTMObjectIcon;
extern DeleteFunc  DeleteTMObjectDock;
static DeleteFunc *DeleteFuncTab[TMOBJTYPES]={DeleteTMObjectExec,
                                              DeleteTMObjectImage,
                                              DeleteTMObjectSound,
                                              DeleteTMObjectMenu,
                                              DeleteTMObjectIcon,
                                              DeleteTMObjectDock};

typedef BOOL       ChangeFunc(struct TMHandle *, struct TMObject *,
                              struct TagItem *);
extern ChangeFunc  ChangeTMObjectExec;
/* extern ChangeFunc  ChangeTMObjectImage; */
extern ChangeFunc  ChangeTMObjectSound;
extern ChangeFunc  ChangeTMObjectMenu;
extern ChangeFunc  ChangeTMObjectIcon;
extern ChangeFunc  ChangeTMObjectDock;
static ChangeFunc *ChangeFuncTab[TMOBJTYPES]={ChangeTMObjectExec,
                                              dummyfunc,
                                              ChangeTMObjectSound,
                                              ChangeTMObjectMenu,
                                              ChangeTMObjectIcon,
                                              ChangeTMObjectDock};

typedef struct TMLink *AllocLinkFunc(struct TMObject *);
extern AllocLinkFunc   AllocLinkTMObjectExec;
extern AllocLinkFunc   AllocLinkTMObjectImage;
extern AllocLinkFunc   AllocLinkTMObjectSound;
static AllocLinkFunc  *AllocLinkFuncTab[TMOBJTYPES]={AllocLinkTMObjectExec,
                                                     AllocLinkTMObjectImage,
                                                     AllocLinkTMObjectSound,
                                                     dummyfunc,
                                                     dummyfunc,
                                                     dummyfunc};

typedef void           DeleteLinkFunc(struct TMLink *);
extern DeleteLinkFunc  DeleteLinkTMObjectMenu;
extern DeleteLinkFunc  DeleteLinkTMObjectIcon;
extern DeleteLinkFunc  DeleteLinkTMObjectDock;
static DeleteLinkFunc *DeleteLinkFuncTab[TMOBJTYPES]={dummyfunc,
                                                      dummyfunc,
                                                      dummyfunc,
                                                      DeleteLinkTMObjectMenu,
                                                      DeleteLinkTMObjectIcon,
                                                      DeleteLinkTMObjectDock};

typedef void         ActivateFunc(struct TMLink *, void *);
extern ActivateFunc  ActivateTMObjectExec;
extern ActivateFunc  ActivateTMObjectImage;
extern ActivateFunc  ActivateTMObjectSound;
extern ActivateFunc  ActivateTMObjectMenu;
extern ActivateFunc  ActivateTMObjectIcon;
extern ActivateFunc  ActivateTMObjectDock;
static ActivateFunc *ActivateFuncTab[TMOBJTYPES]={ActivateTMObjectExec,
                                                  ActivateTMObjectImage,
                                                  ActivateTMObjectSound,
                                                  ActivateTMObjectMenu,
                                                  ActivateTMObjectIcon,
                                                  ActivateTMObjectDock};

/* Allocate a TMObject structure */
struct TMObject *AllocateTMObject(ULONG size)
{
 struct TMObject *tmobj;

 /* Get memory for TMObject */
 if (tmobj=AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC)) {
  /* Init link list */
  NewList(&tmobj->tmo_Links);

  /* All OK */
  return(tmobj);
 }

 /* call failed */
 return(NULL);
}

/* Find an object by name of a specified type */
static struct TMObject *FindObjectInList(struct TMHandle *handle, char *name,
                                         UBYTE type)
{
 struct TMObject *tmobj=GetHead(&handle->tmh_ObjectLists[type]);

 /* Scan list */
 while (tmobj)
  if (strcmp(name,tmobj->tmo_Name))
   tmobj=GetSucc(tmobj);            /* Object not found --> Next object */
  else
   break;                           /* Object found --> Leave loop */

 /* return pointer to object */
 return(tmobj);
}

/* Find an object by name in a specified TMHandle */
static struct TMObject *FindObjectInTMHandle(struct TMHandle *handle,
                                             char *name)
{
 int i;
 struct TMObject *tmobj;

 /* Scan all lists in TMHandle */
 for (i=0; i<TMOBJTYPES; i++)
  if (tmobj=FindObjectInList(handle,name,i)) break; /* Object found */

 /* return pointer to object */
 return(tmobj);
}

/* Create a TMObject of the specified type */
BOOL InternalCreateTMObject(struct TMHandle *handle, char *object, ULONG type,
                            struct TagItem *tags)
{
 struct TMObject *tmobj;

 /* Call type specific create function */
 if (tmobj=(*CreateFuncTab[type])(handle,object,tags)) {
  /* Object created */
  tmobj->tmo_Type=type;
  tmobj->tmo_Name=object;

  /* Add it to the TMHandle */
  AddTail(&handle->tmh_ObjectLists[type],(struct Node *) tmobj);

  /* call succeeded */
  return(TRUE);
 }

 /* call failed */
 return(FALSE);
}

/* Delete a TMObject (NOTE: object MUST Remove() itself from list!!!) */
BOOL CallDeleteTMObject(struct TMObject *tmobj)
{
 return((*DeleteFuncTab[tmobj->tmo_Type])(tmobj));
}

/* Delete a TMObject (NOTE: object MUST Remove() itself from list!!!) */
BOOL InternalDeleteTMObject(struct TMHandle *handle, char *object)
{
 struct TMObject *tmobj;

 /* find object */
 if (tmobj=FindObjectInTMHandle(handle,object))
  /* Object found, remove delete it */
  return((*DeleteFuncTab[tmobj->tmo_Type])(tmobj));

 /* call failed */
 return(FALSE);
}

/* Change a TMObject */
BOOL InternalChangeTMObject(struct TMHandle *handle, char *object,
                            struct TagItem *tags)
{
 struct TMObject *tmobj;

 /* find object */
 if (tmobj=FindObjectInTMHandle(handle,object)){
  /* Object found */

  /* any tags specified? */
  if (tags==NULL) return(TRUE); /* call succeeded :-) */

  /* Change object */
  return((ChangeFuncTab[tmobj->tmo_Type])(handle,tmobj,tags));
 }

 /* call failed */
 return(FALSE);
}

/* Add a link to a TMObject */
struct TMLink *AddLinkTMObject(struct TMHandle *handle, char *object,
                               ULONG type, struct TMObject *linkedto)
{
 struct TMObject *tmobj;

 /* Find object of specified type */
 if (tmobj=FindObjectInList(handle,object,type)) {
  struct TMLink *tml;

  /* Allocate TMLink structure */
  if (tml=(AllocLinkFuncTab[tmobj->tmo_Type])(tmobj)) {
   /* Initialize link */
   tml->tml_Linked=tmobj;
   tml->tml_LinkedTo=linkedto;

   /* Add link to list */
   AddTail(&tmobj->tmo_Links,(struct Node *) tml);

   /* All OK */
   return(tml);
  }
 }

 /* call failed */
 return(NULL);
}

/* Remove a link to a TMObject */
void RemLinkTMObject(struct TMLink *tml)
{
 /* Remove it from list */
 Remove((struct Node *) tml);

 /* Free link structure */
 FreeMem(tml,tml->tml_Size);
}

/* Remove all links to a TMObject (updating objects this object is linked to) */
void DeleteAllLinksTMObject(struct TMObject *tmobj)
{
 struct List *l=&tmobj->tmo_Links;
 struct TMLink *tml;

 /* Scan list */
 while (tml=RemHead(l)) {
  /* Notify linkedTo object, that this link will be removed */
  (DeleteLinkFuncTab[tml->tml_LinkedTo->tmo_Type])(tml);

  /* Free link structure */
  FreeMem(tml,tml->tml_Size);
 }
}

/* Activate a TMObject */
void CallActivateTMObject(struct TMLink *tml, void *args)
{
 (ActivateFuncTab[tml->tml_Linked->tmo_Type])(tml,args);
}
