/*
**++
**  MODULE DESCRIPTION:
**
**      This program was originally written by Phil Baughn of Lexington, KY.
**  Phil wrote the program in BASIC.  I have converted it to C.  Since the
**  program is shareware (by Phil's request) and since he desired that the
**  comments be retained in the source code, I will honour his wish.  With
**  that in mind, below is his comments.
**
**      WEATHER FORECAST PROGRAM by Phil Baughn
**
**      This software program is distributed as "SHAREWARE".  You may
**      feel free to copy and revise it as you like as long as you do
**      not alter or remove the credit information in the program. If
**      you find that you have made some significant improvements and
**      additions to this package, please upload them to my attention
**      either at The MAILROOM RBBS or to Compuserve; User#76044,1535.
**      Enjoy!    Phil Baughn
**
**     Mailing address:          The MAILROOM RBBS-PC
**                               c/o COMMUNITRONICS OF LEXINGTON, INC.
**                               attn.  Phil Baughn
**                               121 Prosperous Place, Suite 6B
**                               Lexington, KY  40509
**                               Data:  (606)293-5119
**                               Voice: (606)263-2737
**
**     Special Credit to Mssrs. Bernard N. Meisner and Leon F. Grave
**     who developed the Heat Index / Apparent Temperature Formula.
**
**  AUTHORS:
**
**      Phil Baughn (original author of BASIC version)
**	Rod Falanga (author of C version)
**
**  CREATION DATE:  15 August 1990
**
**  MODIFICATION HISTORY:
**
**      13-OCT-1990 rjf	I've decided to split off the various weather related
**			routines into their own separate source code files.
**	[@tbs@]...
**--
*/


/*
**
**  INCLUDE FILES
**
*/

#ifdef VMS
#include curses
#include string
#include stdlib
#include time
#else
#include <stdio.h>
#include <osbind.h>
#include <time.h>
#include <bios.h>
#endif

/*
**
**  MACRO DEFINITIONS
**
*/

#define DUMMY_LEN	50

