/*------------- INCLUDE FILES ----------------*/

#include "common.h"

/*-------------  DEFINES  ----------------*/

/*------------ GLOBAL STRUCTURES -------------*/

struct FileRequester *freq;

/*------------ EXTERNAL STRUCTURES -------------*/

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct ArpBase *ArpBase;
extern struct ColorBase *ColorBase;
extern struct IFFBase *IFFBase;
extern struct ILBMBase *ILBMBase;

extern struct Screen *scr;
extern struct Window *win;
extern struct ViewPort *viewport;
extern struct RastPort *rastport;
extern struct Screen *setscr;
extern struct Window *setwin;
extern struct RastPort *setrastport;
extern struct Menu Menu1;
extern struct Gadget ErrMessageGadg;
extern struct Gadget RotationX;
extern struct Gadget RotationY;
extern struct Gadget RotationZ;
extern struct Gadget EquationD;
extern struct Gadget EquationZ;

extern struct Border Border34;
extern struct IntuiText IText93;
#define BorderList Border34
#define ITextList IText93


/*------------ GLOBAL VARIABLES --------------*/

TEXT dirfile[120];
TEXT dirfile3DPL[120];
TEXT colorfile[120];
TEXT dataext[] = ".3DPL";
BOOL fnokay = FALSE;
BOOL titleon = FALSE;
STRPTR InfixEq;
AllPlotData *apd;


/*----------- EXTERNAL VARIABLES -------------*/

extern unsigned char SyntaxErr;  /* For equation input */
extern LONG plottype;	 /* How to plot the graph, see menuselect.h */


/*----------- EXTERNAL FUNCTIONS -------------*/

   /* From openclose.c */
extern VOID opendisplay(VOID);
extern VOID openlibraries(VOID);
extern VOID opendisplayset(VOID);
extern LONG loaddisplay(STRPTR);
extern LONG loadcolors(STRPTR);
extern IFFP savecolors(STRPTR);
extern VOID ChangeResolution(UBYTE);
extern VOID finishup(LONG);
   /* From plot.c */
extern VOID DrawGraph(VOID);
extern VOID DrawContour(VOID);
extern VOID SetLoresColors(VOID);
extern VOID ChangePlotParameters(struct Screen *);
   /* From funceval.c */
extern STRPTR Convert(STRPTR);
   /* From Data.c */
extern AllPlotData *AllocAllPlotData(VOID);
extern VOID Init3DPL(AllPlotData *);
extern VOID SetGadgets(struct Gadget *, AllPlotData *);
extern VOID PrintData(AllPlotData *);

VOID handleerrmessage(struct Gadget *, STRPTR);


/*----------- INTERNAL FUNCTIONS -------------*/

BOOL handlefilename(VOID)
{
STRPTR temp;

if(*(freq->fr_File) == 0)   return FALSE;  /* No filename */

dirfile[0] = 0;  /* make null string */
strcpy(dirfile, freq->fr_Dir);
TackOn(dirfile, freq->fr_File);
strcpy(dirfile3DPL, dirfile);
if(strlen(freq->fr_File) > strlen(dataext)) {  /* Filename length > ext. name */
   temp = dirfile + strlen(dirfile) - strlen(dataext);
   if(strcmp(dataext, temp) == 0) {  /* strings equal */
      *temp = 0;    /* Cut off ext. on filename, dirfile3DPL will have ext. */
   }
   else {
      strcat(dirfile3DPL, dataext);  /* add ext. */
   }
}
else {
   strcat(dirfile3DPL, dataext);  /* add ext. */
}
return TRUE;
} /* handlefilename */


VOID handletemp(code)
   UWORD code;
{
   WBenchToFront();
   printf("Menu num = %u\n", MENUNUM(code));
   printf("Item num = %u\n", ITEMNUM(code));
   printf("Sub num = %u\n\n", SUBNUM(code));
   Delay(150);   /* 3 seconds */
   WBenchToBack();

}  /* handletemp */


