/* twmClient.c

   This module should be compiled and linked with applications that wish to
   be clients of twm when it is present in the system. Briefly, the client
   calls the function twmInit() to set up, afterwards calls PostMe() whenever
   he wishes to go to sleep, then finally calls twmCleanUP() just before
   exiting. Full details are in the prefatory comments to twm.c.
   
   Update history:
      Nov 12/87:  Forbid()/Permit() added to PostMe() and UnPostMe()
*/

#include "header/twm.h"

#define TWM_MSGSIZE ((long)sizeof(struct twmMessage))

extern VOID *CreatePort(), *FindPort();
extern VOID *GetMsg(),     *AllocMem();

struct MsgPort      *mp       = NULL;  /* reply port for our msgs    */
struct MsgPort      *twmport  = NULL;  /* points to twm's port       */
struct twmMessage   *Addmsg   = NULL;  /* TWM_ACTION_ADD message     */
struct twmMessage   *Delmsg   = NULL;  /* TWM_ACTION_DELETE message  */

int twmReady = FALSE;   /* TRUE means ports are allocated & initialized */


PostMe (clientName)
register char *clientName;
{
   /* trying not to pass junk to twm... */
   if (clientName == NULL || *clientName == '\0')
      return FALSE;
   
   /* set up our message telling twm to add its gadget   */
   Addmsg->tmName   = clientName;
   Addmsg->tmAction = TWM_ACTION_ADD;
   
   /* check we're initialized and that twm exists in systemh and send message
   */
   
   Forbid();                  /* to be on the safe side */
   
   if (!twmReady || (twmport = FindPort(PORTNAME)) == NULL)
      return FALSE;
   
   PutMsg(twmport, Addmsg);
   
   Permit();
   
   WaitPort(mp);
   
   Addmsg = GetMsg(mp);
   
   /* anything other than E_OK return code is bad news... forget about twm */
   return (Addmsg->tmAction == E_OK);
}   
   

UnPostMe ()
{
   Delmsg->tmAction = TWM_ACTION_DELETE;

   if (twmReady)
   {
      Forbid();
      
      if ((twmport = FindPort(PORTNAME)) != NULL)
         PutMsg(twmport, Delmsg);
         
      Permit();
      
      /* twm will reply the original (ADD) message before replying this 
         one if it's going to reply it at all... hence loop exit condition
      */
      if (twmport != NULL)
         do
         {
            WaitPort(mp);
         } while (GetMsg(mp) != Delmsg);
   }
}        


twmInit ()
{
   /* don't re-initialize */
   if (twmReady)
      return TRUE;
      
   /* set up our messages, allocate a port */
   if ((mp = CreatePort(NULL, 0L)) == NULL
       || (Delmsg = AllocMem(TWM_MSGSIZE, MEMF_CLEAR)) == NULL
       || (Addmsg = AllocMem(TWM_MSGSIZE, MEMF_CLEAR)) == NULL
      )
   {
      twmCleanUp();
      return FALSE;
   }
   else
   {
      Delmsg->tmMessage.mn_ReplyPort = mp;
      Addmsg->tmMessage.mn_ReplyPort = mp;
      
      Delmsg->tmMessage.mn_Node.ln_Type = NT_MESSAGE;
      Addmsg->tmMessage.mn_Node.ln_Type = NT_MESSAGE;
      
      return (twmReady = TRUE);
   }
}


twmCleanUp ()
{
   twmReady = FALSE;
   
   if (mp)        DeletePort(mp);
   if (Delmsg)    FreeMem(Delmsg, TWM_MSGSIZE);
   if (Addmsg)    FreeMem(Addmsg, TWM_MSGSIZE);
}


