/*
 * Econ     (C) 1993 Software Sculptors
 *              All Rights Under Copyright Reserved
 *
 * Version 1.0
 *
 * Written using SAS/C 6.3
 * Using Magic User Interface (MUI) by Stefan Stuntz
 *
 * By John M. Haubrich, Jr.
 *
 *
 * Version~ Date~~~~~~~ Comments~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * -------  ----        --------
 *    1.0   APR 16 1994 First MUI version.
 *             ;
 */

#include "common.h"
extern struct MUI_Command *RXCommands;


/*
 * GLOBAL VARIABLES ---------------------------------
 */
struct MyGlobals MG;

struct MainWindow       MAIN;
struct DataEntryWindow  DENT;

char  GL_szFault[256];


/*
 * DEFINES ------------------------------------------
 */
#define NUM_ARGS        0
//#define ARG_PUBSCREEN   0


/*
 * LIBRARY VARIABLES ---------------------------------
 */
struct DosBase       *DosBase       = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library       *DiskfontBase  = NULL;
struct Library       *GadToolsBase  = NULL;
struct GfxBase       *GfxBase       = NULL;
struct Library       *WorkbenchBase = NULL;
struct Library       *AslBase       = NULL;
struct Library       *IconBase      = NULL;
struct Library       *MUIMasterBase = NULL;
struct Library       *UtilityBase   = NULL;

#ifdef LATTICE
int CXBRK(void) { return(0); }
void __regargs __chkabort(void) { return; }
#endif


/*
 * CONSTANTS ----------------------------------------
 */
UBYTE *Main_ViewByCYCLabels[] = {
   (UBYTE *)"Name",
   (UBYTE *)"Entry Type",
   (UBYTE *)NULL
};

UBYTE *Main_OperatorNames[] = {
   "Future Value of an Investment",
   "Future Value of Regular Deposit",
   "Desired Future Value",
   "Regular W/D from an Investment",
   "Initial Investment Required",
   "Minimum Investment Required",
   "Interest Rate on an Investment",
   "x",
   "x",
   "x",
   "Loan Payment",
   "Loan Principal",
   "Loan Term",
   "Loan Interest Rate",
   "Loan Remaining Balance",
   NULL
};

// for disk write routine...
USHORT chip ImageDataMuiecon1[] =
{
   0xFFFF,0xFFFF,0xFC00,0x8A88,0xA8A8,0xA800,0x8000,0x0000,
   0x0000,0xAAA8,0x0000,0x0000,0x8440,0x0000,0x0000,0x8A00,
   0x3000,0x0000,0xC000,0x4800,0x0000,0x9401,0xCC00,0x0000,
   0x8802,0x0200,0x0000,0x8004,0x0100,0x0000,0x8008,0xC880,
   0x0000,0x8009,0xCC80,0x0000,0x8009,0xCB00,0x0000,0x8008,
   0xC800,0x0000,0x8004,0x4800,0x0000,0x8002,0x0C00,0x0000,
   0x8001,0x8200,0x0000,0x8000,0x4100,0x0000,0x8000,0x4880,
   0x0000,0x8006,0x4C80,0x0000,0x8009,0x4480,0x0000,0x8009,
   0x4C80,0x0800,0x8008,0xC880,0x0800,0x8004,0x0100,0x8800,
   0x8002,0x0200,0xF000,0x8001,0xCC00,0xF000,0x8000,0x4803,
   0xB800,0x8000,0x3003,0xD800,0x801C,0x00DF,0xF800,0xAABE,
   0xAAFF,0xF800,0xFFFF,0xFFFF,0xF800,0xFFFF,0xFFFF,0xF800,
   0xFFFF,0xFFFF,0xF800,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0400,0x0000,0x0000,0x0400,0x0002,
   0xAABF,0xFC00,0x0007,0xFFFF,0xFC00,0x001F,0xCFFF,0xFC00,
   0x001F,0x87FF,0xFC00,0x047E,0x03FF,0xFC00,0x01FC,0x01FF,
   0xFC00,0x23F8,0x00FF,0xFC00,0x37F0,0x007F,0xFC00,0x3BF0,
   0x007F,0xFC00,0x7FF0,0x04FF,0xFC00,0x7FF0,0x07FF,0xFC00,
   0x7FF8,0x07FF,0xFC00,0x7FFC,0x03FF,0xFC00,0x7FFE,0x01FF,
   0xFC00,0x7FFF,0x80FF,0xFC00,0x7FFF,0x807F,0xFC00,0x7FF9,
   0x807F,0xFC00,0x7FF0,0x807F,0xFC00,0x7FF0,0x807F,0xFC00,
   0x7FF0,0x007F,0xFC00,0x7FF8,0x00FF,0xDC00,0x7FFC,0x01FF,
   0xFC00,0x7FFE,0x03FF,0xF400,0x7FFF,0x87FF,0xB400,0x7FFF,
   0xCFFE,0x9C00,0x7FFF,0xFFFD,0xDC00,0x7FEB,0xFFAA,0xAC00,
   0x7FFF,0xFFFF,0xFC00,0x2AAA,0xAAAA,0xAC00,0x7FFF,0xFFFF,
   0xFC00,0xFFFF,0xFFFF,0xFC00,0x0000,0x0000,0x0000,0x7FFF,
   0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,
   0x7FFF,0xFFFF,0xF800,0x7FFF,0xCFFF,0xF800,0x7FFF,0xB7FF,
   0xF800,0x7FFE,0x33FF,0xF800,0x7FFD,0xFDFF,0xF800,0x7FFB,
   0xFEFF,0xF800,0x7FF7,0x377F,0xF800,0x7FF6,0xB37F,0xF800,
   0x7FF6,0xB4FF,0xF800,0x7FF7,0x37FF,0xF800,0x7FFB,0xB7FF,
   0xF800,0x7FFD,0xF3FF,0xF800,0x7FFE,0x7DFF,0xF800,0x7FFF,
   0xBEFF,0xF800,0x7FFF,0xB77F,0xF800,0x7FF9,0xB37F,0xF800,
   0x7FF6,0xBB7F,0xF800,0x7FF6,0xB37F,0xF800,0x7FF7,0x377F,
   0xF800,0x7FFB,0xFEFF,0xF800,0x7FFD,0xFDFF,0xF800,0x7FFE,
   0x33FF,0xF800,0x7FFF,0xB7FF,0xF800,0x7FFF,0xCFFF,0xF800,
   0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,
   0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x0000,
   0x0000,0x0000
};
struct Image ImageMuiecon1 =
{
   0,
   0,
   38,
   34,
   3,
   ImageDataMuiecon1,
   0x07,
   0x00,
   NULL
};
USHORT chip ImageDataMuiecon2[] =
{
   0x0000,0x0000,0x0000,0x1FFF,0xFFFF,0xFC00,0x6B3B,0xFFFF,
   0xFC00,0x7FFD,0x5540,0x0400,0x6FF8,0x0000,0x0400,0x7FC0,
   0x3000,0x0400,0x7E00,0x7800,0x0400,0x7C01,0xFC00,0x0400,
   0x7803,0xFE00,0x0400,0x4007,0xFF00,0x0400,0x000F,0xFF80,
   0x0400,0x400F,0x7F80,0x0400,0x000F,0x7B00,0x0400,0x000F,
   0xF800,0x0400,0x0007,0xF800,0x0400,0x0003,0xFC00,0x0400,
   0x0001,0xFE00,0x0400,0x0000,0x7F00,0x0400,0x0000,0x7F80,
   0x0400,0x0006,0x7F80,0x0400,0x000F,0x7F80,0x0400,0x000F,
   0x7F80,0x0400,0x000F,0xFF80,0x0400,0x0007,0xFF00,0x0400,
   0x0003,0xFE00,0x0400,0x0001,0xFC00,0x4400,0x0000,0x7800,
   0xAC00,0x0000,0x3001,0x5400,0x0000,0x0002,0x2400,0x0014,
   0x0055,0x5400,0x0000,0x0000,0x0400,0x5555,0x5555,0x5400,
   0x0000,0x0000,0x0400,0xFFFF,0xFFFF,0xFC00,0xFFFF,0xFFFF,
   0xFC00,0xF577,0x5757,0x5000,0xFFFF,0xFFFF,0xF800,0xD557,
   0xFFFF,0xF800,0xBBBF,0xFFFF,0xF800,0xD57F,0xCFFF,0xF800,
   0xABFF,0xB7FF,0xF800,0xD7FE,0x33FF,0xF800,0xA7FD,0xFDFF,
   0xF800,0xFFFB,0xFEFF,0xF800,0xFFF7,0x377F,0xF800,0xFFF6,
   0xB37F,0xF800,0xFFF6,0xB4FF,0xF800,0xFFF7,0x37FF,0xF800,
   0xFFFB,0xB7FF,0xF800,0xFFFD,0xF3FF,0xF800,0xFFFE,0x7DFF,
   0xF800,0xFFFF,0xBEFF,0xF800,0xFFFF,0xB77F,0xF800,0xFFF9,
   0xB37F,0xF800,0xFFF6,0xBB7F,0xF800,0xFFF6,0xB37F,0xF000,
   0xFFF7,0x377F,0xF800,0xFFFB,0xFEFF,0x5000,0xFFFD,0xFDFF,
   0xB800,0xFFFE,0x33FF,0x1000,0xFFFF,0xB7FE,0x0000,0xFFFF,
   0xCFFC,0x0000,0xFFE3,0xFF20,0x0000,0xD541,0x5500,0x0000,
   0x8000,0x0000,0x0000,0x8000,0x0000,0x0000,0x8000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7FFF,
   0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,
   0x7FFF,0xFFFF,0xF800,0x7FFF,0xCFFF,0xF800,0x7FFF,0xB7FF,
   0xF800,0x7FFE,0x33FF,0xF800,0x7FFD,0xFDFF,0xF800,0x7FFB,
   0xFEFF,0xF800,0x7FF7,0x377F,0xF800,0x7FF6,0xB37F,0xF800,
   0x7FF6,0xB4FF,0xF800,0x7FF7,0x37FF,0xF800,0x7FFB,0xB7FF,
   0xF800,0x7FFD,0xF3FF,0xF800,0x7FFE,0x7DFF,0xF800,0x7FFF,
   0xBEFF,0xF800,0x7FFF,0xB77F,0xF800,0x7FF9,0xB37F,0xF800,
   0x7FF6,0xBB7F,0xF800,0x7FF6,0xB37F,0xF800,0x7FF7,0x377F,
   0xF800,0x7FFB,0xFEFF,0xF800,0x7FFD,0xFDFF,0xF800,0x7FFE,
   0x33FF,0xF800,0x7FFF,0xB7FF,0xF800,0x7FFF,0xCFFF,0xF800,
   0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,
   0xF800,0x7FFF,0xFFFF,0xF800,0x7FFF,0xFFFF,0xF800,0x0000,
   0x0000,0x0000
};
struct Image ImageMuiecon2 =
{
   0,
   0,
   38,
   34,
   3,
   ImageDataMuiecon2,
   0x07,
   0x00,
   NULL
};
struct DiskObject diskobj = {
   WB_DISKMAGIC, WB_DISKVERSION,
   {
      NULL,
      0, 0, 38, 34,
      GADGIMAGE | GFLG_GADGHIMAGE,
      GADGIMMEDIATE | RELVERIFY,
      BOOLGADGET,
      (APTR)&ImageMuiecon2,
      (APTR)&ImageMuiecon1,
      NULL,
      NULL,
      NULL,
      0,
      NULL
   },
   WBPROJECT,
   "MUIEcon",
   NULL,
   NO_ICON_POSITION,
   NO_ICON_POSITION,
   NULL,
   NULL,
   8192
};


