#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <curses.h>

#include "loantype.def"
#include "macmenu.def"

/*
*************************************************************************

 ##                                      ##   ##                
 ##                                      ### ###                
 ##       ####    ####   #####    #####  #######  #####   ## ###
 ##      ##  ##      ##  ##  ##  ##      ## # ## ##  ##   ####  
 ##      ##  ##   #####  ##  ##   ####   ##   ## ##  ##   ###   
 ##      ##  ##  ##  ##  ##  ##      ##  ##   ##  #####   ##    
 ######   ####    ###### ##  ##  #####   ##   ##     ##   ##    
                                                 #####          

*************************************************************************

 Module:      LOANUTIL.C


 Description: This module is a collection of generally unrelated utilities
              used by LoansMgr.                        


 Version:     2.5a (SuSE Linux 9.0, gcc compiler)

 Author:      Michael A. Campbell

****************************************************************************
*/

/**/

/*
-------------------
External Variables
-------------------
*/

extern char *month_names[];    /* The month name array from LoansMgr       */
extern char *year_names[];     /* The year name array from LoansMgr        */

extern int  month_ix;          /* Index into month_names of start month    */
extern int  year_ix;           /* Index into year_names of start year      */

extern WINDOW *lm_win;         /* Main ncurses window for LoansMgr         */

/**/

/*
-----------------------------------------------------------------------
External Functions Used    
-----------------------------------------------------------------------
*/

#include "macmenu.ext"
#include "strutil.ext"
#include "fileutil.ext"

/**/

void setmem ( memp, len, setchar )

/***************************************************************************
 *                                                                         *
 * This function sets the indicated area of memory to the indicated        *
 * pattern.                                                                *
 *                                                                         *
 ***************************************************************************/

char *memp;        /* Pointer to the area to set                           */
int len;           /* Length of area to set                                */
char setchar;      /* Value to set the memory to                           */

{
   register int i;

   for ( i = 0; i < len; i++ )
      memp[i] = setchar;

} /* setmem */

/**/

FILE *open_file_for_writing ( filename, open_mode )

/***************************************************************************
 *                                                                         *
 * This function attempts to open the supplied file for writing. If the    *
 * file doesn't exist, it is created. If it does exist, the user is given  *
 * the option of either overwriting it, or cancelling the operation.       *
 * If the file is successfully opened, this function returns a file        *
 * pointer to it; else it returns NULL                                     *
 *                                                                         *
 ***************************************************************************/

char *filename;             /* The name of the file to open                */
char *open_mode;            /* The mode to open it with                    */

{
   FILE *file_ptr = NULL;   /* Pointer to the file                         */
   char input  [256];       /* A buffer for command line input             */
   char output [82];        /* A buffer for status line output             */
   char response;           /* Response to overwrite prompt                */

   if ( file_exists(filename) ) {

      /* The file already exists - prompt for an overwrite decision        */

      if ( strlen(filename) < 20 ) 
         strcpy ( output, filename );
      else 
         strcpy_right_justify ( filename, output, 20, ' ' );
         
      strcat ( output, " already exists - overwrite [y/n]?" );

      put_status_string ( output );
      response = get_command_key ();

      if ( response == 'Y' )
         file_ptr = fopen ( filename, open_mode );

      clr_status_line ();
   }
   else
      file_ptr = fopen ( filename, open_mode );

   return ( file_ptr );

} /* open_file_for_writing */

/**/

void read_starting_date ( start_month, start_year, start_date_str, menu  )

/****************************************************************************
 *                                                                          *
 * This function reads the starting month and year for the loan, and puts   *
 * it into the schedule menu's data. This function returns the month and    *
 * year as indices into the global month and year tables, defined above.    *
 *                                                                          *
 ****************************************************************************/

int     *start_month;    /* Index of the starting month                     */
int     *start_year;     /* Index of the starting year                      */
char    *start_date_str; /* The starting date as a printable string         */
MENU_ID menu;            /* The menu to post the results to                 */