VOID handleproject(code)
   UWORD code;
{
   LONG err;

   switch(ITEMNUM(code)) {

      case PROJECTNEW:
	 {  /* Start block */
	 STRPTR string = ((struct StringInfo *)(EquationZ.SpecialInfo))->Buffer;

	 Init3DPL(apd);
	 SetGadgets(setwin->FirstGadget, apd);
	 InfixEq = Convert(string);
	 handleerrmessage(&EquationZ, string);
	 }  /* End block */
	 break;

      case PROJECTOPEN:
	 ScreenToFront(setscr);

	 freq->fr_Hail = "LOAD FILE";
	 freq->fr_Window = setwin;
	 if (FileRequest(freq)) {
	    fnokay = handlefilename();
	    if(fnokay) {
	       LONG submenu = SUBNUM(code);

	       if( (submenu == OPENALL) || (submenu == OPENPICTURE) ) {
		  err = loaddisplay(dirfile); /* Clears current display first */
		  if(err) {
		     printf("Error = %d\n", err);
		     opendisplay();  /* Open previous display */
		  }
	       } /* if */
	       if( (submenu == OPENALL) || (submenu == OPENSETTINGS) ) {
		  err = Read3DPL(dirfile3DPL, apd);
		  if(err) {
		     printf("Error 3DPL = %d\n", err);
		  }
		  else {
		     STRPTR string = ((struct StringInfo *)(EquationZ.SpecialInfo))->Buffer;

		     SetGadgets(setwin->FirstGadget, apd);
		     InfixEq = Convert(string);
		     handleerrmessage(&EquationZ, string);
		  }
	       } /* if */
	    } /* if */

	    /* ScreenToFront(scr);
	    ActivateWindow(win);  */
	 } /* if */
	 break;

      case PROJECTSAVE:
	 if(fnokay) {  /* filename OK */
	    LONG submenu = SUBNUM(code);

	    if( (submenu == SAVEALL) || (submenu == SAVEPICTURE) ) {
	       ShowTitle(scr, FALSE);  /* Turn off for save */
	       err = SaveBitMap(dirfile, rastport->BitMap,
				viewport->ColorMap->ColorTable, 1);
	       if(titleon)  ShowTitle(scr, TRUE);  /* Turn back on */
	       if(err == 0L) {
		  err = IffError();
		  printf("ERROR = %d\n", err);
	       } /* if */
	    } /* if */
	    if( (submenu == SAVEALL) || (submenu == SAVESETTINGS) ) {
	       err = Save3DPL(dirfile3DPL, apd);
	       if(err) {
		  printf("Error 3DPL = %d\n", err);
	       }
	    } /* if */
	 } /* if */

	 ScreenToFront(setscr);
	 ActivateWindow(setwin);
	 break;

      case PROJECTSAVEAS:
	 ScreenToFront(setscr);
	 freq->fr_Hail = "SAVE FILE";
	 freq->fr_Window = setwin;
	 if (FileRequest(freq)) {
	    fnokay = handlefilename();
	    if(fnokay) {
	       LONG submenu = SUBNUM(code);

	       if( (submenu == SAVEASALL) || (submenu == SAVEASPICTURE) ) {
		  ShowTitle(scr, FALSE);  /* Turn off for save */
	       /*
		  err = SaveBitMap(dirfile, rastport->BitMap,
				   viewport->ColorMap->ColorTable, 1);
	       */
		  err = (LONG)SaveWindowToIFF(dirfile, win);
		  if(titleon)  ShowTitle(scr, TRUE);  /* Turn back on */
		  if(err == 0L) {
		     err = IffError();
		     printf("ERROR = %d\n", err);
		  } /* if */
	       } /* if */
	       if( (submenu == SAVEASALL) || (submenu == SAVEASSETTINGS) ) {
		  err = Save3DPL(dirfile3DPL, apd);
		  if(err) {
		     printf("Error 3DPL = %d\n", err);
		  }
	       } /* if */
	    } /* if */

	 } /* if */
	 ActivateWindow(setwin);
	 break;

      case PROJECTCOLOR:
	 switch((UBYTE)SUBNUM(code)) {
	    case COLORADJUST:
	       ScreenToFront(scr);
	       ActivateWindow(win);
	       err = DoColor(NULL, scr);
	       break;
	    case COLORLOAD:
	       { /* Start block */
	       struct Window *fwin;

	       Forbid();
	       fwin = IntuitionBase->ActiveWindow;
	       Permit();
	       ScreenToFront(setscr);
	       freq->fr_Hail = "LOAD COLORS";
	       freq->fr_Window = setwin;
	       if (FileRequest(freq)) {
		  if(*(freq->fr_File) != 0) {  /* Filename specified */
		     colorfile[0] = 0;	/* make null string */
		     strcpy(colorfile, freq->fr_Dir);
		     TackOn(colorfile, freq->fr_File);
		     err = loadcolors(colorfile);
		     if(err) {
			printf("Color load error = %d\n", err);
		     }
		  } /* if */
	       } /* if */
	       if(fwin = win) {
		  ScreenToFront(scr);
		  ActivateWindow(win);
	       }
	       else {
		  ScreenToFront(setscr);
		  ActivateWindow(setwin);
	       }
	       } /* End block */
	       break;
	    case COLORSAVE:
	       ScreenToFront(setscr);
	       freq->fr_Hail = "SAVE COLORS";
	       freq->fr_Window = setwin;
	       if (FileRequest(freq)) {
		  if(*(freq->fr_File) != 0) {  /* Filename specified */
		     colorfile[0] = 0;	/* make null string */
		     strcpy(colorfile, freq->fr_Dir);
		     TackOn(colorfile, freq->fr_File);
		     err = savecolors(colorfile);
		     if(err) {
			printf("Color save error = %d\n", err);
		     }
		  } /* if */
	       } /* if */
	       ActivateWindow(setwin);
	       break;
	    default:
	       break;
	 } /* switch */
	 break;

      case PROJECTSCREEN:
	 ChangeResolution((UBYTE)SUBNUM(code));
	 ChangePlotParameters(scr);
	 break;

      case PROJECTTITLE:
	 if(SUBNUM(code) == TITLEON) {
	    ShowTitle(scr, TRUE);
	    titleon = TRUE;
	 }
	 else {
	    ShowTitle(scr, FALSE);
	    titleon = FALSE;
	 }
	 break;

      case PROJECTQUIT:
	 finishup(0L);
	 break;

      default:
	 handletemp(code);
	 break;

   }  /* switch */

}    /* handleproject */