/* 
**  Atari ST related global definitions (because there's no header file which
**  contains these definitions.)
*/
#ifndef VMS
char *strcpy(), *strchr(), *memset();
double atof();
#endif 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This is the main controling function for this program.  (I bet you
**  couldn't figure that one out.)
**
**--
*/
main ()
{
#ifdef VMS
    void target3 (void), 
         init (void), 
         target4 (void), 
         main_menu (void), 
         farewell (void);
#else
    void target3 (), 
         init (), 
         target4 (), 
         main_menu (), 
         farewell ();
#endif

    init ();
    target3 ();
    target4 ();

    /*	 
    **  The next function called was TARGET15 in the BASIC program.
    */	 
    main_menu ();

    farewell ();
#ifdef VMS
    endwin ();
#endif
}   /* end of main() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      The purpose of this function is to position the cursor at a given
**  location on the screen.
**
**  FORMAL PARAMETERS:
**
**      x_pos:
**          the x position, this is an int
**       
**      x_pos:
**          the y position, this is an int
**
**  SIDE EFFECTS:
**
**      Please see the function description for details
**
**--
*/
#ifdef VMS
void position ( int x_pos, int y_pos)
#else
void position ( x_pos, y_pos)
int x_pos;
int y_pos;
#endif
{
    if (x_pos < 1 || y_pos < 1)	/* Can't have a negative or zero position. */
        return;

    /*	 
    **  Now, position the cursor.
    */
#ifdef VMS
    move (x_pos-1, y_pos-1);	/* I think that curses indexs from 0. */
#else
    x_pos += '\040';
    y_pos += '\040';
    printf ("\033Y%c%c", (char)x_pos, (char)y_pos);
    fflush (stdout);
#endif
}   /* end of position() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function lets the User know what this program is all about.
**
**--
*/
#ifdef VMS
void target3 (void)
#else
void target3 ()
#endif
{
#ifdef VMS
    void print (const char *), 
         get_dummy (void);
#else
    void print (), 
         get_dummy ();
#endif
    Erase();
    position (7, 31);
    print("WEATHER FORCASTING");
    position (9, 28);
    print ("DEVELOPED FOR THE IBM-PC");
    position (10, 39);
    print ("BY");
    position (11, 35);
    print ("PHIL BAUGHN");
    position (13, 14);
    print ("Special Thanks For Module Improvements To Sean Gayle,");
    position (14, 11);
    print ("John Fleming, & Brad James - Meteorologist, WTVQ, Lexington");
    position (16, 20);
    print ("Distributed Through The MAILROOM RBBS-PC");
    position (17, 29);
    print ("In Lexington, Kentucky");
    position (18, 22);
    print ("(606)293-5119   24 Hours - 9600 Baud");
    position (19, 22);
    print ("Latest Revision [ 6.0 ]; August 1990");
    position (22, 27);
    print ("Press any key when ready...");
    get_dummy();
}   /* end of target3() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function will print to the screen the string handed it.
**
**  FORMAL PARAMETERS:
**
**      string:
**          a pointer of type char
**
**--
*/
#ifdef VMS
void print (const char *string)
#else
void print (string)
const char *string;
#endif
{
#ifdef VMS
    addstr (string);
    refresh ();
#else
    register char *c;

    c = string;
    while (*c)
    {
        if (*c == '\n')
            Cconws("\r\n");
        else
            Cconout(*c);
	c++;
    }
#endif
}   /* end of print() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      The purpose of this function is to just wait until a character
**  is typed.
**
**  DESIGN:
**
**      I will attempt to write this function so that it can be used by either
**  the Atari ST or the VAX.
**
**  INCLUDED FILES:
**   
**      curses, for the VAX; and osbind for the ST
**   
**--
*/
#ifdef VMS
void get_dummy (void)
#else
void get_dummy ()
#endif
{
    int c;

#ifdef VMS
    refresh ();
    crmode ();
    noecho ();
    c = getch ();
    echo ();
    nocrmode ();
#else
    c = (int)Bconin(BC_CON);
#endif
}   /* end of get_dummy() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function does whatever initialization is necessary.
**
**--
*/
#ifdef VMS
void init (void)
#else
void init ()
#endif
{
#ifdef VMS
    /*	 
    **  Initialize the curses standard window.
    */	 
    initscr ();
#endif
}   /* end of init() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This is the master welcome document.
**
**--
*/
#ifdef VMS
void target4 (void)
#else
void target4 ()
#endif
{
    Erase();
    print ("  \n");
    print ("  \n");
    print ("    This  program  will provide  you with a very good forcast providing\n");
    print ("    you supply the correct  information  as to barometric  pressure and\n");
    print ("    wind direction.  This method has been used  for ages  by  sailors &\n");
    print ("    the tables  themselves can still be found in  almost  all  editions\n");
    print ("    of The Farmers Almanac.\n");
    print (" \n");
    print ("    The other four programs which are included at present;  Wind Chill,\n");
    print ("    Dew Point, Temp/Humidity, & Heat Index; can be especially important\n");
    print ("    when working outdoors.  Wind Chill tells you the true  FEEL  of the\n");
    print ("    temperature  after the wind has it's effect.   It's not always safe\n");
    print ("    to simply  look  at the outdoor thermometer!  Humidity also effects\n");
    print ("    the temperature.   Higher humidity  levels  cause it to effect your\n");
    print ("    body as if it were hotter than the thermometer states.\n");
    print ("  \n");
    print ("    Enjoy the program,   please pass along any  improvements  which you\n");
    print ("    may develop  or  additional  modules  which will fit well into  the\n");
    print ("    menu.   Listing  the source code  WEATHER.C  will provide  you with\n");
    print ("    more detailed contact information.\n");
    print ("  \n");
    print ("  \n");
    print ("    Press any key when ready...\n");
    get_dummy();
}   /* end of target4() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function handles the main menu, displaying it and so on.  The
**  program will stay in this menu until the User wants to quit.
**
**  DESIGN:
**
**      A. Set a flag which will indicate whether the main loop should be
**	   exited.
**	B. Display the main menu.
**	C. Get the User's choice
**	    1.	If the User chooses a valid option, then call the option and
**		ask the User if they want another calculation.
**	    2.  If the User did NOT choose a valid option, then us the C
**		CONTINUE statement to skip over the question about whether the
**		User wants to do another calculation and go straight back to
**		the beginning of the loop again.
**
**--
*/
#ifdef VMS
void main_menu (void)
#else
void main_menu ()
#endif
{
#ifdef VMS
    void list_options (void), 
         forecast (void), 
         wind_chill (void), 
         humidity_index (void), 
         heat_index (void), 
         dew_point (void);
#else
    void list_options (), 
         forecast (), 
         wind_chill (), 
         humidity_index (), 
         heat_index (), 
         dew_point ();
#endif    
    int again, 
	ans, 
#ifdef VMS
        get_option (void), 
        get_char (void);
#else
        get_option (), 
        get_char ();
#endif
    /*	 
    **  First, set the flag so that we'll stay in the loop.
    */	 
    again = 1;

    /*	 
    **  Now, enter the loop.
    */	 
    while (again)
    {
        /*	 
        **  Display the options.
        */	 
        list_options ();

        /*	 
        **  Get the User's choice for an option and evaluate it.
        */	 
        switch (get_option ())
        {
            case 1:
                /*	 
                **  Weather forecast routine.  (Used to be TARGET5.)
                */	 
                forecast ();
                break;
            case 2:
                /*	 
                **  Wind chill calculation.  (Used to be TARGET8.)
                */	 
                wind_chill ();
                break;
            case 3:
                /*	 
                **  Temperature humidity index.  (Used to be TARGET10.)
                */	 
                humidity_index ();
                break;
            case 4:
                /*	 
                **  Heat index calculation.  (Used to be TARGET12.)
                */	 
                heat_index ();
                break;
            case 5:
                /*	 
                **  Dew point calculation.  (Used to be TARGET14.)
                */	 
                dew_point ();
                break;
            default:
                continue;
                break;
        }

        /*	 
        **  Ask the User if they want to do another calculation.
        */	 
        position (24, 14);
        print ("DO YOU WISH TO DO A DIFFERENT CALCULATION (Y/N) ");
        if ((ans = get_char ()) == 'N' || ans == 'n')
            again = 0;	/* The User wishes to stop. */
    }
}   /* end of main_menu() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function gets a character in an unbuffered manner from the User
**  and returns that character to the calling routine.  The entered character
**  is to be echoed to the terminal.
**
**  RETURN VALUE:
**
**      an int, which is the character gotten from the User.
**
**--
*/
#ifdef VMS
int get_char (void)
#else
int get_char ()
#endif
{
    int ch;

#ifdef VMS
    refresh ();
    crmode ();
    ch = getch ();
    nocrmode ();
#else
    ch = (int)Cconin();
#endif

    return ch;
}   /* end of get_char() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function basically says good bye to the User.
**
**--
*/
#ifdef VMS
void farewell (void)
#else
void farewell ()
#endif
{
#ifdef VMS
    void position (int , int), 
         get_dummy (void);
#else
    void position (), 
         get_dummy ();
#endif

    Erase();
    position (9, 23);
    print ("I hope you enjoyed WEATHER and");
    position (11, 21);
    print ("that your forecast was a good one.");
    position (15, 20);
    print ("Let us hear from you on The MAILROOM");
    position (17, 18);
    print ("Data (606)293-5119 - 9600 Baud Supported");
    position (19, 37);
    print ("- Phil Baughn");
#ifndef VMS
    position (23, 1);
    print ("(Press any key to quit...)");
    get_dummy();
#endif
}   /* end of farewell() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This simplistic function merely lists the options that are currently
**  available in this program.
**
**--
*/
#ifdef VMS
void list_options (void)
#else
void list_options ()
#endif
{
#ifdef VMS
    void position (int , int), 
         print (char *);
#else
    void position (), 
         print ();
#endif
    /*	 
    **  Clear the screen.
    */	 
    Erase();

    /*	 
    **  Show the User the options.
    */	 
    position (9, 20);
    print ("1 - WEATHER FORECAST PROGRAM");
    position (11, 20);
    print ("2 - WIND CHILL CALCULATION");
    position (13, 20);
    print ("3 - TEMPERATURE HUMIDITY INDEX");
    position (15, 20);
    print ("4 - HEAT INDEX CALCULATION");
    position (17, 20);
    print ("5 - DEW POINT CALCULATION");
    position (5, 5);
    print ("ENTER THE NUMBER OF THE WEATHER PROGRAM WHICH YOU WISH TO RUN  ");
}   /* end of list_options() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function will get a number as a character string from the User
**  and will translate that into a double value.
**
**  RETURN VALUE:
**
**      A double value which is the value that the User entered.
**
**  DESIGN:
**
**      A. Get a string from the user.
**	B. make a call to the atof() function to translate the string into
**	   a double value
**	C. If any error is encountered during the translation of the string,
**	   then return the value -1000.0, which in the context of this
**	   program is ridiculous.
**
**--
*/
#ifdef VMS
double get_double (void)
#else
double get_double ()
#endif
{
    char dummy [DUMMY_LEN+2];
    double ret;

    /*	 
    **  First, get the string numeric value.
    */	 
#ifdef VMS
    refresh ();
    getstr (dummy);
    if (strlen (dummy) == 0)
        strcpy (dummy, "-1000.0");
#else
	memset(dummy, '\0', DUMMY_LEN+2);
    dummy[0] =	DUMMY_LEN;
    Cconrs(dummy);
    if (dummy[1] != 0)
        strcpy (dummy, &dummy[2]);
    else
        strcpy (dummy, "-1000.0");
#endif

    /*	 
    **  Now, translate the string into the numeric double.
    */	 
    ret = atof (dummy);
    return ret;
}   /* end of get_double() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function clears the screen.
**
**--
*/
#ifdef VMS
int Erase (void)
#else
int Erase ()
#endif
{
#ifdef VMS
    clear ();
    refresh ();
#else
    Cconws("\033E");
#endif
}   /* end of Erase() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      The purpose of this function is to read a string from the User.
**
**  FORMAL PARAMETERS:
**
**      string:
**          a pointer of type char
**
**--
*/
#ifdef VMS
void get_string ( char *string)
#else
void get_string (string)
char *string;
#endif
{
    char dummy [DUMMY_LEN+2];

#ifdef VMS
    refresh ();
    getstr (dummy);
#else
	memset(dummy, '\0', DUMMY_LEN+2);
    dummy[0] =	DUMMY_LEN;
    Cconrs(dummy);
    if (dummy[1] != 0)
        strcpy (dummy, &dummy[2]);
    else
        dummy[0] = '\0';
#endif
    strcpy (string, dummy);
}   /* end of get_string() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function gets the system's current date and time and returns those
**  values in the variables passed to it.
**
**  FORMAL PARAMETERS:
**
**      today:
**          a pointer of type char which will have today's date put into it
**       
**      now:
**          a pointer of type char which will have the system's current time
**	    put into it
**
**--
*/
#ifdef VMS
void get_date_time (char *today, char *now)
#else
void get_date_time (today, now)
char *today, *now;
#endif
{
    time_t bintim;
    tm_t *time_ptr;
    char month [4];

    /*	 
    **  First, get the system's time as a numeric value.
    */	 
    time (&bintim);

    /*	 
    **  Now, get the time structure.
    */	 
    time_ptr = localtime (&bintim);

    /*	 
    **  And now write the relevant fields of the structure to the
    **	strings passed into this routine.
    */	 
    switch (time_ptr->tm_mon)
    {
        case 0:
            strcpy (month, "Jan");
            break;
        case 1:
            strcpy (month, "Feb");
            break;
        case 2:
            strcpy (month, "Mar");
            break;
        case 3:
            strcpy (month, "Apr");
            break;
        case 4:
            strcpy (month, "May");
            break;
        case 5:
            strcpy (month, "Jun");
            break;
        case 6:
            strcpy (month, "Jul");
            break;
        case 7:
            strcpy (month, "Aug");
            break;
        case 8:
            strcpy (month, "Sep");
            break;
        case 9:
            strcpy (month, "Oct");
            break;
        case 10:
            strcpy (month, "Nov");
            break;
        default:
            strcpy (month, "Dec");
            break;
    }
    sprintf (today, "%d %s %d", time_ptr->tm_mday, month, time_ptr->tm_year);
    sprintf (now, "%d:%d:%d", time_ptr->tm_hour, 
	time_ptr->tm_min, time_ptr->tm_sec);

#ifdef VMS
	/* Unfortunately, the Mark Williams 3.0 for the Atari ST will only */
	/* deallocate memory that had been allocated by malloc, calloc or */
	/* realloc.  The localtime() function apparently doesn't use either */
	/* of these functions, so I can't use the free to deallocate the */
	/* allocated memory.  However, since the memory allocated is only to */
	/* a long int, I don't think that that will be much of a problem. */
    free (time_ptr);
#endif
}   /* end of get_date_time() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function will get an option number from the user and return it
**  to the calling routine.  If the User types in something ridiculous, then
**  a 0 is returned.
**
**  RETURN VALUE:
**
**      The number, as an int, which is what the User entered.
**
**--
*/
#ifdef VMS
int get_option (void)
#else
int get_option ()
#endif
{
    char resp [DUMMY_LEN], *s;
    int choice;
#ifdef VMS
    void get_string (char *);
#else
    void get_string ();
#endif

    /*	 
    **  First, let's get the User's response.
    */	 
    get_string(resp);

    /*	 
    **  Remove any leading white space.
    */	 
    s = resp;
    while (*s)
    {
        if (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\r')
        {
            /*	 
            **  Then presumably this is some sort of number...
            */	 
            break;
        }
	s++;
    }

    /*	 
    **  If we're at the end of the User's response (i.e.: they did a carriage
    **	return), then just return a 0.
    */	 
    if (*s == '\0')
        return 0;

    /*	 
    **  OK, everything seems to be fine.  Process the number.
    */	 
    choice = atoi (resp);
    return choice;
}   /* end of get_option() */