{
   int   month = -1;           /* The starting month                        */
   int   year  = -1;           /* The starting year                         */
   char  month_str [20];       /* Buffer to hold the month                  */
   char  year_str  [20];       /* Buffer to hold the year                   */

   char  input [256];          /* General input string                      */
   int   fields_converted;     /* Number of fields sscanf converted OK      */

   put_status_string ( "Enter starting Month/Year (mmm yy)" );
   get_command_string ( input );
   clr_status_line ();

   /* Look up the user entered month and year and verify that they are      */
   /* recognized. To make life easier for the user, convert the first       */
   /* char of the month string to upper case, since the table they are      */
   /* looked up in has them with the first letter upper case and the rest   */
   /* in lower case.                                                        */

   fields_converted = sscanf ( input, "%s %s", &month_str, &year_str );

   if ( fields_converted == 2 ) {
      month_str[0] = toupper(month_str[0]);

      month = findstr ( month_str, month_names, NUM_MONTHS );
      year  = findstr ( year_str,  year_names,  NUM_YEARS  );
   }

   if (( month != -1 ) && ( year != -1 )) {

      /* If valid data received, format it and print it on the terminal.   */
      /* Also, load up the global start_date_str for use in profile data   */

      strcpy ( start_date_str, month_str );
      strcat ( start_date_str, " "            );
      strcat ( start_date_str, year_str );

      put_menu_item_data ( menu, 'D', D_STRING, start_date_str );
   }
   else {
      /* Return the current global values, and tell the user of the error */

      month = month_ix;
      year  = year_ix;
      put_status_string ( "Unrecognized month and year - Format is 'Mmm yy' (ex: Jan 95)" );
   }

   *start_month = month;
   *start_year  = year;

} /* read_starting_date */

/**/

void read_payment_interval ( pi, menu )

/***************************************************************************
 *                                                                         *
 * This function reads the payment interval from the user, and parses it   *
 * into the pi, and pi_str data structures.                                *
 *                                                                         *
 * This functions returns the payment interval in the two supplied args,   *
 * and the i_divisor as the functions return value.                        *
 *                                                                         *
 ***************************************************************************/

struct  t_pi   *pi;            /* The returned interval                    */
MENU_ID menu;                  /* The menu to post the result in           */

{
   char parm_string[256];      /* String to hold the parameter read        */
   int  fields_converted = 0;  /* The number of fields sscanf converted OK */

   double n;                   /* The number of units per interval         */
   char   units;               /* The units of n                           */

   put_status_string ( "Enter payment interval in form 'n [Weeks|Months]'" );
   get_command_string ( parm_string );
   clr_status_line ();

   fields_converted = sscanf ( parm_string, "%lf %c", &n, &units );

   if ( fields_converted != 2 )
      put_status_string ( "Invalid interval format: use 'n [Weeks|Months]'" );

   else {
      /* Got the data OK. Load up the payment interval data structures     */

      pi->n = n;
      pi->units = units = toupper(units);

      sprintf ( pi->str, "%3.2f " , n );

      if ( units == 'M' )
         strcat ( pi->str, "Months" );
      else
         strcat ( pi->str, "Weeks" );

      put_menu_item_data ( menu, 'T', D_STRING, pi->str );

      /* Now compute the number of payments per year. This is needed to      */
      /* deal with computing equivalent simple interest rates for the quoted */
      /* rate, compounded "c" times per year, and to convert this rate into  */
      /* a per period rate.                                                  */

      if ( units == 'M' )
         pi->ny = 12.0 / n;
      else
         pi->ny = 52.0 / n;

   } /* Got data OK */

} /* read_payment_interval */

/**/

double read_loan_parm ( prompt, default_value )

/*************************************************************************
 *                                                                       *
 * This function reads a double precision number, echos it to the        *
 * indicated menu, and returns it to the caller.                         *
 *                                                                       *
 *************************************************************************/