VOID handlefunction(code)
   UWORD code;
{
   switch(ITEMNUM(code))  {
      case FUNCTIONPLOT:
	 plottype = SUBNUM(code);
	 ScreenToFront(scr);
	 ActivateWindow(win);
	 if(plottype == PLOTCONTOUR) {
	    DrawContour();
	 }
	 else {  /* PLOTNORMAL, PLOTHIDDEN, PLOTFILLED */
	    DrawGraph();
	 }
	 break;
      case FUNCTIONSETTINGS:
	 ScreenToFront(setscr);
	 ActivateWindow(setwin);
	 break;
      case FUNCTIONGRAPH:
	 ScreenToFront(scr);
	 ActivateWindow(win);
	 break;
      default:
	 handletemp(code);
	 break;
   } /* switch */
}  /* handlefunction */


VOID handletext(code)
   UWORD code;
{
   handletemp(code);
}


VOID handleerrmessage(gadget, EqBuf)
   struct Gadget *gadget;  /* The equation gadget */
   STRPTR EqBuf;  /* Pointer to equation string buffer */
{
   STRPTR ErrMessage = ErrMessageGadg.GadgetText->IText;
   WORD ErrPosition = 0;

   strcpy(ErrMessage, "                                        "); /* 40 */
   RefreshGList(&ErrMessageGadg, setwin, NULL, 1);

      /* ERROR STUFF */

      if (SyntaxErr) {
	 if (SyntaxErr == STACKUNDERFLOW)
	    strcpy(ErrMessage,"Stack underflow");
	 else if (SyntaxErr == STACKOVERFLOW)
	    strcpy(ErrMessage,"Stack overflow");
	 else if (SyntaxErr == TOOMANYCONST)
	    strcpy(ErrMessage,"Too many constants in function");
	 else {
	    ErrPosition = InfixEq - EqBuf;

	    switch (SyntaxErr) {
	       case MISPLACEDOP:
		  strcpy(ErrMessage,"Misplaced operator");
		  break;
	       case ILLEGALCHAR:
		  strcpy(ErrMessage,"Illegal character");
		  break;
	       case ILLEGALEXP:
		  strcpy(ErrMessage,"Illegal exponent");
		  break;
	       case ILLEGALFUNC:
		  strcpy(ErrMessage,"Illegal function");
		  break;
	       case MISSINGOP:
		  strcpy(ErrMessage,"Missing operator");
		  break;
	       case MISSINGOPRP:
		  strcpy(ErrMessage,"Missing operator or right parenthesis");
		  break;
	       case MISSINGLP:
		  strcpy(ErrMessage,"Missing left parenthesis");
		  break;
	       case MISSINGRP:
		  strcpy(ErrMessage,"Missing right parenthesis");
		  break;
	       case MISSINGPARM:
		  strcpy(ErrMessage,"Missing parameter");
		  break;
	       case LONEDECIMAL:
		  strcpy(ErrMessage,"Lone decimal point");
		  break;
	       case EXTRADECIMAL:
		  strcpy(ErrMessage,"Extra decimal");
		  break;
	       case EXTRAE:
		  strcpy(ErrMessage,"Extra E");
		  break;

	    } /* switch */

	 } /* else */

      } /* if */

      else {
	 strcpy(ErrMessage, "Acceptable");
      }

      ((struct StringInfo *)(gadget->SpecialInfo))->BufferPos = ErrPosition;
      RefreshGList(&ErrMessageGadg, setwin, NULL, 6);

      if(SyntaxErr)
	 ActivateGadget(gadget, setwin, NULL);  /* For correction */

} /* handleerrmessage */