/*
 * FUNCTIONS ----------------------------------------
 */
//
// JMH_About(): show program info, basename, author, free memory, etc...
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void JMH_About( void )
{
   char  *pszVersion, *pszAuth, *pszCopyright, *pszBase, *pszDescrip;
   char   szAbout[1024];
   ULONG  ulChipFree, ulFastFree;


   get( MG.App, MUIA_Application_Version,     &pszVersion );
   get( MG.App, MUIA_Application_Author,      &pszAuth );
   get( MG.App, MUIA_Application_Copyright,   &pszCopyright );
   get( MG.App, MUIA_Application_Base,        &pszBase );
   get( MG.App, MUIA_Application_Description, &pszDescrip );

   ulChipFree = AvailMem( MEMF_CHIP );
   ulFastFree = AvailMem( MEMF_FAST );

   sprintf( szAbout, "\33c\33b%s\n\33c%s\n\33c%s\n\n\33c%s %s\n\n%s\n\n\
Graphics memory: %lu\nOther memory: %lu\n\nUsing Magic User Interface (MUI) by Stefan Stuntz",
                     pszVersion+6,
                     pszAuth,
                     pszCopyright,
                     "BASENAME:",
                     pszBase,
                     pszDescrip,
                     ulChipFree,
                     ulFastFree
          );

   MUI_Request( MG.App, NULL, 0, NULL, "*OK", szAbout, NULL );
}

//
// JMH_Error(): error routine that also provides help
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LONG JMH_Error( char *pszMsg, APTR pWindowObj, BOOL fARexx,
                char *pszHelpFile, char *pszHelpNode, LONG lHelpLine )
{
   LONG l;


   if ( fARexx )
   {
      set( MG.App, MUIA_Application_RexxMsg, pszMsg );
   }
   else
   {
redisplay:
      l = MUI_Request( MG.App, pWindowObj, 0, NULL, "*OK|Help", pszMsg, NULL );
      if ( l == 0 )
      {
         if ( pszHelpFile && pszHelpNode )
         {
            DoMethod( MG.App, MUIM_Application_ShowHelp, pWindowObj,
                      pszHelpFile, pszHelpNode, lHelpLine );
         }
         else
         {
            MUI_Request( MG.App, pWindowObj, 0, NULL, "*OK", "No help is available for this topic.", NULL );
         }
         goto redisplay;
      }
   }
   return( l );
}

//
// JMH_InitVars(): initialize variables to default values
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VOID JMH_InitVars()
{
   //
   // initialize variables...
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   GL_szFault[0] = 0;
   MG.pCCPNode   = NULL;

   //
   // init window objects to NULL
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   MG.WIN_Main      = NULL;
   MG.WIN_Dent      = NULL;

   //
   // open libraries
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   DosBase = (struct DosBase *)OpenLibrary( "dos.library", 37L );
   if ( !DosBase ) JMH_Quit("Cannot open dos.library 37+");

   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37L);
   if (!IntuitionBase) JMH_Quit("Cannot open intuition.library 37+");

   DiskfontBase = (struct Library *)OpenLibrary("diskfont.library", 37L);
   if (!DiskfontBase) JMH_Quit("Cannot open diskfont.library 37+");

   GadToolsBase = (struct Library *)OpenLibrary("gadtools.library", 37L);
   if (!GadToolsBase) JMH_Quit("Cannot open gadtools.library 37+");

   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37L);
   if (!GfxBase) JMH_Quit("Cannot open graphics.library 37+");

   WorkbenchBase = (struct Library *)
      OpenLibrary("workbench.library",37L);
   if (!WorkbenchBase) JMH_Quit("Cannot open workbench.library 37+");

   AslBase = OpenLibrary("asl.library",37L);
   if (!AslBase) JMH_Quit("Cannot open asl.library 37+");

   IconBase = (struct Library *)OpenLibrary("icon.library",37L);
   if (!IconBase) JMH_Quit("Cannot open icon.library 37+");

   UtilityBase = (struct Library *)OpenLibrary("utility.library",37L);
   if (!UtilityBase) JMH_Quit("Cannot open utility.library 37+" );

   MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN);
   if (!MUIMasterBase)
   {
      printf("Cannot open muimaster.library" );
      JMH_Quit( NULL );
   }
}

//
// JMH_Quit(): close down everything we've opened and JMH_Quit
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void JMH_Quit( char *t )
{
   char  szQuitBuf[256+20];


   if (t)
   {
      sprintf( szQuitBuf, "%s\nExiting...", t );
      MUI_Request( MG.App, NULL, 0, NULL, "*OK", szQuitBuf, NULL );
   }

   // free app object
   if ( MG.App )        MUI_DisposeObject( MG.App );

   // free disk object (icon)
   if ( MG.dobj_App )   FreeDiskObject( MG.dobj_App );

   if (MUIMasterBase)   CloseLibrary(MUIMasterBase);
   if (UtilityBase)     CloseLibrary(UtilityBase);
   if (IconBase)        CloseLibrary(IconBase);
   if (AslBase)         CloseLibrary(AslBase);
   if (WorkbenchBase)   CloseLibrary(WorkbenchBase);
   if (GfxBase)         CloseLibrary((struct Library *)GfxBase);
   if (GadToolsBase)    CloseLibrary(GadToolsBase);
   if (DiskfontBase)    CloseLibrary(DiskfontBase);
   if (IntuitionBase)   CloseLibrary((struct Library *)IntuitionBase);
   if (DosBase)         CloseLibrary((struct Library *)DosBase);

   exit(0);
}

