[comp.sys.sgi] new, improved ical; was Re: Ical update

seth@miro.Berkeley.EDU (Seth Teller) (11/21/90)

In article <1990Nov19.171917.15946@relay.wpd.sgi.com> schuman@sgi.com (Aaron Schuman) writes:
>Dan>	Is there a simple way to bump the calendar program
>Dan>	at night so that is shows the correct day if you
>Dan>	leave it running overnight ?
>
>I use this easy shell script (kept in ~/bin/cal_update):
>
>
>kill `ps -ef | grep ical | grep -v ep | awk '{print $2}'`
>/usr/sbin/ical
>echo "sh /usr/people/schuman/bin/cal_update" | at 0500 tomorrow

here's another approach.  below is a hacked version of ical that
a) keeps correct time as long as it gets timer events (days,
weeks, etc.), and b) has a nifty sun & moon that rise and set
at 6am and 6pm.  

i can't remember if a) was added by paul or me.  if it works,
thank him.  if it's broken, complaints to me i suppose (or fix
it yourself).

if any astronomer types make the program faithful to reality, 
please share your efforts with us.

finally, note the hack in the first 7 lines of the c file:
save it as ical.c, and source it (or chmod it and execute
it)... and it will compile itself with no Makefile.

yours,

seth teller

#cut here, do not include this line
#ifdef EXECUTABLE 
set verbose
cc -o ical ical.c -I/usr/include/gl -lgl_s -lm
unset verbose
exit
cc -o ical ical.c -I/usr/include/gl -lgl_s -lgutil -lm
#endif EXECUTABLE
/* to compile this, make .c file executable and type 'source ical.c' */
/*
 *      ical - 
 *              A very simple desk calendar.  Use the left and middle mouse
 *      mouse buttons to go forward and backward in time.
 *      
 *                              Paul Haeberli - 1985
 *
 *      modified to add alpha clock in lrh corner, yellow sun, blue moon...
 *
 *                              Seth Teller - 1989    
 */
#include "gl.h"
#include "device.h"
#include "math.h"
#include <time.h>

#define rgb(r,g,b) cpack(((unsigned char)(b * 255.0) << 16) | ((unsigned char)(g * 255.0) << 8) | ((unsigned char)(r * 255.0) << 0))
#define grey(i) cpack(((unsigned char)(i * 255.0) << 16) | ((unsigned char)(i * 255.0) << 8) | ((unsigned char)(i * 255.0) << 0))

#define PI (3.1415926)

char *monthnames[]= {
    "January", "February", "March", "April",
    "May", "June", "July", "August",
    "September", "October", "November", "December",
};