VOID handleboolgadget(gadget)
   struct Gadget *gadget;
{
   STRPTR gtext;

   switch(gadget->GadgetID) {

      case SURFACE:
	 gtext = gadget->GadgetText->NextText->IText;
	 switch(apd->pi.Surface) {
	    case XANDY:
	       apd->pi.Surface = XONLY;
	       strcpy(gtext, "X Only ");
	       break;
	    case XONLY:
	       apd->pi.Surface = YONLY;
	       strcpy(gtext, "Y Only ");
	       break;
	    case YONLY:
	       apd->pi.Surface = XANDY;
	       strcpy(gtext, "X and Y");
	       break;
	    default:
	       break;
	 } /* switch */
	 RefreshGList(gadget, setwin, NULL, 1);
	 break;

      case AXESTYPE:
	 gtext = gadget->GadgetText->NextText->IText;
	 switch(apd->pi.AxesType) {
	    case AXESTYPENONE:
	       apd->pi.AxesType = AXESTYPESTAR;
	       strcpy(gtext, "Star");
	       break;
	    case AXESTYPESTAR:
	       apd->pi.AxesType = AXESTYPEBOX;
	       strcpy(gtext, "Box ");
	       break;
	    case AXESTYPEBOX:
	       apd->pi.AxesType = AXESTYPENONE;
	       strcpy(gtext, "None");
	       break;
	    default:
	       break;
	 } /* switch */
	 RefreshGList(gadget, setwin, NULL, 1);
	 break;

      case SWAPXYZ:
	 {		    /* begin block */
	 WORD tempTopEdge;

	 switch(apd->pi.RotationOrder) {
	    case ROTATEXYZ:	  /* to XZY */
			  /* New positions */
	       tempTopEdge = RotationY.TopEdge;
	       RotationY.TopEdge = RotationZ.TopEdge;
	       RotationZ.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationY.NextGadget = RotationZ.NextGadget;
	       RotationZ.NextGadget = &RotationY;
	       RotationX.NextGadget = &RotationZ;
	       break;
	    case ROTATEXZY:	  /* to YXZ */
			  /* New positions */
	       tempTopEdge = RotationX.TopEdge;
	       RotationX.TopEdge = RotationZ.TopEdge;
	       RotationZ.TopEdge = RotationY.TopEdge;
	       RotationY.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationZ.NextGadget = RotationY.NextGadget;
	       RotationY.NextGadget = &RotationX;
	       EquationD.NextGadget = &RotationY;
	       break;
	    case ROTATEYXZ:	  /* to YZX */
			  /* New positions */
	       tempTopEdge = RotationX.TopEdge;
	       RotationX.TopEdge = RotationZ.TopEdge;
	       RotationZ.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationX.NextGadget = RotationZ.NextGadget;
	       RotationZ.NextGadget = &RotationX;
	       RotationY.NextGadget = &RotationZ;
	       break;
	    case ROTATEYZX:	  /* to ZXY */
			  /* New positions */
	       tempTopEdge = RotationY.TopEdge;
	       RotationY.TopEdge = RotationX.TopEdge;
	       RotationX.TopEdge = RotationZ.TopEdge;
	       RotationZ.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationY.NextGadget = RotationX.NextGadget;
	       RotationX.NextGadget = &RotationY;
	       EquationD.NextGadget = &RotationZ;
	       break;
	    case ROTATEZXY:	  /* to ZYX */
			  /* New positions */
	       tempTopEdge = RotationX.TopEdge;
	       RotationX.TopEdge = RotationY.TopEdge;
	       RotationY.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationX.NextGadget = RotationY.NextGadget;
	       RotationY.NextGadget = &RotationX;
	       RotationZ.NextGadget = &RotationY;
	       break;
	    case ROTATEZYX:	  /* to XYZ */
			  /* New positions */
	       tempTopEdge = RotationX.TopEdge;
	       RotationX.TopEdge = RotationZ.TopEdge;
	       RotationZ.TopEdge = tempTopEdge;
			  /* Reorder gadgets in list */
	       RotationZ.NextGadget = RotationX.NextGadget;
	       RotationY.NextGadget = &RotationZ;
	       RotationX.NextGadget = &RotationY;
	       EquationD.NextGadget = &RotationX;
	       break;
	    default:
	       break;
	 } /* switch */
	 RefreshGList(&EquationD, setwin, NULL, 4);
	 apd->pi.RotationOrder = (++(apd->pi.RotationOrder)) % 6;
	 } /* end block */
	 break;

      default:
	 break;

   } /* switch */

} /* handleboolgadget */