//
// JMH_Startup(): handle arguments, setup environment, init vars/GUI...
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void JMH_Startup( int argc, char *argv[] )
{
   static char       *programname = "MUIEcon";
   static char        programpath[512];
   BPTR               tmplock;
   struct WBStartup  *WBenchMsg   = NULL;


   JMH_InitVars();

   if (argc)
   {
      GetProgramName( programpath, 512 );
   }
   else
   {
      WBenchMsg   = (struct WBStartup *)argv;
      programname = WBenchMsg->sm_ArgList->wa_Name;

      tmplock  = Lock( programname, ACCESS_READ );
      NameFromLock( tmplock, programpath, 256 );
      UnLock( tmplock );
   }

   // get real program name
   programname = FilePart( programpath );

   // try to get disk object
   MG.dobj_App = GetDiskObject( programpath );

   //
   // set up the MUI application object
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   MG.App = ApplicationObject,
      MUIA_Application_Title      , "MUIEcon",
      MUIA_Application_Version    , "$VER: MUIEcon 1.0 (15.05.94)",
      MUIA_Application_Copyright  , "(C) 1994  John M Haubrich Jr",
      MUIA_Application_Author     , "John M Haubrich Jr",
      MUIA_Application_Description, "Investment and loan calculator.",
      MUIA_Application_Base       , "MUIECON",
      MUIA_Application_DiskObject , MG.dobj_App,
      MUIA_Application_Commands   , RXCommands,
      MUIA_Application_HelpFile   , "PROGDIR:muiecon.guide",
      End;

   if ( !MG.App )
      JMH_Quit( "Failed to create Application." );
}

//
// Strip psz1 of all chars NOT in psz2
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char *JMH_CStrip( char psz1[], char *psz2 )
{
   char *rc = NULL;
   char *pNew = NULL;
   int   i;


   if ( pNew = (char *)AllocVec( strlen( psz1 ) + 1, MEMF_ANY | MEMF_CLEAR ) )
   {
      rc = pNew;
      for ( i=0; i < strlen( psz1 ); i++ )
      {
         if ( strchr( psz2, psz1[i] ) )
         {
            *pNew++ = psz1[i];
         }
      }
   }

   return( rc );
}

//
// JMH_WindowTitle(): set window title as PROGNAME: current-filespec
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void JMH_WindowTitle()
{
   static char  szWindowTitle[256];
   char        *pszTitle;


   get( MG.App, MUIA_Application_Title, &pszTitle );
   sprintf( szWindowTitle, "%s: ", pszTitle );
   strncat( szWindowTitle, MG.szProjectSpec, 256-32-1 );
   set( MG.WIN_Main, MUIA_Window_Title, szWindowTitle );
}

//
// JMH_Write(): write data with error checking; returns 0 on FAILURE
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BOOL JMH_Write( BPTR fh, APTR pRec, ULONG ulLen, BOOL fARexx )
{
   BOOL   rc = FALSE;   // assume failure
   LONG   lIoErr;
   LONG   lDiskStat;
   ULONG  ul;


writeagain:
   lDiskStat = Write( fh, pRec, ulLen );
   if ( lDiskStat != ulLen )
   {
      lIoErr = IoErr();
      if ( lIoErr == ERROR_DISK_FULL )
      {
         ul = MUI_Request( MG.App, NULL, 0, NULL,
                           "*Retry|Cancel",
                           "The information cannot be stored because\nthe storage device is full.\n\nDo you wish to retry or cancel?", NULL );
         if ( ul == 1 )
         {
            // Retry
            goto writeagain;
         }
      }
      else
      {
         Fault( lIoErr, "Disk write error!\n", GL_szFault, sizeof( GL_szFault ) );
         strcat( GL_szFault, "\n\nThe data file may be corrupt." );
         JMH_Error( GL_szFault, NULL, FALSE, "PROGDIR:muiecon.guide", "errors", 0 );
      }
   }
   else
   {
      rc = TRUE;
   }

   return( rc );
}


/**
 **   S U B R O U T I N E S  -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 **/