char    *prompt;         /* Prompt for this parm                         */
double  default_value;   /* What to return if user enters invalid stuff  */
{

   double parm = 0.0;             /* The parm being read and returned    */
   int    fields_converted = 0;   /* SSCANF output                       */
   char   parm_string [256];      /* Input buffer for the parm string    */

   put_status_string ( prompt );
   get_command_string ( parm_string );
   clr_status_line ();

   fields_converted = sscanf ( parm_string, "%lf", &parm );

   /* If the user has not entered valid data, prompt for it again. If  */
   /* valid data has been entered, echo it to the indicated menu.      */

   if ( fields_converted != 1 ) {
      put_status_string ( "Not a valid number" );
      parm = default_value;
   }

   else {
      /* Converted the number OK. Verify that it is a "reasonable" number, */
      /* and error out if not. Else, load it up.                           */

      if ( parm <= 0.0 ) {
         put_status_string ( "Value must be greater than zero" );
         put_beep ();
         parm = default_value;
      }
      else if ( parm > 999999999999.99 ) {
         put_status_string ( "Values approaching national debt can't be handled!" );
         put_beep ();
         parm = default_value;
      }
   }

   return ( parm );

} /* read_loan_parm */

/**/

void edit_schedule_file ( filename, menu )

/***************************************************************************
 *                                                                         *
 * This function shells out to DOS and invokes the user's editor of choice *
 * to view the schedule file just generated in the schedule_menu_processor.*
 *                                                                         *
 ***************************************************************************/

char *filename;             /* The name of the schedule file               */
MENU_ID menu;               /* The menu to restore after editing is done   */

{
   char *editor;            /* The editor environment variable             */
   char edit_cmd [82];      /* The command buffer for the edit command     */
   int  sys_code;           /* Return code from system call                */

   /* Find out what the user specified editor is, via the editor variable. */
   /* If not set, use the standard DOS internal TYPE command.              */

   editor = (char *) getenv ( "EDITOR" );

   if ( editor != NULL )
      strcpy ( edit_cmd, editor );
   else
      strcpy ( edit_cmd, "less" );  /* Use the less pager if no editor      */

   strcat ( edit_cmd, " " );
   strcat ( edit_cmd, filename );

   /* Kill ncurses and run the editor */

   remove_macmenu_envt ();

   sys_code = system ( edit_cmd );

   /* Now clean up the screen and get back to business */

   create_macmenu_envt ();

   werase   ( lm_win );
   put_menu ( menu   );
   wrefresh ( lm_win );

   /* Examine results. If the system call bombed, alert the user to this     */
   /* fact. If it did not, then either the EDITOR command ran OK, or the     */
   /* TYPE cmd was used. If TYPE was used, tell user this, so that they      */
   /* know they can set the EDITOR variable if they wish.                    */

   if ( sys_code != 0 ) 
      put_status_string ( "OS error while attempting to view file" );
   else
      if ( editor == NULL )
         put_status_string ( "EDITOR environment var not set - used less" );

} /* edit_schedule_file */

/**/

void os_ci ( menu )

/***************************************************************************
 *                                                                         *
 * This function shells out to the OS. It runs the command interpreter in  *
 * the environment variable SHELL. If SHELL is not set, this function      *
 * returns an error.                                                       *
 *                                                                         *
 ***************************************************************************/

MENU_ID menu;         /* The menu this is being invoked from               */

{
   char *ci;
   char throw_away;

   /* Find out what the user specified shell is via the environment var */
   /* SHELL.                                                            */

   ci = (char *) getenv ( "SHELL" );

   if ( ci == NULL )
      put_status_string ( "Cannot shell -- SHELL environment var not set" );

   else {
      /* Kill ncurses and run the shell */

      remove_macmenu_envt ();

      printf ( "\nPress ENTER to continue - Type 'exit' to return to LoansMgr\n" );
      fflush ( stdout );
      throw_away = getchar ();

      system ( ci );

      /* Now clean up the screen and get back to business */

      create_macmenu_envt ();

      werase   ( lm_win );
      put_menu ( menu   );
      wrefresh ( lm_win );
   }

} /* os_ci */