VOID handlestringgadget(gadget, next)
   struct Gadget *gadget;
   BOOL next;
{
   STRPTR string = ((struct StringInfo *)(gadget->SpecialInfo))->Buffer;
   LONG longint = ((struct StringInfo *)(gadget->SpecialInfo))->LongInt;
   DOUBLE number;

   if( (gadget->Activation) & LONGINT ) {   /* LONGINT */

      switch(gadget->GadgetID) {
	 case ROTATIONX:
	    apd->dd.RotationX = longint;
	    break;
	 case ROTATIONY:
	    apd->dd.RotationY = longint;
	    break;
	 case ROTATIONZ:
	    apd->dd.RotationZ = longint;
	    break;
	 case ORIGINX:
	    apd->dd.OriginX = longint;
	    break;
	 case ORIGINY:
	    apd->dd.OriginY = longint;
	    break;
	 default:
	    break;
      } /* switch */

   } /* if */

   else {  /* STRINGS */

      number = atof(string);

      switch(gadget->GadgetID) {
	 case SIZINGPROJPLANE:
	    apd->dd.ProjPlane = number;
	    break;
	 case SIZINGVIEWDIST:
	    apd->dd.ViewDist = number;
	    break;
	 case SIZINGSCALE:
	    apd->dd.Scale = number;
	    break;
	 case LINESPACINGX:
	    apd->dd.LineSpacingX = number;
	    break;
	 case LINESPACINGY:
	    apd->dd.LineSpacingY = number;
	    break;
	 case PLOTSPANXMIN:
	    apd->dd.PlotXmin = number;
	    break;
	 case PLOTSPANXMAX:
	    apd->dd.PlotXmax = number;
	    break;
	 case PLOTSPANYMIN:
	    apd->dd.PlotYmin = number;
	    break;
	 case PLOTSPANYMAX:
	    apd->dd.PlotYmax = number;
	    break;
	 case PLOTPRECISIONX:
	    apd->dd.PlotPrecisionX = number;
	    break;
	 case PLOTPRECISIONY:
	    apd->dd.PlotPrecisionY = number;
	    break;
	 case AXESSPANXMIN:
	    apd->ad.AxesXmin = number;
	    break;
	 case AXESSPANXMAX:
	    apd->ad.AxesXmax = number;
	    break;
	 case AXESSPANYMIN:
	    apd->ad.AxesYmin = number;
	    break;
	 case AXESSPANYMAX:
	    apd->ad.AxesYmax = number;
	    break;
	 case AXESSPANZMIN:
	    apd->ad.AxesZmin = number;
	    break;
	 case AXESSPANZMAX:
	    apd->ad.AxesZmax = number;
	    break;
	 case AXESPRECISION:
	    apd->ad.AxesPrecision = number;
	    break;
	 case EQUATIONZ:
	    InfixEq = Convert(string);
	    strcpy(apd->ei.Equation, string);
	    handleerrmessage(gadget, string);
	    break;
	 case SETTINGSNOTE:
	    strcpy(apd->nt, string);
	    break;
	 default:
	    break;
      } /* switch */

      if(gadget->GadgetID >= SIZINGPROJPLANE) {   /* floating point */
	 gcvt(number, 10, string);
	 RefreshGList(gadget, setwin, NULL, 1);
      }

   } /* else */

   if(next == TRUE) {  /* Next gadget if switch TRUE */
      BOOL exitflag;

      do {
	 gadget = gadget->NextGadget;

	 if(gadget == NULL) {
	    exitflag = TRUE;
	 }
	 else if ( ((gadget->GadgetType) & STRGADGET) &&
		     !((gadget->Flags) & GADGDISABLED) ) {
	    ActivateGadget(gadget, setwin, NULL);
	    exitflag = TRUE;
	 }
	 else {
	    exitflag = FALSE;
	 }

      } while(exitflag == FALSE);

   } /* if */

} /* handlestringgadget */