//
// pDataLine = MUI object of string gadget
// ubLine    = Line to check (1..5)
//
ULONG fnCheckDENT( APTR pDataLine, UBYTE ubLine, BOOL fARexx )
{
   BOOL  rc = SUCCESS;
   char *pszStat;


   if ( ( ubLine < 5 ) || ( MG.ubCurrentEntryMode == 25 ) )
   {
      // check for required entry and non-zero
      get( pDataLine, MUIA_String_Contents, &pszStat );
      if ( strcmp( pszStat, "" ) == 0 )
      {
         JMH_Error( "This field is required.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
         set( MG.WIN_Dent, MUIA_Window_ActiveObject, pDataLine );
         rc = FAILURE;
      }
   }

   // if the above checked out OK, try this...
   if ( rc == SUCCESS )
   {
      switch( ubLine )
      {
         case 1:
            switch( MG.ubCurrentEntryMode )
            {
               case 11:
               case 21:
               case 22:
               case 23:
               case 24:
               case 25:
                  get( pDataLine, MUIA_String_Contents, &pszStat );
                  if ( atof( pszStat ) == 0.0 )
                  {
                     JMH_Error( "This field cannot be zero.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
                     set( MG.WIN_Dent, MUIA_Window_ActiveObject, pDataLine );
                     rc = FAILURE;
                  }
                  break;
            }
            break;
         case 2:
            switch( MG.ubCurrentEntryMode )
            {
               case 21:
               case 22:
               case 23:
               case 24:
               case 25:
                  get( pDataLine, MUIA_String_Contents, &pszStat );
                  if ( atof( pszStat ) == 0.0 )
                  {
                     JMH_Error( "This field cannot be zero.", NULL, FALSE, "PROGDIR:muiecon.guide", "errors", 0 );
                     set( MG.WIN_Dent, MUIA_Window_ActiveObject, pDataLine );
                     rc = FAILURE;
                  }
                  break;
            }
            break;
         case 3:
            switch( MG.ubCurrentEntryMode )
            {
               case 11:
               case 12:
               case 13:
               case 14:
               case 15:
               case 16:
               case 17:
               case 24:
               case 25:
                  get( pDataLine, MUIA_String_Contents, &pszStat );
                  if ( atof( pszStat ) == 0.0 )
                  {
                     JMH_Error( "This field cannot be zero.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
                     set( MG.WIN_Dent, MUIA_Window_ActiveObject, pDataLine );
                     rc = FAILURE;
                  }
                  break;
            }
            break;
         case 4:
            switch( MG.ubCurrentEntryMode )
            {
               case 11:
               case 12:
               case 13:
               case 14:
               case 15:
               case 16:
               case 17:
               case 21:
               case 22:
               case 23:
               case 24:
               case 25:
                  get( pDataLine, MUIA_String_Contents, &pszStat );
                  if ( atof( pszStat ) == 0.0 )
                  {
                     JMH_Error( "This field cannot be zero.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
                     set( MG.WIN_Dent, MUIA_Window_ActiveObject, pDataLine );
                     rc = FAILURE;
                  }
                  break;
            }
            break;
         case 5:
            break;
      }
   }

   return( rc );
}

//
// calculate based on entries in entry window and MG.ulCurrentEntryMode
//
double fnCalculate( ULONG *pulSecondaryError )
{
   double   rc = 0.0;
   double   d1 = 0.0, d2 = 0.0, d3 = 0.0, d4 = 0.0, d5 = 0.0;
   char    *pszStat;
   LONG     lContComp;


   get( DENT.CHE_ContComp, MUIA_Selected, &lContComp );

   get( DENT.STR_DataLine1, MUIA_String_Contents, &pszStat );
   d1 = atof( pszStat );
   get( DENT.STR_DataLine2, MUIA_String_Contents, &pszStat );
   d2 = atof( pszStat );
   get( DENT.STR_DataLine3, MUIA_String_Contents, &pszStat );
   d3 = atof( pszStat );
   get( DENT.STR_DataLine4, MUIA_String_Contents, &pszStat );
   d4 = atof( pszStat );
   get( DENT.STR_DataLine5, MUIA_String_Contents, &pszStat );
   d5 = atof( pszStat );
   switch( MG.ubCurrentEntryMode )
   {
      case 11:
         switch( lContComp )
         {
            case 1:
               {
                  double  dInitial, dAPR, dCompPeriods, dNumYears;
                  double  dPercentPerPeriod;
                  LONG    lNumPeriods;


                  dInitial     = d1;
                  dAPR         = d2;
                  dCompPeriods = d3;
                  dNumYears    = d4;

                  lNumPeriods = (LONG)( dCompPeriods * dNumYears );
                  dPercentPerPeriod = dAPR / ( dCompPeriods == 0.0 ? 1 : dCompPeriods );
                  dPercentPerPeriod /= 100;
                  rc = dInitial * p_to_f( dPercentPerPeriod, (double)lNumPeriods );
               }
               break;
            case 0:
               {
                  double  dInitial, dAPR, dCompPeriods, dNumYears;
                  double  dPercentPerPeriod;
                  LONG    lNumPeriods;


                  dInitial     = d1;
                  dAPR         = d2;
                  dCompPeriods = d3;
                  dNumYears    = d4;

                  lNumPeriods = (LONG)( dCompPeriods * dNumYears );
                  dPercentPerPeriod = dAPR / ( dCompPeriods == 0.0 ? 1 : dCompPeriods );
                  dPercentPerPeriod /= 100;
                  rc = dInitial * p_to_f_c( dPercentPerPeriod, (double)lNumPeriods );
               }
               break;
         }
         break;
      case 12:
         switch( lContComp )
         {
            case 1:
               {
                  double  dRegDeposit, dAPR, dDepPerYear, dNumYears;
                  double  dAPRPerPeriod;
                  double  dNumPeriods;


                  dRegDeposit  = d1;
                  dAPR         = d2;
                  dDepPerYear  = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dDepPerYear;
                  dNumPeriods = dDepPerYear * dNumYears;

                  rc = dRegDeposit * a_to_f( dAPRPerPeriod, dNumPeriods );
               }
               break;
            case 0:
               {
                  double  dRegDeposit, dAPR, dDepPerYear, dNumYears;
                  double  dAPRPerPeriod;
                  double  dNumPeriods;


                  dRegDeposit  = d1;
                  dAPR         = d2;
                  dDepPerYear  = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dDepPerYear;
                  dNumPeriods = dDepPerYear * dNumYears;

                  rc = dRegDeposit * a_to_f_c( dAPRPerPeriod, dNumPeriods );
               }
               break;
            }
         break;
      case 13:
         switch( lContComp )
         {
            case 1:
               {
                  double  dDesiredVal, dAPR, dDepPerYear, dNumYears;
                  double  dAPRPerPeriod;


                  dDesiredVal  = d1;
                  dAPR         = d2;
                  dDepPerYear  = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dDepPerYear;

                  rc = dDesiredVal * f_to_a( dAPRPerPeriod, dDepPerYear*dNumYears );
               }
               break;
            case 0:
               {
                  double  dDesiredVal, dAPR, dDepPerYear, dNumYears;
                  double  dAPRPerPeriod;


                  dDesiredVal  = d1;
                  dAPR         = d2;
                  dDepPerYear  = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dDepPerYear;

                  rc = dDesiredVal * f_to_a_c( dAPRPerPeriod, dDepPerYear*dNumYears );
               }
               break;
         }
         break;
      case 14:
         switch( lContComp )
         {
            case 1:
               {
                  double  dInitial, dAPR, dWDPerYear, dNumYears;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dInitial   = d1;
                  dAPR       = d2;
                  dWDPerYear = d3;
                  dNumYears  = d4;

                  dAPR /= 100;
                  ulNumPeriods = (ULONG)( dWDPerYear * dNumYears );
                  dAPRPerPeriod = dAPR / dWDPerYear;
                  rc = dInitial * p_to_a( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
            case 0:
               {
                  double  dInitial, dAPR, dWDPerYear, dNumYears;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dInitial   = d1;
                  dAPR       = d2;
                  dWDPerYear = d3;
                  dNumYears  = d4;

                  dAPR /= 100;
                  ulNumPeriods = (ULONG)( dWDPerYear * dNumYears );
                  dAPRPerPeriod = dAPR / dWDPerYear;
                  rc = dInitial * p_to_a_c( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
         }
         break;
      case 15:
         switch( lContComp )
         {
            case 1:
               {
                  double  dDesiredVal, dAPR, dPeriods, dNumYears;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dDesiredVal  = d1;
                  dAPR         = d2;
                  dPeriods     = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dPeriods;
                  ulNumPeriods = (ULONG)( dPeriods * dNumYears );

                  rc = dDesiredVal * f_to_p( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
            case 0:
               {
                  double  dDesiredVal, dAPR, dPeriods, dNumYears;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dDesiredVal  = d1;
                  dAPR         = d2;
                  dPeriods     = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dPeriods;
                  ulNumPeriods = (ULONG)( dPeriods * dNumYears );

                  rc = dDesiredVal * f_to_p_c( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
         }
         break;
      case 16:
         switch( lContComp )
         {
            case 1:
               {
                  double  dRegWD, dAPR, dWDPerYear, dNumYears;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dRegWD       = d1;
                  dAPR         = d2;
                  dWDPerYear   = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dWDPerYear;
                  ulNumPeriods = (ULONG)( dWDPerYear * dNumYears );

                  rc = dRegWD * a_to_f( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
            case 0:
               {
                  double  dRegWD, dAPR, dWDPerYear, dNumYears;
                  double  dAPRPerPeriod, rc;
                  ULONG   ulNumPeriods;


                  dRegWD       = d1;
                  dAPR         = d2;
                  dWDPerYear   = d3;
                  dNumYears    = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dWDPerYear;
                  ulNumPeriods = (ULONG)( dWDPerYear * dNumYears );

                  rc = dRegWD * a_to_f_c( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
         }
         break;
      case 17:
         switch( lContComp )
         {
            case 1:
               {
                  //
                  // equation: p_to_f
                  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  // pres * (1+i)**n = fut
                  //
                  // (1+i)**n = fut/pres
                  //
                  // 1+i = (fut/pres)**(1/n)
                  //
                  // i = (fut/pres)**(1/n) - 1;
                  //
                  double  dInitial, dDesiredVal, dDepPerYear, dNumYears;
                  ULONG   ulNumPeriods;


                  dInitial     = d1;
                  dDesiredVal  = d2;
                  dDepPerYear  = d3;
                  dNumYears    = d4;

                  ulNumPeriods = (ULONG)( dDepPerYear * dNumYears );
                  rc = ( pow( dDesiredVal/dInitial, 1.0/(double)ulNumPeriods) - 1.0);
                  rc *= ulNumPeriods;    // equation gives percent PER PERIOD!!!
                  rc *= 100.0;           // change back to percentage
               }
               break;
            case 0:
               break;
         }
         break;
      case 21:
         switch( lContComp )
         {
            case 1:
               {
                  double  dPrin, dNumYears, dAPR, dNumPayPerYr;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dPrin        = d1;
                  dNumYears    = d2;
                  dAPR         = d3;
                  dNumPayPerYr = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dNumPayPerYr;
                  ulNumPeriods = (ULONG)( dNumPayPerYr * dNumYears );

                  rc = dPrin * p_to_a( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
            case 0:
               {
                  double  dPrin, dNumYears, dAPR, dNumPayPerYr;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dPrin        = d1;
                  dNumYears    = d2;
                  dAPR         = d3;
                  dNumPayPerYr = d4;

                  dAPR /= 100;
                  dAPRPerPeriod = dAPR / dNumPayPerYr;
                  ulNumPeriods = (ULONG)( dNumPayPerYr * dNumYears );

                  rc = dPrin * p_to_a_c( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
         }
         break;
      case 22:
         switch( lContComp )
         {
            case 1:
               {
                  double  dRegPymt, dNumYears, dAPR, dNumPymtPerYr;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dRegPymt      = d1;
                  dNumYears     = d2;
                  dAPR          = d3;
                  dNumPymtPerYr = d4;

                  dAPR /= 100;
                  ulNumPeriods = (ULONG)( dNumYears * dNumPymtPerYr );
                  dAPRPerPeriod = dAPR / dNumPymtPerYr;

                  rc = dRegPymt * a_to_p( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
            case 0:
               {
                  double  dRegPymt, dNumYears, dAPR, dNumPymtPerYr;
                  double  dAPRPerPeriod;
                  ULONG   ulNumPeriods;


                  dRegPymt      = d1;
                  dNumYears     = d2;
                  dAPR          = d3;
                  dNumPymtPerYr = d4;

                  dAPR /= 100;
                  ulNumPeriods = (ULONG)( dNumYears * dNumPymtPerYr );
                  dAPRPerPeriod = dAPR / dNumPymtPerYr;

                  rc = dRegPymt * a_to_p( dAPRPerPeriod, (double)ulNumPeriods );
               }
               break;
         }
         break;
      case 23:
         switch( lContComp )
         {
            case 1:
               {
                  double  dRegPymt, dPrin, dAPR, dNumPymtPerYr;
                  double  dAPRPerPeriod, dTotal;
                  ULONG   ulNumPeriods, ulPeriodsPerYr;


                  dRegPymt      = d1;
                  dPrin         = d2;
                  dAPR          = d3;
                  dNumPymtPerYr = d4;

                  dAPR /= 100;
                  ulPeriodsPerYr = (ULONG)dNumPymtPerYr;
                  dTotal = dPrin;

                  dAPRPerPeriod = 1 + ( dAPR / dNumPymtPerYr );
                  ulNumPeriods = 0;

                  //
                  // find total with interest...
                  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  while ( dTotal > 0.0 )
                  {
                     dTotal -= dRegPymt;
                     dTotal = ( dTotal * dAPRPerPeriod );
                     ulNumPeriods++;
                  }

                  rc = (double)ulNumPeriods;
               }
               break;
            case 0:
               break;
         }
         break;
      case 24:
         switch( lContComp )
         {
            case 1:
               {
                  //
                  // equation: p_to_a
                  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  // i*((1+i)**n)    present_value
                  // ------------ = ---------------
                  // (1+i)**n - 1       annuity
                  //
                  double  dRegPymt, dPrin, dNumYears, dNumPymtPerYr;
                  double  dPA;                     // PresentValue to Annuity ratio
                  double  dHi, dLo, dTry;          // interpolation vars
                  double  dp, dl;                  // loop vars
                  ULONG   ulNumPeriods;


                  dRegPymt      = d1;
                  dPrin         = d2;
                  dNumYears     = d3;
                  dNumPymtPerYr = d4;

                  ulNumPeriods = (ULONG)( dNumYears * dNumPymtPerYr );
                  dPA = dPrin / dRegPymt;

                  dHi=1.0; dLo=0.0;
                  while ( (dHi*100 - dLo*100) > 0.01 )
                  {
                     dTry = (dHi + dLo)/2.0;
                     dp = pow( 1+dTry, (double)ulNumPeriods );
                     dl = (dp-1)/(dTry*dp);
                     if ( abs(dl*100 - dPA*100) <= 0.01 ) break;
                     else if ( dl < dPA ) dHi = dTry;
                     else if ( dl > dPA ) dLo = dTry;
                  }
                  rc = dTry;
                  rc *= ulNumPeriods;    // equation gives interest PER PERIOD!!!
                  rc *= 100;             // gives us ##.##% value
               }
               break;
            case 0:
               break;
         }
         break;
      case 25:
         switch( lContComp )
         {
            case 1:
               {
                  double  dRegPymt, dInitial, dNumPymtMade, dAPR, dNumPymtPerYr;
                  double  dAPRPerPeriod, dTotal;
                  ULONG   ulPeriodsMade, ul;
                  BOOL    fError = FALSE;


                  dRegPymt      = d1;
                  dInitial      = d2;
                  dNumPymtMade  = d3;
                  dAPR          = d4;
                  dNumPymtPerYr = d5;

                  dAPR /= 100;
                  ulPeriodsMade = (ULONG)dNumPymtMade;
                  dTotal = dInitial;
                  dAPRPerPeriod = 1 + ( dAPR / dNumPymtPerYr );

                  //
                  // find the answer, dude...
                  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  for ( ul=0; ul < ulPeriodsMade; ul++ )
                  {
                     dTotal = ( dTotal * dAPRPerPeriod );
                     dTotal -= dRegPymt;
                     if ( dTotal <= 0.0 )
                     {
                        rc = dTotal;
                        *pulSecondaryError = ul;
                        break;
                     }
                  }
                  if ( fError == FALSE )
                  {
                     rc = dTotal;
                  }
               }
               break;
            case 0:
               break;
         }
         break;
   }

   return( rc );
}

LONG fnDoCalculation( BOOL fARexx, BOOL fInsertItem )
{
   LONG   rc = RETURN_OK;     // default to OK...
   ULONG  ulStat = 0;
   char   szBuf[256], szBuf2[50];
   char  *pszStat;


   if ( fnCheckDENT( DENT.STR_DataLine1, 1, fARexx ) == SUCCESS )
      if ( fnCheckDENT( DENT.STR_DataLine2, 2, fARexx ) == SUCCESS )
         if ( fnCheckDENT( DENT.STR_DataLine3, 3, fARexx ) == SUCCESS )
            if ( fnCheckDENT( DENT.STR_DataLine4, 4, fARexx ) == SUCCESS )
               if ( fnCheckDENT( DENT.STR_DataLine5, 5, fARexx ) == SUCCESS )
               {
                  double  d;


                  d = fnCalculate( &ulStat );
                  if ( d < 0.0 )
                  {
                     // get secondary result
                     sprintf( szBuf, "Loan will be paid off after only %lu payments!", ulStat );

                     if ( fARexx )
                     {
                        set( MG.App, MUIA_Application_RexxString, szBuf );
                        rc = RETURN_ERROR;
                     }
                     else
                     {
                        MUI_Request( MG.App, MG.WIN_Main, 0, NULL, "*OK", szBuf, NULL );
                     }
                  }
                  else
                  {
                     get( DENT.STR_Name, MUIA_String_Contents, &pszStat );
                     if ( *pszStat == NULL )
                     {
                        pszStat = "Unnamed";
                     }
                     get( DENT.CHE_ContComp, MUIA_Selected, &ulStat );
                     sprintf( szBuf, "%c", ( ulStat ? 2 : 1 ) );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 11:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 12:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 13:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 14:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 15:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 16:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 17:    sprintf( szBuf2, "%s%c%.4f%c%c", pszStat, 255, d, '%', 255 );   break;
                        case 21:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 22:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                        case 23:    sprintf( szBuf2, "%s%c%.4f yrs%c", pszStat, 255, d, 255 );   break;
                        case 24:    sprintf( szBuf2, "%s%c%.4f%c%c", pszStat, 255, d, '%', 255 );   break;
                        case 25:    sprintf( szBuf2, "%s%c$%.2f%c", pszStat, 255, d, 255 );   break;
                     }
                     strcat( szBuf, szBuf2 );

                     get( DENT.STR_DataLine1, MUIA_String_Contents, &pszStat );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 11:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 12:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 13:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 14:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 15:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 16:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 17:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 21:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 22:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 23:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 24:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 25:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                     }
                     strcat( szBuf, szBuf2 );
                     get( DENT.STR_DataLine2, MUIA_String_Contents, &pszStat );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 11:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 12:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 13:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 14:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 15:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 16:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 17:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 21:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 22:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 23:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 24:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 25:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                     }
                     strcat( szBuf, szBuf2 );
                     get( DENT.STR_DataLine3, MUIA_String_Contents, &pszStat );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 11:    sprintf( szBuf2, "%s per/yr%c", pszStat, 255 );   break;
                        case 12:    sprintf( szBuf2, "%s dep/yr%c", pszStat, 255 );   break;
                        case 13:    sprintf( szBuf2, "%s dep/yr%c", pszStat, 255 );   break;
                        case 14:    sprintf( szBuf2, "%s wd/yr%c", pszStat, 255 );   break;
                        case 15:    sprintf( szBuf2, "%s per/yr%c", pszStat, 255 );   break;
                        case 16:    sprintf( szBuf2, "%s wd/yr%c", pszStat, 255 );   break;
                        case 17:    sprintf( szBuf2, "%s per/yr%c", pszStat, 255 );   break;
                        case 21:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 22:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 23:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                        case 24:    sprintf( szBuf2, "$%s%c", pszStat, 255 );   break;
                        case 25:    sprintf( szBuf2, "%s%c%c", pszStat, '%', 255 );   break;
                     }
                     strcat( szBuf, szBuf2 );
                     get( DENT.STR_DataLine4, MUIA_String_Contents, &pszStat );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 11:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 12:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 13:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 14:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 15:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 16:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 17:    sprintf( szBuf2, "%s yrs%c", pszStat, 255 );   break;
                        case 21:    sprintf( szBuf2, "%s pymt/yr%c", pszStat, 255 );   break;
                        case 22:    sprintf( szBuf2, "%s pymt/yr%c", pszStat, 255 );   break;
                        case 23:    sprintf( szBuf2, "%s pymt/yr%c", pszStat, 255 );   break;
                        case 24:    sprintf( szBuf2, "%s pymt/yr%c", pszStat, 255 );   break;
                        case 25:    sprintf( szBuf2, "%s pymt/yr%c", pszStat, 255 );   break;
                     }
                     strcat( szBuf, szBuf2 );
                     get( DENT.STR_DataLine5, MUIA_String_Contents, &pszStat );
                     switch( MG.ubCurrentEntryMode )
                     {
                        case 25:    sprintf( szBuf2, "%s pymts%c", pszStat, 255 );   break;
                        default:    sprintf( szBuf2, "%c", 255 );                    break;
                     }
                     strcat( szBuf, szBuf2 );

                     if ( fInsertItem )
                     {
                        if ( MG.fReplacementMode )
                        {
                           DoMethod( MAIN.LIS_EditList, MUIM_List_Remove, MUIV_List_Remove_Active );
                        }
                        DoMethod( MAIN.LIS_EditList, MUIM_List_InsertSingle, &szBuf, MUIV_List_Insert_Sorted );
                     }
                  }

                  if ( !fARexx )
                     fnDestructDentWindow( ENDWINDOW_OK );
               }

   return( rc );
}

ULONG fnPrint( ULONG ulPrintWhich, BOOL fARexx )
{
   ULONG  rc = RETURN_OK;     // assume ARexx success...
   LONG   lStat;
   BPTR   fhPRT = NULL;

   struct LVNode *pLVNode = NULL;


   switch( ulPrintWhich )
   {
      case 0:
         break;
      case 1:     // Print ALL
         fhPRT = Open( "PRT:", MODE_NEWFILE );
         if ( fhPRT )
         {
            static char   szPrintBuf[512];
            ULONG         ul, ulLow = 0, ulHigh;


            get( MAIN.LIS_EditList, MUIA_List_Entries, &ulHigh );
            for ( ul = ulLow; ul < ulHigh; ul++ )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, ul, &pLVNode );
               if ( pLVNode )
               {
                  sprintf( szPrintBuf, "%s   %s\n     Result = %s\n     %s     %s\n     %s     %s\n     %s\n\n",
                           pLVNode->pszName,
                           Main_OperatorNames[ pLVNode->ubDataEntryMode ],
                           pLVNode->pszResult,
                           pLVNode->pszText1,
                           pLVNode->pszText2,
                           pLVNode->pszText3,
                           pLVNode->pszText4,
                           ( ( pLVNode->pszText5 == NULL ) ? "" : pLVNode->pszText5 )
                         );
                  if ( JMH_Write( fhPRT, szPrintBuf, strlen( szPrintBuf ), fARexx ) == FALSE )
                  {
                     break;
                  }
               }
            }
            Close( fhPRT );
         }
         else
         {
            JMH_Error( "Cannot access printer.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
            rc = RETURN_ERROR;
         }
         break;
      case 2:     // Print SELECTED item(s)
         fhPRT = Open( "PRT:", MODE_NEWFILE );
         if ( fhPRT )
         {
            static char   szPrintBuf[512];


            lStat = -1;
            DoMethod( MAIN.LIS_EditList, MUIM_List_NextSelected, &lStat );
            while ( lStat != -1 )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, lStat, &pLVNode );
               if ( pLVNode )
               {
                  sprintf( szPrintBuf, "%s   %s\n     Result = %s\n     %s     %s\n     %s     %s\n     %s\n\n",
                           pLVNode->pszName,
                           Main_OperatorNames[ pLVNode->ubDataEntryMode ],
                           pLVNode->pszResult,
                           pLVNode->pszText1,
                           pLVNode->pszText2,
                           pLVNode->pszText3,
                           pLVNode->pszText4,
                           ( ( pLVNode->pszText5 == NULL ) ? "" : pLVNode->pszText5 )
                         );
                  if ( JMH_Write( fhPRT, szPrintBuf, strlen( szPrintBuf ), fARexx ) == FALSE )
                  {
                     break;
                  }
               }
               DoMethod( MAIN.LIS_EditList, MUIM_List_NextSelected, &lStat );
            }
            Close( fhPRT );
         }
         else
         {
            JMH_Error( "Cannot access printer.", NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
            rc = RETURN_ERROR;
         }
         break;
   }

   return( rc );
}

ULONG fnPrintAs( BOOL fARexx )
{
   ULONG  rc = RETURN_OK;     // assume ARexx success...
   LONG   lStat;


   set( MG.App, MUIA_Application_Sleep, TRUE );
   lStat = SystemTags( "SYS:Prefs/Printer", SYS_Asynch, FALSE, TAG_DONE, TAG_DONE );
   if ( lStat != 0 )
   {
      if ( lStat > 0 )
         Fault( IoErr(),
                "Cannot launch Printer Preferences tool because",
                GL_szFault,
                sizeof( GL_szFault ) );
      else
         strcpy( GL_szFault, "Unable to launch Printer Preferences tool!" );

      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      rc = RETURN_ERROR;
   }
   set( MG.App, MUIA_Application_Sleep, FALSE );

   return( rc );
}

ULONG fnReadData( char *pszFile, BOOL fARexx )
{
   char   pszBuf[256];
   UBYTE  ubRecordSize;
   LONG   lDiskStat;
   char   szBuf[100];
   BPTR   fh = NULL;
   char   szPathPart[ FMSIZE+1 ], szFilePart[ FMSIZE+1 ], *psz;

   struct Window        *pWindow = NULL;
   struct FileRequester *pFReq   = NULL;


   if ( !pszFile )
   {
      get( MG.WIN_Main, MUIA_Window , &pWindow );
      if ( pFReq = MUI_AllocAslRequestTags( ASL_FileRequest, TAG_DONE ) )
      {
         strcpy( szPathPart, MG.szProjectSpec );
         psz = FilePart( szPathPart );
         if ( psz )
         {
            strcpy( szFilePart, psz );
            *psz = 0;
         }
         else
         {
            strcpy( szFilePart, "" );
         }

         if ( MUI_AslRequestTags( pFReq,
                                  ASLFR_Window         , pWindow,
                                  ASLFR_PrivateIDCMP   , TRUE,
                                  ASLFR_TitleText      , "Open MUIEcon File",
                                  ASLFR_InitialDrawer  , szPathPart,
                                  ASLFR_InitialFile    , szFilePart,
                                  TAG_DONE ) )
         {
            // set the new contents for our string gadget
            memset( MG.szProjectSpec, 0, sizeof( MG.szProjectSpec ) );
            strncpy( MG.szProjectSpec, pFReq->fr_Drawer, sizeof( MG.szProjectSpec )-1 );
            AddPart( MG.szProjectSpec, pFReq->fr_File,   sizeof( MG.szProjectSpec )-1 );
         }
         else
         {
            MUI_FreeAslRequest( pFReq );
            return( FALSE );
         }

         MUI_FreeAslRequest( pFReq );
      }
   }
   else
   {
      strcpy( MG.szProjectSpec, pszFile );
   }

   JMH_WindowTitle();

   fh = Open( MG.szProjectSpec, MODE_OLDFILE );
   if ( !fh )
   {
      Fault( IoErr(), "File open error!\n", GL_szFault, sizeof( GL_szFault ) );
      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      return( RETURN_ERROR );
   }

   //
   // we got the file open... now let's verify that it's one of ours...
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lDiskStat = Read( fh, szBuf, strlen( FILEID_HEADER ) );
   if ( lDiskStat != strlen( FILEID_HEADER ) )
   {
      Fault( IoErr(), "Disk read error!\n", GL_szFault, sizeof( GL_szFault ) );
      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      Close( fh );
      return( RETURN_ERROR );
   }
   szBuf[ strlen( FILEID_HEADER ) ] = 0;
   if ( strcmp( szBuf, FILEID_HEADER ) )
   {
      Fault( IoErr(), "Disk read error!\n", GL_szFault, sizeof( GL_szFault ) );
      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      Close( fh );
      return( RETURN_ERROR );
   }

   //
   // ok, read the file into memory...
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   DoMethod( MAIN.LIS_EditList, MUIM_List_Clear, TRUE );
   set( MG.App, MUIA_Application_Sleep, TRUE );

   lDiskStat = Read( fh, pszBuf, 2 );
   if ( lDiskStat != 2 )
   {
      Fault( IoErr(), "Disk read error!\n", GL_szFault, sizeof( GL_szFault ) );
      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      Close( fh );
      set( MG.App, MUIA_Application_Sleep, FALSE );
      return( RETURN_ERROR );
   }

   ubRecordSize = *pszBuf;
   set( MAIN.LIS_EditList, MUIA_List_Quiet, TRUE );
   while ( ubRecordSize != 0 )
   {
      MG.ubCurrentEntryMode = *(pszBuf+1);

      lDiskStat = Read( fh, pszBuf, ubRecordSize-2 );
      if ( lDiskStat != ubRecordSize-2 )
      {
         Fault( IoErr(), "Disk read error!\n", GL_szFault, sizeof( GL_szFault ) );
         JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
         Close( fh );
         set( MG.App, MUIA_Application_Sleep, FALSE );
         set( MAIN.LIS_EditList, MUIA_List_Quiet, FALSE );
         return( RETURN_ERROR );
      }
      *( pszBuf + ( ubRecordSize-2 ) ) = 0;

      DoMethod( MAIN.LIS_EditList, MUIM_List_InsertSingle,
                (char *)&pszBuf, MUIV_List_Insert_Sorted );

      lDiskStat = Read( fh, pszBuf, 2 );
      if ( lDiskStat == 0 )
      {
         // END OF FILE -- BREAK THE LOOP
         ubRecordSize = 0;
         break;
      }
      else if ( lDiskStat != 2 )
      {
         Fault( IoErr(), "Disk read error!\n", GL_szFault, sizeof( GL_szFault ) );
         JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
         Close( fh );
         set( MG.App, MUIA_Application_Sleep, FALSE );
         set( MAIN.LIS_EditList, MUIA_List_Quiet, FALSE );
         return( RETURN_ERROR );
      }
      ubRecordSize = *pszBuf;
   }
   set( MAIN.LIS_EditList, MUIA_List_Quiet, FALSE );

   Close( fh );
   set( MG.App, MUIA_Application_Sleep, FALSE );
   return( RETURN_OK );
}

ULONG fnWriteData( BOOL fPopupFReq, BOOL fARexx )
{
   ULONG  rc = RETURN_OK;   // assume ARexx success

   char   szBuf[100];
   ULONG  ul, ulStat;
   BPTR   fh = NULL;
   char   szPathPart[ FMSIZE+1 ], szFilePart[ FMSIZE+1 ], *psz;

   struct Window        *pWindow = NULL;
   struct FileRequester *pFReq   = NULL;
   struct LVNode        *pLVNode = NULL;
   struct DiskObject    *pDObj   = NULL;


   if ( ( fPopupFReq ) || ( strcmp( MG.szProjectSpec, "" ) == 0 ) )
   {
      get( MG.WIN_Main, MUIA_Window , &pWindow );
      if ( pFReq = MUI_AllocAslRequestTags( ASL_FileRequest, TAG_DONE ) )
      {
         strcpy( szPathPart, MG.szProjectSpec );
         psz = FilePart( szPathPart );
         if ( psz )
         {
            strcpy( szFilePart, psz );
            *psz = 0;
         }
         else
         {
            strcpy( szFilePart, "" );
         }

         if ( MUI_AslRequestTags( pFReq,
               ASLFR_Window         , pWindow,
               ASLFR_PrivateIDCMP   , TRUE,
               ASLFR_TitleText      , "Save MUIEcon File",
               ASLFR_DoSaveMode     , TRUE,
               ASLFR_InitialDrawer  , szPathPart,
               ASLFR_InitialFile    , szFilePart,
               TAG_DONE ) )
         {
            // set the new contents for our string gadget
            memset( MG.szProjectSpec, 0, sizeof( MG.szProjectSpec ) );
            strncpy( MG.szProjectSpec, pFReq->fr_Drawer, sizeof( MG.szProjectSpec )-1 );
            AddPart( MG.szProjectSpec, pFReq->fr_File,   sizeof( MG.szProjectSpec )-1 );
         }
         else
         {
            return( FALSE );
         }

         MUI_FreeAslRequest( pFReq );
      }
   }

   fh = Open( MG.szProjectSpec, MODE_NEWFILE );
   JMH_WindowTitle();
   if ( fh )
   {
      set( MG.App, MUIA_Application_Sleep, TRUE );

      if ( JMH_Write( fh, FILEID_HEADER, strlen( FILEID_HEADER ), fARexx ) == TRUE )
      {
         get( MAIN.LIS_EditList, MUIA_List_Entries, &ulStat );
         for ( ul = 0; ul < ulStat; ul++ )
         {
            DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, ul, &pLVNode );
            if ( pLVNode )
            {
               sprintf( szBuf, " %c%c%s%c%s%c%s%c%s%c%s%c%s%c",
                               pLVNode->ubDataEntryMode,
                               pLVNode->ubContComp,
                               pLVNode->pszName,   255,
                               pLVNode->pszResult, 255,
                               pLVNode->pszText1,  255,
                               pLVNode->pszText2,  255,
                               pLVNode->pszText3,  255,
                               pLVNode->pszText4,  255,
                               pLVNode->pszText5,  255 );
               szBuf[0] = strlen( szBuf );
               if ( JMH_Write( fh, szBuf, strlen( szBuf ), fARexx ) == FALSE )
               {
                  rc = RETURN_ERROR;   // signify FAILURE
                  break;
               }
            }
         }

         // write icon here
         pDObj = GetDiskObject( MG.szProjectSpec );
         if ( !pDObj )
         {
            // don't write an icon if one already exists...
            PutDiskObject( MG.szProjectSpec, &diskobj );
         }
         else
         {
            FreeDiskObject( pDObj );
         }
      }
      Close( fh );
      set( MG.App, MUIA_Application_Sleep, FALSE );
   }
   else
   {
      Fault( IoErr(),
             "Cannot open data file because",
             GL_szFault,
             sizeof( GL_szFault ) );
      JMH_Error( GL_szFault, NULL, fARexx, "PROGDIR:muiecon.guide", "errors", 0 );
      rc = RETURN_ERROR;
   }

   return( rc );
}


/**
 ** M A I N   P R O G R A M -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 **/
void main(int argc, char *argv[])
{
   ULONG   signals;
   ULONG   ulInputEvent;
   char    szBuf[256];

   struct LVNode *pLVNode = NULL;

   // generic status vars
   LONG    lStat;
   ULONG   ulStat;
   char   *pszStat;
   double  dTotalS = 0.0, dTotalA = 0.0;

   BPTR               tmplock;
   struct WBStartup  *WBenchMsg   = NULL;
   struct WBArg      *pWBArg      = NULL;

   char               szProgramSpec[ FMSIZE+1 ];


   MG.running = TRUE;

   //
   // setup variables, read startup params, etc...
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   JMH_Startup( argc, argv );

   //
   // attempt to create window objects and attach to application parent
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if ( fnConstructMainWindow() == FAILURE )
   {
      JMH_Quit( "Failed to create Main window." );
   }
   if ( fnConstructDentWindow() == FAILURE )
   {
      JMH_Quit( "Failed to create Data Entry window." );
   }

   //
   // Load application settings; populate global vars
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   DoMethod( MG.App, MUIM_Application_Load, MUIV_Application_Load_ENV );

   //
   // open main window
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   fnInitMainWindow();

   //
   // if we're passed a data file, load it
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if ( argc > 1 )
   {
      fnReadData( argv[1], FALSE );
   }
   else
   {
      WBenchMsg   = (struct WBStartup *)argv;
      pWBArg      = WBenchMsg->sm_ArgList;

      pWBArg++;   // get first parameter

      if ( pWBArg )
      {
         if ( ( pWBArg->wa_Lock ) && ( *pWBArg->wa_Name ) )
         {
            tmplock  = Lock( pWBArg->wa_Name, ACCESS_READ );
            NameFromLock( tmplock, szProgramSpec, FMSIZE );
            fnReadData( szProgramSpec, FALSE );
            UnLock( tmplock );
         }
      }
   }

   //
   // show 'em what it's all 'About'
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   JMH_About();

   //
   //   MAIN LOOP          MAIN LOOP         MAIN LOOP         MAIN LOOP
   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   while ( MG.running )
   {
      ulInputEvent = DoMethod( MG.App, MUIM_Application_Input, &signals );
      switch ( ulInputEvent )
      {
         case MUIV_Application_ReturnID_Quit:
         case ID_CLOSEMAINWINDOW:
         case ID_MENU_QUIT:
            if ( MUI_Request( MG.App, MG.WIN_Main, 0, NULL, "OK|*Cancel",
                              "Are you sure you want to quit?", NULL ) == 1 )
            {
               MG.running = FALSE;
            }
            break;
         case ID_CLOSEDENTWINDOW:
            fnDestructDentWindow( ENDWINDOW_CANCEL );
            break;

         // MENUS ---------------------------------------------
         case ID_MENU_NEW:
            if ( MUI_Request( MG.App, MG.WIN_Main, 0, NULL, "OK|*Cancel",
                              "Are you sure you wish to clear all data?", NULL ) == 1 )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_Clear, TRUE );

               set( MAIN.TXT_TotalAll,      MUIA_Text_Contents, "0.00" );
               set( MAIN.TXT_TotalSelected, MUIA_Text_Contents, "0.00" );

               MG.pCCPNode = NULL;
            }
            break;
         case ID_MENU_OPEN:
            fnReadData( NULL, FALSE );

            // total all items in list...
            dTotalA = 0.0;
            lStat = -1;
            get( MAIN.LIS_EditList, MUIA_List_Entries, &ulStat );
            for ( lStat = 0; lStat < ulStat; lStat++ )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, lStat, &pLVNode );
               if ( pLVNode )
               {
                  pszStat = JMH_CStrip( pLVNode->pszResult, "0123456789.");
                  dTotalA += atof( pszStat );
                  FreeVec( pszStat );
               }
            }
            sprintf( szBuf, "%.2f", dTotalA );
            set( MAIN.TXT_TotalAll, MUIA_Text_Contents, szBuf );
            break;
         case ID_MENU_SAVE:
            fnWriteData( FALSE, FALSE );
            break;
         case ID_MENU_SAVEAS:
            fnWriteData( TRUE, FALSE );
            break;
         case ID_MENU_PRINT:
            get( MAIN.LIS_EditList, MUIA_List_Active, &lStat );
            if ( lStat == MUIV_List_Active_Off )
            {
               ulStat = 1;    // if no selection, assume we print ALL
            }
            else
            {
               ulStat = MUI_Request( MG.App, MG.WIN_Main, 0, NULL, "*All|Selected|Cancel",
                                 "Print all or selected data?", NULL );
            }
            fnPrint( ulStat, FALSE );
            break;
         case ID_MENU_PRINTAS:
            fnPrintAs( FALSE );
            break;
         case ID_MENU_ABOUT:
            JMH_About();
            break;
         case ID_MENU_CUT:
         {
            struct LVNode  *pNode = NULL;
            ULONG           ulLen;


            DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &pNode );
            if ( pNode )
            {
               if ( MG.pCCPNode )   FreeVec( MG.pCCPNode );
               ulLen = sizeof( struct LVNode ) +
                       strlen( pNode->pszName ) +
                       strlen( pNode->pszResult ) +
                       strlen( pNode->pszText1 ) +
                       strlen( pNode->pszText2 ) +
                       strlen( pNode->pszText3 ) +
                       strlen( pNode->pszText4 ) +
                       strlen( pNode->pszText5 ) + 1;
               if ( MG.pCCPNode = AllocVec( ulLen, MEMF_ANY | MEMF_CLEAR ) )
               {
                  memcpy( MG.pCCPNode, pNode, ulLen );
               }
               DoMethod( MAIN.LIS_EditList, MUIM_List_Remove, MUIV_List_Remove_Active );
            }
            break;
         }
         case ID_MENU_COPY:
         {
            struct LVNode  *pNode = NULL;
            ULONG           ulLen;


            DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &pNode );
            if ( pNode )
            {
               if ( MG.pCCPNode )   FreeVec( MG.pCCPNode );
               ulLen = sizeof( struct LVNode ) +
                       strlen( pNode->pszName ) +
                       strlen( pNode->pszResult ) +
                       strlen( pNode->pszText1 ) +
                       strlen( pNode->pszText2 ) +
                       strlen( pNode->pszText3 ) +
                       strlen( pNode->pszText4 ) +
                       strlen( pNode->pszText5 ) + 1;
               if ( MG.pCCPNode = AllocVec( ulLen, MEMF_ANY | MEMF_CLEAR ) )
               {
                  memcpy( MG.pCCPNode, pNode, ulLen );
               }
            }
            break;
         }
         case ID_MENU_PASTE:
         {
            ULONG          ulBeforeLine;
            char           szBuf[200];
            struct LVNode *pLVNode = NULL;
            UBYTE          ubStore;


            get( MAIN.LIS_EditList, MUIA_List_Active, &ulBeforeLine );
            if ( MG.pCCPNode )
            {
               pLVNode = (struct LVNode *)MG.pCCPNode;
               sprintf( szBuf,   "%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c",
                                 pLVNode->ubContComp,
                                 pLVNode->pszName,    255,
                                 pLVNode->pszResult,  255,
                                 pLVNode->pszText1,   255,
                                 pLVNode->pszText2,   255,
                                 pLVNode->pszText3,   255,
                                 pLVNode->pszText4,   255,
                                 pLVNode->pszText5,   255
                      );
               ubStore = MG.ubCurrentEntryMode;
               MG.ubCurrentEntryMode = pLVNode->ubDataEntryMode;
               DoMethod( MAIN.LIS_EditList, MUIM_List_InsertSingle, &szBuf, ulBeforeLine-1 );
               MG.ubCurrentEntryMode = ubStore;
            }
            break;
         }
         case ID_MENU_ERASE:
         {
            if ( MUI_Request( MG.App, MG.WIN_Main, 0, NULL, "OK|*Cancel",
                              "Are you sure you want to erase this item?", NULL ) == 1 )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_Remove, MUIV_List_Remove_Active );
            }
            break;
         }
         case ID_MENU_ASSIGNMACRO:
         {
            char   szBuf[ FMSIZE+1 ], szRxCmd[ FMSIZE+1+5 ];

            struct Window        *pWindow = NULL;
            struct FileRequester *pFReq   = NULL;


            get( MG.WIN_Main, MUIA_Window, &pWindow );
            if ( pFReq = MUI_AllocAslRequestTags( ASL_FileRequest, TAG_DONE ) )
            {
               if ( MUI_AslRequestTags( pFReq,
                                        ASLFR_Window         , pWindow,
                                        ASLFR_PrivateIDCMP   , TRUE,
                                        ASLFR_TitleText      , "Open MUIEcon ARexx File",
                                        ASLFR_InitialDrawer  , "PROGDIR:Macros",
                                        TAG_DONE ) )
               {
                  // run the ARexx script as a separate task...
                  strcpy( szBuf, pFReq->fr_Drawer );
                  AddPart( szBuf, pFReq->fr_File, sizeof( szBuf )-1 );
                  sprintf( szRxCmd, "rx \"%s\"", szBuf );
                  lStat = SystemTags( szRxCmd, SYS_Asynch, TRUE,
                                               TAG_DONE, TAG_DONE );
                  if ( lStat != 0 )
                  {
                     if ( lStat > 0 )
                        Fault( IoErr(),
                               "Cannot launch macro because",
                               GL_szFault,
                               sizeof( GL_szFault ) );
                     else
                        strcpy( GL_szFault, "Unable to launch the specified macro!" );

                     JMH_Error( GL_szFault, NULL, FALSE, "PROGDIR:muiecon.guide", "errors", 0 );
                  }
               }
               MUI_FreeAslRequest( pFReq );
            }
            break;
         }

         // GADGETS -------------------------------------------
         // MAIN WINDOW
         case ID_LIS_EDITLISTDBLCLICK:
            DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &pLVNode );
            fnInitDentWindow( pLVNode->ubDataEntryMode, TRUE, TRUE );
            break;
         case ID_CYC_MAINVIEWBYCYCLE:
            set( MAIN.LIS_EditList, MUIA_List_Quiet, TRUE );
            DoMethod( MAIN.LIS_EditList, MUIM_List_Sort, TRUE );
            set( MAIN.LIS_EditList, MUIA_List_Quiet, FALSE );
            break;
         case ID_LIS_MAINLISTCHANGE:
            // total all items in list...
            dTotalA = 0.0;
            lStat = -1;
            get( MAIN.LIS_EditList, MUIA_List_Entries, &ulStat );
            for ( lStat = 0; lStat < ulStat; lStat++ )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, lStat, &pLVNode );
               if ( pLVNode )
               {
                  pszStat = JMH_CStrip( pLVNode->pszResult, "0123456789.");
                  dTotalA += atof( pszStat );
                  FreeVec( pszStat );
               }
            }
            sprintf( szBuf, "%.2f", dTotalA );
            set( MAIN.TXT_TotalAll, MUIA_Text_Contents, szBuf );

            // now total only those selected
            dTotalS = 0.0;
            lStat = -1;
            DoMethod( MAIN.LIS_EditList, MUIM_List_NextSelected, &lStat );
            while ( lStat != -1 )
            {
               DoMethod( MAIN.LIS_EditList, MUIM_List_GetEntry, lStat, &pLVNode );
               if ( pLVNode )
               {
                  pszStat = JMH_CStrip( pLVNode->pszResult, "0123456789.");
                  dTotalS += atof( pszStat );
                  FreeVec( pszStat );
               }
               DoMethod( MAIN.LIS_EditList, MUIM_List_NextSelected, &lStat );
            }
            sprintf( szBuf, "%.2f", dTotalS );
            set( MAIN.TXT_TotalSelected, MUIA_Text_Contents, szBuf );
            break;
         case ID_BUT_MAININVFVINVEST:
            fnInitDentWindow( 11, FALSE, TRUE );
            break;
         case ID_BUT_MAININVFVREGDEPOSIT:
            fnInitDentWindow( 12, FALSE, TRUE );
            break;
         case ID_BUT_MAININVDESIREDFV:
            fnInitDentWindow( 13, FALSE, TRUE );
            break;
         case ID_BUT_MAININVREGWD:
            fnInitDentWindow( 14, FALSE, TRUE );
            break;
         case ID_BUT_MAININVWDINITINVEST:
            fnInitDentWindow( 15, FALSE, TRUE );
            break;
         case ID_BUT_MAININVWDMININVEST:
            fnInitDentWindow( 16, FALSE, TRUE );
            break;
         case ID_BUT_MAININVAPRONINVEST:
            fnInitDentWindow( 17, FALSE, TRUE );
            break;
         case ID_BUT_MAINLOANPRINCIPAL:
            fnInitDentWindow( 21, FALSE, TRUE );
            break;
         case ID_BUT_MAINLOANPAYMENT:
            fnInitDentWindow( 22, FALSE, TRUE );
            break;
         case ID_BUT_MAINLOANTERM:
            fnInitDentWindow( 23, FALSE, TRUE );
            break;
         case ID_BUT_MAINLOANAPRONLOAN:
            fnInitDentWindow( 24, FALSE, TRUE );
            break;
         case ID_BUT_MAINLOANLOANBALANCE:
            fnInitDentWindow( 25, FALSE, TRUE );
            break;

         // DENT WINDOW
         case ID_DENT1:
            set( MG.WIN_Dent, MUIA_Window_ActiveObject,  DENT.BUT_Calculate );
            fnCheckDENT( DENT.STR_DataLine1, 1, FALSE );
            break;
         case ID_DENT2:
            set( MG.WIN_Dent, MUIA_Window_ActiveObject,  DENT.BUT_Calculate );
            fnCheckDENT( DENT.STR_DataLine2, 2, FALSE );
            break;
         case ID_DENT3:
            set( MG.WIN_Dent, MUIA_Window_ActiveObject,  DENT.BUT_Calculate );
            fnCheckDENT( DENT.STR_DataLine3, 3, FALSE );
            break;
         case ID_DENT4:
            set( MG.WIN_Dent, MUIA_Window_ActiveObject,  DENT.BUT_Calculate );
            fnCheckDENT( DENT.STR_DataLine4, 4, FALSE );
            break;
         case ID_DENT5:
            set( MG.WIN_Dent, MUIA_Window_ActiveObject,  DENT.BUT_Calculate );
            fnCheckDENT( DENT.STR_DataLine5, 5, FALSE );
            break;
         case ID_BUT_DENTCALCULATE:
            fnDoCalculation( FALSE, TRUE );
            break;
         case ID_BUT_DENTCANCEL:
            fnDestructDentWindow( ENDWINDOW_CANCEL );
            break;
      }
      if ( MG.running && signals ) Wait(signals);
   }

   set( MG.WIN_Main, MUIA_Window_Open, FALSE );
   JMH_Quit( NULL );
}

