/* Copyright ) Darin Johnson, 1989 */
/*                                 */
/* Permission is granted to use    */
/* this program and to freely copy */
/* it and/or source code as long   */
/* as these notices remain.        */
/* No charges for these copies may */
/* be made, except for handling    */
/* and distribution fees.          */

/* This is the main process for MyMenu.  This gets loaded and run in the */
/* background by MyMenu.  When started, it finishes initializing itself, */
/* and starts monitoring the WorkBench IDCMP port.  If any messages show */
/* up that we are interested in, we run them as a CLI or WorkBench       */
/* process.  We don't do any memory allocation or cleanup and leave that */
/* all to MyMenu (in order to save some space).  Communication with      */
/* MyMenu is done via a public port - never used as a port, but it holds */
/* "global" variables.                                                   */

#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <workbench/icon.h>
#include <functions.h>
#include "mymenu.h"

static char *copyright = "Copyright ) Darin Johnson, 1989";

struct IntuitionBase *IntuitionBase;

#ifdef DO_WB
struct IconBase *IconBase;	/* already defined in Manx C */
#endif

struct MMData *MM;		/* data shared with other tasks */
struct Process *MyProcess;
#ifdef DO_WB
int wb_cnt;			/* number of wb processes run */
struct MsgPort *wb_reply_port;	/* replies from terminating WB processes */
#endif

#ifdef DO_WB
  /* error messages */
struct IntuiText wb_open_msg_5 = { 3,1,JAM2,24,36,NULL,
	(UBYTE*)"Do you REALLY want to quit now?", NULL };
struct IntuiText wb_open_msg_4 = { 0,1,JAM2,7,28,NULL,
	(UBYTE*)"the program finishes after MyMenu.", &wb_open_msg_5 };
struct IntuiText wb_open_msg_3 = { 0,1,JAM2,7,20,NULL,
	(UBYTE*)"still be open.  This can cause a crash if", &wb_open_msg_4 };
struct IntuiText wb_open_msg_2 = { 0,1,JAM2,7,12,NULL,
	(UBYTE*)"A WorkBench program started by MyMenu may", &wb_open_msg_3 };
struct IntuiText wb_open_msg = { 3,1,JAM2,142,4,NULL,
	(UBYTE*)"WARNING!!", &wb_open_msg_2 };
struct IntuiText true_msg = { 0,1,JAM2,7,3,NULL,
	(UBYTE*)"Yes, quit MyMenu", NULL };
struct IntuiText false_msg = { 0,1,JAM2,7,3,NULL,
	(UBYTE*)"No! I didn't mean it", NULL };
#endif

/* returns an error to MyMenu if we get one during initialization */
error(code)
char code;
{
  MM->error_code = code;
  if (IntuitionBase)
    CloseLibrary(IntuitionBase);
#ifdef DO_WB
  if (IconBase)
    CloseLibrary(IconBase);
#endif
    /* coordinate with add_handler() in MyMenu */
  Signal(MM->parent_task, 1 << MM->parent_sig);
    /* now coordinate with remove_handler() in MyMenu */
  Wait(SIGBREAKF_CTRL_C);	/* wait for parent */
  Signal(MM->parent_task, 1 << MM->parent_sig);  
  _exit(0);
}

/* add personalized menus to menustrip */
add_menu_strip() {
  struct Menu *menu_strip;
  ULONG ilock;
  menu_strip = MM->WBWindow->MenuStrip;
  ilock = LockIBase(0L);
  ClearMenuStrip(MM->WBWindow);
  MM->prev_menu->NextMenu = MM->my_menu;
  SetMenuStrip(MM->WBWindow, menu_strip);
  UnlockIBase(ilock);
}

/* remove our personalized menus from menustrip */
del_menu_strip() {
  struct Menu *menu_strip;
  ULONG ilock;
  menu_strip = MM->WBWindow->MenuStrip;
  ilock = LockIBase(0L);
  ClearMenuStrip(MM->WBWindow);
  MM->prev_menu->NextMenu = NULL;
  SetMenuStrip(MM->WBWindow, menu_strip);
  UnlockIBase(ilock);
}

/* main program - initialize and start up monitor */
_main() {
    /* find data set up by parent */
  MM = (struct MMData *)FindPort(MYMENU_NAME);
  if (!MM)
    _exit(0);	/* some one ran us directly, bail out */

    /* finish initialization */
  MM->handler_task = FindTask(NULL);
  MyProcess = (struct Process *)MM->handler_task;
  MyProcess->pr_ConsoleTask = NULL;
  MyProcess->pr_CLI = NULL;
  MyProcess->pr_WindowPtr = (APTR)-1;	/* disable requesters for FindIt() */
  MyProcess->pr_CurrentDir = NULL;

    /* open necessary libraries */  
  IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  if (IntuitionBase == NULL)
    error(ERR_LIB);
#ifdef DO_WB
  IconBase = (struct IconBase *)OpenLibrary(ICONNAME, 0);
  if (IconBase == NULL)
    error(ERR_LIB);
#endif

  if (!MM->WBWindow)
    error(ERR_WIN);
  if (!setup_mon())
    error(ERR_MON);

  MM->error_code = ERR_OK;

    /* signal parent that we're fully weaned */
  Signal(MM->parent_task, 1 << MM->parent_sig);

  add_menu_strip();

#ifdef DO_WB
  wb_cnt = 0;
    /* create port AFTER setup_mon() so we don't get same signal */
  wb_reply_port = CreatePort(WBPORT_NAME, 0);
  NewList(&wb_reply_port->mp_MsgList);	/* is this necessary? */
#endif

restart:
    monitor();
#ifdef DO_WB
      /* see if we can leave gracefully */
      /* we don't want to terminate and then have a WB reply message */
    if ((wb_cnt > 0) && (AutoRequest(NULL,&wb_open_msg,
    			&true_msg,&false_msg,0,0,370,80)==FALSE))
    {
      MM->error_code = ERR_WB_OPEN;
      Signal(MM->parent_task, 1 << MM->parent_sig);  
      goto restart;
    }
#endif

    /* clean everything up */
  MM->error_code = ERR_OK;	/* let parent know that we finished up */
  finish_mon();

  del_menu_strip();
  CloseLibrary(IntuitionBase);
#ifdef DO_WB
  CloseLibrary(IconBase);
#endif

    /* Forbid until we terminate, so that we don't get UnLoadSeg'ed to soon */
  Forbid();

#ifdef DO_WB
  {
    register struct Message *msg;
    while ((msg=GetMsg(wb_reply_port))!=0)
      wbfree(msg);
    DeletePort(wb_reply_port);
  }
#endif

    /* signal parent that we are done */
  Signal(MM->parent_task, 1 << MM->parent_sig);  
}