VOID handlemenu(code)
   UWORD code;
{
   switch(MENUNUM(code)) {
      case MENUPROJECT:
	 handleproject(code);
	 break;
      case MENUFUNCTION:
	 handlefunction(code);
	 break;
      case MENUTEXT:
	 handletext(code);
	 break;
      default:
	 break;
   } /* switch */
}   /* handlemenu */


/*---------------- MAIN PROGRAM ---------------*/

VOID main()
{
   struct IntuiMessage *message;
   struct MenuItem *item;
   struct Gadget *gadget;
   struct Gadget *curgadget = NULL;
   ULONG mclass;
   UWORD menunum;

   openlibraries();
   opendisplay();
   opendisplayset();

   apd = AllocAllPlotData();
   Init3DPL(apd);
   SetGadgets(setwin->FirstGadget, apd);

   freq = ArpAllocFreq();  /* Alloc FileRequester Structure */

   PrintIText(setrastport, &ITextList, 0, 0);
   DrawBorder(setrastport, &BorderList, 0, 0);

   SetLoresColors();

   InfixEq = Convert(apd->ei.Equation);

#define CheckGadg(x) {if(x) {handlestringgadget(x, FALSE); x = NULL; }}

   FOREVER  {

      Wait( (1 << win->UserPort->mp_SigBit) | (1 << setwin->UserPort->mp_SigBit) );

      while(message = (struct IntuiMessage *) GetMsg(setwin->UserPort)) {
	 mclass = message->Class;
	 menunum = message->Code;
	 gadget = (struct Gadget *) message->IAddress;
	 ReplyMsg((struct Message *)message);

	 switch(mclass) {
	    case MENUPICK:
	       CheckGadg(curgadget);
	       while(menunum != MENUNULL) {
		  item = (struct MenuItem *)ItemAddress(&Menu1, menunum);
		  handlemenu(menunum);
		  menunum = item->NextSelect;
	       } /* while */
	       break;

	    case GADGETDOWN:
	       CheckGadg(curgadget);
	       if(gadget->GadgetType & BOOLGADGET)   /* Boolean */
		  handleboolgadget(gadget);
	       else
		  curgadget = gadget;		     /* String */
	       break;

	    case GADGETUP:    /* String */
	       handlestringgadget(gadget, TRUE);
	       break;

	    case MOUSEBUTTONS:
	    case INACTIVEWINDOW:
	       CheckGadg(curgadget);
	       break;

	    default:
	       break;

	 } /* switch */

      }  /* while */

      while(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
	 mclass = message->Class;
	 menunum = message->Code;
	 ReplyMsg((struct Message *)message);

	 switch(mclass) {
	    case MENUPICK:
	       while(menunum != MENUNULL) {
		  item = (struct MenuItem *)ItemAddress(&Menu1, menunum);
		  handlemenu(menunum);
		  menunum = item->NextSelect;
	       } /* while */
	       break;

	    default:
	       break;

	 }  /* switch */

      }  /* while */

   }  /* FOREVER */

}  /* main */