char *daynames[] = {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

char monlength[] = {
    0,
    31, 29, 31, 30,
    31, 30, 31, 31,
    30, 31, 30, 31,
};

struct  caltime {
    int second;
    int minute;
    int hour;
    int day;
    int month;
    int year;
};

struct caltime today = { -1, -1, -1, -1, -1, -1 }, show;
long toffset;

void
update_time (show, today)
struct caltime *show, *today;
{
static long lasttime, thetime, lastreq;
static float correction = 1.0;
static struct tm *tm;
int samemonth;

    samemonth = ((today->year == show->year) && (today->month == show->month));

    lasttime = thetime;
    thetime = time(0) + toffset;
    tm = localtime(&thetime);

    today->second = tm->tm_sec;
    if (today->minute != tm->tm_min) {
        today->minute = tm->tm_min;
        qenter (REDRAW);
        }
    today->hour = tm->tm_hour;

    today->year = tm->tm_year + 1900;
    today->month = tm->tm_mon + 1;
    if ((today->day = tm->tm_mday) == 1 && samemonth)   {
        show->month = today->month;
        show->year = today->year;
        }

    if (lastreq && thetime - lasttime >= 30 && !toffset)
        correction = (lastreq / 60.0) / (thetime - lasttime);

    lastreq = (int)(20 + 60 * (60 - today->second) * correction);

    if (!toffset)
        noise (TIMER0, lastreq);
    else
        noise (TIMER0, 3600);
}

main(argc, argv)
char *argv[];
{
short val;

    prefsize(260,185);

    winopen("cal");
    if (getplanes() > 8)
        doublebuffer();
    RGBmode();
    gconfig();

    qdevice(REDRAW);
    qdevice(LEFTMOUSE);
    qdevice(MIDDLEMOUSE);
    qdevice(TIMER0);
    qdevice(BKEY);
    qdevice(FKEY);
    qdevice(RKEY);

    update_time(&show, &today);

    if (argc >= 2) {
        show.month = atoi(argv[1]);
        show.year = atoi(argv[2]);
        show.day = 1;
    } else
        show = today;

    while (1) {
        switch (qread(&val)) {

            case BKEY :
                if (val)    {
                    toffset -= 2 * 60;  /* 2 minutes */
                    update_time(&show, &today);
                    }
                break;

            case FKEY :
                if (val)    {
                    toffset += 2 * 60;  /* 2 minutes */
                    update_time(&show, &today);
                    }
                break;

            case RKEY :
                if (val)    {
                    toffset = 0;
                    update_time(&show, &today);
                    }
                break;

            case LEFTMOUSE :
                if (val) {
                    show.month--;
                    if (show.month == 0) {
                        show.year--;
                        show.month = 12;
                    }
                    drawcal(&show, &today);
                }
                break;

            case MIDDLEMOUSE :
                if (val) {
                    show.month++;
                    if (show.month == 13) {
                        show.year++;
                        show.month = 1;
	                }
		    drawcal(&show, &today);
                    }
                break;

            case REDRAW :
                drawcal(&show, &today);
                break;

	    case TIMER0 :
		update_time(&show, &today);
		break;

	    default:
		break;
	    }
    }
}

int
drawcal(show, today)
struct caltime *show, *today;
{
register i;
int c;
int ycoord;
int samemonth;
char tempstr[30];

    reshapeviewport();
    gsync();

    samemonth = ((today->year == show->year) && (today->month == show->month));

    grey(0.8);
    clear();
    grey(0.0);

    {
    /* draw in the sun and the moon */
    /* sun as yellow circle, moon as blue crescent */

    static short left, right, bottom, top;
    int sunx, suny, moonx, moony;
    float sung;			    /* green comp */

    if (left == right)
        getscrmask (&left, &right, &bottom, &top); 

    /* scr mask to clip to top half of screen */
    scrmask (left, right, bottom + (top - bottom) / 2 + 8, top);

    /* draw sun */
    sunx = 130.0 - (60.0 * sin (2.0 * PI * ((today->hour / 24.0) + today->minute/(60.0 * 24.0)))); 
    suny =  98.0 - (60.0 * cos (2.0 * PI * ((today->hour / 24.0) + today->minute/(60.0 * 24.0)))); 

    if (suny < 118.0 && suny >= 98.0)
        sung = (12.8 * (suny - 98.0)) / 255.0;  
    else if (suny < 98.0 && suny >= 78.0)
        sung = 0.0;
    else
        sung = 1.0;

    rgb (1.0, sung, 0.0);
    circf (sunx, suny, 20.0);

    /* scr mask to clip to bottom half of screen */
    scrmask (left, right, bottom, bottom + (top - bottom) / 2 - 1 + 8);

    rgb (0.0, 0.0, 1.0);
    circfi ((int)sunx, (int)suny, 20);
    grey (0.8);
    circfi ((int)sunx - 10, (int)suny, 20);

    /* scr mask back to normal */
    scrmask (left, right, bottom, top);

    rgb(0.0, 1.0, 0.0);
    move2i(20,99);
    draw2i(240,99);
    }

    grey(0.5);
    move2i(20,163);
    draw2i(240,163);

    rgb(0.0,0.0,1.0);
    cmov2i(20,165);
    charstr(monthnames[show->month-1]);
    rgb(1.0,0.0,0.0);
    sprintf(tempstr,"%u",show->year);
    cmov2i(208,165);
    charstr(tempstr);

    rgb(0.5, 0.5, 0.5);
    move2i(20,143);
    draw2i(240,143);

    grey(0.0);

    for (i=0; i<7; i++){
        cmov2i(24+32*i,145);
        charstr(daynames[i]);
        }

    c = dayofweek(show->month, show->year);
    ycoord = 125;
    for (i=1; i<=monlength[show->month]; i++) {
        cmov2i(24+32*c,ycoord);
        sprintf(tempstr,"%2d",i); 
        if ((i == /*show*/today->day) && samemonth)
            rgb(1.0,0.0,0.0);
        charstr(tempstr);
        if ((i == /*show*/today->day) && samemonth)
            grey(0.0);
        if (++c == 7) {
            c = 0;
            ycoord -= 20;
        }
    }

    rgb(0.0,0.0,1.0);
    cmov2i(176, 10);
    sprintf(tempstr,"%2d:%02d %cm", (today->hour - 1 + 12) % 12 + 1, today->minute, today->hour > 11 ? 'p' : 'a'); 
    charstr(tempstr);

    swapbuffers();
}

dayofweek(m, y)
{
    register d, i;

    d = jan1(y);
    if (((jan1(y+1)+7-d)%7) == 1)
        monlength[2] = 28;
    else
        monlength[2] = 29;
    for (i=1; i<m; i++)
        d += monlength[i];
    return d%7;
}

/*
 *      return day of the week
 *      of jan 1 of given year
 */
jan1(y)
int y;
{
    register int d;

    d = y+4+(y+3)/4;
    if (y > 1752) {
        d += 3;
        if (y > 1800) {
            d -= (y-1701)/100;
            d += (y-1601)/400;
        }
    }
    return d%7;
}

SOFPJF@VM.UOGUELPH.CA (Peter Jaspers-Fayer) (11/23/90)

My mail to Seth bounced.  Sorry all.

Seth.  Thanks for ical. Thanks for the "hack" to allow self-compiling
C programs (I love it).  The big square clock flickers annoyingly, so
having the small time printed on the calendar is ideal.  However,

I get a nastygram:
ERROR #98  gconfig: not enough bitplanes for RGBmode.: ERR_INVAIDMODE

(*sigh* I've only got 8).  And my sun is white (not yellow).  Can anyone
tell me what to patch?  I suspect it's these 2 lines.  How do I tell
the system what kind of graphics board I have?  Man pages are no help.

    RGBmode();
    gconfig();

glear(1) causes my system to complain too.  SGI says that it's because
it's not checking properly to see what kind of graphics board I have.
Maybe I should just upgrade :-)

 /PJ                                                SofPJF@VM.UoGuelph.Ca
         --------------------------------------
It is impossible to make anything foolproof because fools are so ingenious.