/*********************************************************************\
**                               ________________________________    **
**    A n t h o n y             |________    __    __    ________|   **
**                                       |  |o_|  |o_|  |            **
**            T h y s s e n            __|   __    __   |__          **
**                                  __|   __|  |  |  |__   |__       **
**   `` Dragon Computing ! ''    __|   __|     |  |     |__   |__    **
**                              |_____|        |__|        |_____|   **
**                                                                   **
\*********************************************************************/
/* This program puts customized menus into the WorkBench menubar.
 * The program is split up into two parts, AMenu and AMenu-Handler.
 * This section is AMenu and it initializes and starts up a process
 * to run AMenu-Handler, and then terminates.  AMenu also terminates
 * and cleans up after the suprocess.  AMenu will parse the users
 * menus, initialize data to be passed to AMenu-Handler, and start
 * up AMenu-Handler.  AMenu-Handler does very little memory
 * allocation in order to save space, so AMenu does allocation and
 * freeing for it.
 */

#include "AMenu.h"            /* Handler Message Port definition */
#include "AllocStr.h"         /* String Allocation macros */
#include "ArpC.h"             /* Header for ArpC startup code */


struct MPort *M;              /* Externel Handler Port (Named Port) */

extern void  FreeMenus();     /* External Routines called */
extern BOOL  ParseMenus();

/*---------------------------------------------------*/


void
ExitAMenu(Str,Ret)
  char *Str;
  int Ret;
/* Print string and exit. The Arp, Graphics, and Intuition
** libraries are automatically closed by ArpC startup code
*/
{
  Puts(Str); exit(Ret);
}



void
RemoveHandler()
/* shutdown and clean up after handler */
{
  if (!M)
    return;
  Printf("Removing -- ", VERSION);
  DB( Puts(""); )
  if( M->Segment ) {
    DB( Puts("Signaling Handler to Exit - Waiting"); )
    M->Parent = (struct Task *)Process;   /* from ArpC startup code */
    M->ParentSig = AllocSignal(-1L);
    Signal( M->Handler, SIGBREAKF_CTRL_C);   /* don't advertize use of ^C */
    Wait(1 << M->ParentSig);
    FreeSignal(M->ParentSig);

    DB( Puts("Handler has reported in"); )
    switch( M->ErrorCode ) {
    case ERR_OK:
      break;
    case ERR_WBOPEN:  /* WB process still active */
      ExitAMenu("Leaving handler in place...\n", 0);
    default:           /* some strange error */
      Printf("Handler reports error (%ld)", (LONG)M->ErrorCode);
      ExitAMenu("",0);
    }

    DB( Puts("Unloading Port/Handler"); )
    RemPort( &M->Port );
    UnLoadSeg( M->Segment );
  }

    /* this is done here, not in handler... */
  DB( Puts("Freeing Menus/Port"); )
  FreeMenus();
  if( M->Port.mp_Node.ln_Name )
    FreeStr(M->Port.mp_Node.ln_Name);
  if( M->Directory )
    FreeStr(M->Directory);
  if( M->Console )
    FreeStr(M->Console);
  FreeMem(M, sizeof(struct MPort));
  ExitAMenu("Done", 0);
}


void
HandlerReport()
/* report the result from load or update of handler */
{
  switch( M->ErrorCode ) {
  case ERR_OK:
    ExitAMenu("OK", 0);
  case ERR_DIR:
    Puts("Bad Global Directory - Can't Lock\n");
    break;
  case ERR_LIB:
    Puts("Handler unable to open Libraries\n");
    break;
  default:
    Printf("Handler returned error (%ld)\n", (LONG)M->ErrorCode);
  }
  RemoveHandler();
}


