
/*
**                  ╗╗╗ CG Calendar v.03 (Preliminary) ллл
**
**                Written by Craig G. Callan     August 1994
*/


#include <clib/intuition_protos.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <graphics/text.h>
#include <graphics/gfx.h>
#include <exec/types.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#define HEIGHT      15
#define WIDTH       40
#define WINHEIGHT   160
#define WINWIDTH    315

    struct      IntuitionBase   *IntuitionBase;
    struct      Window          *Window;
    struct      NewWindow       NewWindow = {320 - (WINWIDTH + 100) / 2, 20,
                                WINWIDTH + 100, WINHEIGHT, 0, 1, CLOSEWINDOW |
                                INTUITICKS, WINDOWCLOSE | SMART_REFRESH |
                                ACTIVATE | WINDOWDRAG | WINDOWDEPTH |
                                NOCAREREFRESH, NULL, NULL,
                                "CG Calender v.03 (Preliminary)", NULL,
                                NULL, 440, 160, 440, 160, WBENCHSCREEN};
    struct      EasyStruct      myES = {sizeof (struct EasyStruct), 0,
                                "CG Calendar Request",
                                "Do You Really Want to Quit?", "YES|NO"};
    struct      TextExtent      ResultTextExtent;
    struct      tm              *localTime;

    time_t                      timeDate;
    char                        buf [80], c, datestring[80], mname [12], monthname [13][12], Tim [9], weekname [8][10], wkname [10], yr [4];
    long                        timx [3];
    int                         day, julian, leapflg, month, wkday, wkdayfirst, year;
    int                         monthlen [13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int                         CheckQ, ht, Number, reCheck, QFlag, wt;

    void main (), BuildTimeString (), doIDCMP (), doScreen (), doText (), GetToday (), Refresh (), ShutDown (), StartUp ();

/*
╗╗╗ Start Of Main Program лллллллллллллллллллллллллллллллллллллллллллллллллллл
*/

void main()
{
    CheckQ = 0; reCheck = 0; QFlag = 0;
    StartUp ();

    GetToday ();
    julian = FindJulian (day, month, year);
    doScreen ();
    while (QFlag == 0)
    {
        doIDCMP ();
        if (CheckQ == 1)
        {
            CheckQ = 0;
/*
    ╗╗╗ This part is for the "Do You Really Want to Quit?" requester ллл

            QFlag = EasyRequest (NULL, &myES, NULL, NULL, Number);
*/
            QFlag = 1;
        }
    }
    ShutDown ();
    exit (TRUE);
}

/*
╗╗╗ All Subroutines/Functions Reside Below This Point лллллллллллллллллллллллл
*/

void BuildTimeString ()
{
    USHORT                      Hours, Mins;

    Hours = (USHORT) timx [1] / 60;
    Tim [5] = ' '; Tim [7] = 'M'; Tim [8] = 0;
    Mins = (USHORT) timx [1] - (60 * Hours);
    if (Hours > 12)
    {
        Hours = Hours - 12;
        Tim [6] = 'P';
    }
    else
        Tim [6] = 'A';
    Tim [0] = (Hours < 10) ? '0' : (Hours / 10) + '0';
    Tim [1] = (Hours < 10) ? '0' + Hours : (Hours % 10) + '0';
    if (Tim [2] == ':')
        Tim [2] = ' ';
    else
        Tim [2] = ':';
    Tim [3] = (Mins < 10) ? '0' : (Mins / 10) + '0';
    Tim [4] = (Mins < 10) ? '0' + Mins : (Mins % 10) + '0';
}

int CheckForLeapYear (yr)
{
    if ((yr % 4) == 0)
    {                     /* Check for leap year and alter February MONTHLEN */
        monthlen [2] = 29;
        return 1;
    }
    else
    {
        monthlen [2] = 28;
        return 0;
    }
}

void doIDCMP ()
{
    struct      IntuiMessage    *message;
    static      USHORT          ticks;
    char                        Str [2];
    int                         bDay, bMonth, bYear;

    WaitPort (Window -> UserPort);
    while (message = (struct IntuiMessage *) GetMsg (Window -> UserPort))
    {
        switch (message -> Class)
        {
            case CLOSEWINDOW:
                CheckQ = 1;
                break;
            case INTUITICKS:
                if (ticks++ > 7)
                {
                    ticks = 0;
                    DateStamp (timx);
                    BuildTimeString (timx);
                    doText (310, WINWIDTH + 86, 62 + ht, Tim, 1);
                    reCheck++;
                    if (reCheck > 1)           /* Recheck date every second */
                    {
                        reCheck = 0;
                        bDay = day; bMonth = month; bYear = year;
                        GetToday ();
                        julian = FindJulian (day, month, year);
                        if (day != bDay || month != bMonth || year != bYear)
                            Refresh ();
                    }
                }
                break;
        }
        ReplyMsg (message);
    }
}

void doScreen ()
{
    char        Day [4], buf [40];
    int         c1, c2, d, i, j, w, x, y;

/*
╗╗╗ Draw the "Info" part of the window ллл
*/

    doText (310, WINWIDTH + 86, 58 - ht + (ht / 2), "Information", 2);
    SetAPen (Window -> RPort, 1);
    Move (Window -> RPort, 310, 58 + (HEIGHT * 6) + 6);
    Draw (Window -> RPort, 310, 58);
    Draw (Window -> RPort, WINWIDTH + 86, 58);
    SetAPen (Window -> RPort, 2);
    Draw (Window -> RPort, WINWIDTH + 86, 58 + (HEIGHT * 6) + 6);
    Draw (Window -> RPort, 310,  58 + (HEIGHT * 6) + 6);
    Move (Window -> RPort, (WINWIDTH + 86 + 310) / 2 - (wt / 2), 58 - ht + (ht / 2));
    doText (310, WINWIDTH + 86, 62 + ht, "--:-- --", 1);
    strcopy (buf, "Julian ");
    for (i = 0; i < 4; i++)
        Day [i] = 0;
    itoa (julian, Day);
    strcat (buf, Day);
    doText (310, WINWIDTH + 86, 58 + (ht * 4), buf, 1);
    if (leapflg == 1)
        doText (310, WINWIDTH + 86, 62 + (ht * 5), "Leap Year", 1);
/*
╗╗╗ Draw Calendar ллл
*/
    d = 1; y = 58;
    buf [0] = 0;
    strcat (buf, monthname [month]); strcat (buf, " "); strcat (buf, yr);
    doText (0, WINWIDTH, 30, buf, 2);
    w = wt / i;
    SetAPen (Window -> RPort, 1);
    Day [0] = 0; Day [1] = 0; Day [2] = 0;
    for (i = 1; i < 8; i++)
    {
        x = 9 + (i * (WIDTH + 2)) - WIDTH - 2;
        strcopy (buf, weekname [i]); buf [3] = 0;
        doText (x, x + WIDTH, y - ht + (ht / 2), buf, 1);
    }
    do
    {
        if (d == 1)
            j = wkdayfirst;
        else
            j = 1;
        while (j < 8 && d < monthlen [month] + 1)
        {
            x = 10 + (j * (WIDTH + 2)) - WIDTH - 2;
            Move (Window -> RPort, x, y + HEIGHT);
            if (d == day)
            {
                c1 = 2; c2 = 1;
            }
            else
            {
                c1 = 1; c2 = 2;
            }
            SetAPen (Window -> RPort, c2);
            Draw (Window -> RPort, x, y);
            Draw (Window -> RPort, x + WIDTH, y);
            SetAPen (Window -> RPort, c1);
            Draw (Window -> RPort, x + WIDTH, y + HEIGHT);
            Draw (Window -> RPort, x, y + HEIGHT);
            SetAPen (Window -> RPort, 1);
            itoa (d, Day);
            Move (Window -> RPort, x + (w / (w / 2)) , y + ht);
            if (d < 10)
                Text (Window -> RPort, Day, 1);
            else
                Text (Window -> RPort, Day, 2);
            d++; j++; x = x + WIDTH + 2;
        }
        y = y + HEIGHT + 1;
    } while (d < monthlen [month] + 1);
}


void doText (wx1, wx2, y, str, color)
    char                        str [80];
    int                         color, wx1, wx2, y;
{
    int                         x;

    TextExtent (Window -> RPort, str, strlen (str), &ResultTextExtent);
    ht = ResultTextExtent.te_Height;
    if (ht > HEIGHT - 2)
    {
        ShutDown ();
        printf ("\nError!  Please use a font that is smaller than %d points...\n\n", HEIGHT - 1);
        exit (FALSE);
    }
    wt = ResultTextExtent.te_Width;
    x = ((wx2 + wx1) / 2) - (wt / 2);
    SetAPen (Window -> RPort, color);
    Move (Window -> RPort, x, y);
    Text (Window -> RPort, str, strlen (str));
}

int FindJulian (dy, mnth, year)
{
    int     jul, i;

    leapflg = CheckForLeapYear (year);
    jul = dy;
    for (i = 1; i < mnth; i++)
        jul = jul + monthlen [i];
    return jul;
}

void GetToday ()
{
    int         i, j;

    timeDate = time (NULL);
    localTime = localtime (&timeDate);
    strftime (datestring, (size_t)80, "\"%A, %d %B %Y\"\n", localTime );
    i = 0;
    while (datestring [i] != 'y' && datestring [i] != 0)
    {
        wkname [i] = datestring [i + 1];
        i++;
        wkname [i] = 0;
    }
    wkday = 0;
    for (j = 1; j < 8; j++)
        if (strcmp (weekname [j], wkname) == 0) wkday = j;
    i = i + 3; j = 0;
    while (datestring [i] != ' ' && datestring [i] != 0)
    {
        buf [j] = datestring [i];
        i++; j++;
        buf [j] = 0;
    }
    day = atoi (buf);
    i++; j = 0;
    while (datestring [i] != ' ' && datestring [i] != 0)
    {
        mname [j] = datestring [i];
        i++; j++;
        mname [j] = 0;
    }
    month = 0;
    for (j = 1; j < 13; j++)
        if (strcmp (monthname [j], mname) == 0) month = j;
    i++; j = 0;
    while (j < 4)
    {
        yr [j] = datestring [i];
        i++; j++;
        yr [j] = 0;
    }
    year = atoi (yr);
    i = day; wkdayfirst = wkday;
    while (i > 1)
    {
        i--; wkdayfirst--;
        if (wkdayfirst < 1) wkdayfirst = 7;
    }
    leapflg = CheckForLeapYear (year);
}

itoa (n, s)     register    int    n;
                register    char   *s;
{
    int         i, forechar;

    i = forechar = 0;
    if (n < 0)
    {
        forechar = 1;
        n = -n;
    }
    do
    {
        s [i++] = n % 10 + '0';
    } while ((n /= 10) > 0);
    if (forechar)
        s [i++] = '-';
    reverse (s);
}

void Refresh ()
{
    SetAPen (Window -> RPort, 0);
    RectFill (Window -> RPort, 4, ht * 3, WINWIDTH + 88, WINHEIGHT - 4);
    doScreen ();
}

reverse (s)     register    char    *s;
{
    register    int c, i, j;

    for (i = 0, j = strlen (s) - 1; i < j; i++, j--)
    {
        c = s [i];
        s [i] = s [j];
        s [j] = c;
    }
}

void ShutDown ()
{
    if (Window) CloseWindow (Window);
    if (IntuitionBase) CloseLibrary (IntuitionBase);
}

void StartUp ()
{
    int         i, j;
    char        buf [4];

    IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37);
    if (IntuitionBase == NULL)
    {
        printf ("    You must have Kickstart v37 or newer, aborting...\n");
        exit (FALSE);
    }
    if ((Window = (struct Window *) OpenWindow (&NewWindow)) == NULL)
    {
        CloseLibrary (IntuitionBase);
        exit (FALSE);
    }
    TextExtent (Window -> RPort, "Test", 4, &ResultTextExtent);
    ht = ResultTextExtent.te_Height;
    if (ht > HEIGHT - 2)
    {
        ShutDown ();
        printf ("\nError!  Please use a font that is smaller than %d points...\n\n", HEIGHT - 2);
        exit (FALSE);
    }
    strcopy (weekname [1], "Sunday"); strcopy (weekname [2], "Monday");
    strcopy (weekname [3], "Tuesday"); strcopy (weekname [4], "Wednesday");
    strcopy (weekname [5], "Thursday"); strcopy (weekname [6], "Friday");
    strcopy (weekname [7], "Saturday");
    strcopy (monthname [1], "January"); strcopy (monthname [2], "February");
    strcopy (monthname [3], "March"); strcopy (monthname [4], "April");
    strcopy (monthname [5], "May"); strcopy (monthname [6], "June");
    strcopy (monthname [7], "July"); strcopy (monthname [8], "August");
    strcopy (monthname [9], "September"); strcopy (monthname [10], "October");
    strcopy (monthname [11], "November"); strcopy (monthname [12], "December");
}

strcopy (t, s)  register    char    *t, *s;
{
    while (*t++ = *s++);
}