void
UpdateHandler()
/* The Handler already exists so just replace the menus */
{
  Printf("Updating %s -- ", VERSION);

  DB( Puts("\nSignaling Handler for Update - Waiting"); )
  M->Parent = (struct Task *)Process;  /* from ArpC startup code */
  M->ParentSig = AllocSignal(-1L);
  Signal(M->Handler, SIGBREAKF_CTRL_D);
  Wait(1 << M->ParentSig);
  FreeSignal(M->ParentSig);
  FreeMenus();

  DB( Puts("Handler Waiting -- Updating Menus"); )
  if( ParseMenus() )
    RemoveHandler();

  DB( Puts("Signaling Handler to Continue"); )
  Signal(M->Handler, SIGBREAKF_CTRL_D);

  HandlerReport();
}


void
LoadHandler()
/* Load, Read config and Start Handler */
{
  struct Screen *Scr;
  ULONG         ILock;

  Printf("Installing %s -- ", VERSION);

  DB( Puts("\nCreating Port"); )      /* do NOT use ArpAlloc() */
  M = (struct MPort *)AllocMem( sizeof(struct MPort), MEMF_PUBLIC|MEMF_CLEAR);

  DB( Puts("Locating WB Window"); )
  Scr = (struct Screen *)OpenWorkBench();  /* this returns workbench */
  if( !Scr ) {
    FreeMem( M, sizeof(struct MPort) );
    ExitAMenu("Unable to locate Workbench screen!",24);
  }
  ILock = LockIBase(NULL);
  for( M->WBWindow=Scr->FirstWindow; M->WBWindow;
             M->WBWindow = M->WBWindow->NextWindow )
    if( M->WBWindow->Flags & WBENCHWINDOW ) break;
  UnlockIBase(ILock);
  if( !M->WBWindow ) {
    FreeMem( M, sizeof(struct MPort) );
    ExitAMenu("Unable to locate Workbench Window!",25);
  }

  if( ParseMenus() )
    RemoveHandler();

  DB( Puts("Adding Port"); )
  M->Port.mp_Flags = PA_IGNORE;
  M->Port.mp_Node.ln_Pri = 0;
  M->Port.mp_Node.ln_Type = NT_MSGPORT;
  M->Port.mp_Node.ln_Name = AllocStr(AMENU_PORT);
  AddPort(&M->Port);

  DB( Puts("Loading Handler"); )
  M->Segment = LoadPrg(AMENU_HANDLER);
  if (!M->Segment)
    M->Segment = LoadPrg(AMENU_HANDLER2);
  if (!M->Segment) {
    Printf("Can't find %s", AMENU_HANDLER);
    RemoveHandler();
  }

  DB( Puts("Starting Handler"); )
  if( !CreateProc(AMENU_HANDLER2, 0, M->Segment, DEF_STACK) ) {
    Puts("Can't Create Process!");
    RemoveHandler();
  }

    /* handshake so that we know it got started ok */
  DB( Puts("Waiting for Handler Signal"); )
  M->Parent = (struct Task *)Process; /* from ArpC startup code */
  M->ParentSig = AllocSignal(-1L);
  Wait(1 << M->ParentSig);
  FreeSignal(M->ParentSig);

  DB( Puts("Handler Signal recieved"); )
  HandlerReport();
}


/*-----------------------------------------------------------------*/



/* These globals are for ArpC the startup code used */
char *CLI_Args[2];    /* the argc array -- in line with template below */
char *CLI_Template = "Q=QUIT/s,V=VERSION/s";
char *CLI_Help     = "Amenu [QUIT] -- AMenu by Anthony Thyssen";

void
main(argc,argv)   /* called from ArpC */
  int   argc;
  char *argv[];
{
  /* the Arp library (thus Graphics and Intuition libraries) are
  ** opened in the ArpC startup code. Any CLI arguments given in
  ** the template is also parsed and placed in correct position.
  */

   /* Locate Named Port -- see if handler is running */
  M = (struct MPort *)FindPort(AMENU_PORT);

  if( CLI_Args[0] )                /* Was QUIT was given? */
    RemoveHandler();               /* no return */

  if( CLI_Args[1] )                /* Was VERSION asked for? */
    ExitAMenu(COPYRIGHT,0);        /* no return */

  if( M )
    UpdateHandler();               /* no return */

  LoadHandler();                   /* no return */

  /* should never be reached */
}

