#!/usr/bin/perl -w

# htmlcal

# Produces a calendar for the four weeks in HTML format, including
# appointments and WHY, and a todo list.  Also prints it all out as
# plain text on stdout.

# Files:
#   events
#      Contains events in format "yyyy/m/d descriptive text",
#      one per line.  Lines beginning # are comments.
#      Year or month set to zero means "every".
#   todo
#      Contains things to do, one per line.  Web and mail addresses
#      complete with http:// or mailto: will be made active in the
#      output.
#   calendar.html
#      contains the spiffy output for the next 28 days.
# These all live in $workingdir, which is ~/.htmlcal by default.

# (c) rfbooth, 2001.  http://rfbooth.com/

use strict ;

sub mil_day ; # mday = mil_day(day, month, year)
sub make_document_opening ;
my $version = 1.02 ;
my $workingdir = "$ENV{HOME}/.htmlcal/" ;

######################################################################
my @month_offsets=(0,31,59,90,120,151,181,212,243,273,304,334);
my @wdays=("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat") ;
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) ;
my $wday ;      # day of the week today, 0-6
my $month ;     # month, 0-11
my $mday ;      # date, 1-31 (possibly)
my $year ;      # year (since 1900)
my @events ;    # to hold everything for the next four weeks
$#events = 27 ;
my $today ;     # will be today as a mil_day
my $event ;     # event, read from file.
my $eday ;      #
my $emonth ;    # when the event is
my $eyear ;     #
my $delta_day ; # days from today for event

($mday, $month, $year, $wday ) = (localtime)[3,4,5,6] ;

$today = mil_day($mday, $month, $year) ;

############################################################
# read the events
open ( EVENTS, "${workingdir}events" ) or
    die "Can't open ${workingdir}events: $!" ;

while ($event = <EVENTS>) {
    next if $event =~ /^\s*$/ ;
    next if $event =~ /^\#/ ;
    chomp $event ;
    ($event =~ s{^([0-9]+)/([0-9]+)/([0-9]+)\s*}{})
	or die "Bad or no date in events:\n   $event" ;
    ($eyear, $emonth, $eday) = ( $1-1900, $2-1 , $3 ) ;
    if ( $emonth == -1 ) {
	for ( $emonth = 0 ; $emonth < 12 ; ++$emonth ) {
	    make_event( $eyear, $emonth, $eday ) ;
	}
    } else {
	make_event( $eyear, $emonth, $eday ) ;
    }
}

############################################################
# Write the htmldoc and so on.
open ( CAL, "> ${workingdir}calendar.html" ) or
    die "Can't open ${workingdir}calendar.html: $!" ;

make_document_opening ;

my $loopv ;
for ( $loopv = 0 ; $loopv < 28 ; ++$loopv ) {
    if ( ($loopv % 7) == 0 ) {
	print CAL "  <tr>\n";
    }
    if ( defined($events[$loopv]) ) {
	print $events[$loopv][0], ":\n" ;
	print CAL "    <td class=\"event\">\n" ;
	print CAL "      <span class=\"date\">$events[$loopv][0]</span>\n" ;
	foreach (@{$events[$loopv][1]}) {
	    print "  $_\n" ;
	    print CAL "      <br>$_\n" ;
	}
	print CAL "    </td>\n" ;
    } else {
	print CAL "    <td class=\"empty\">&nbsp;</td>\n" ;
    }
    if ( ($loopv % 7) == 6 ) {
	print CAL "  </tr>\n";
    }
}

$ year += 1900 ; 
print CAL "</table>\n<ul>\n" ;

open ( TODO, "${workingdir}todo" ) or
    die "Can't open ${workingdir}todo: $!" ;

while ( $event = <TODO> ) {
    next if $event =~ /^\s*$/ ;
    print " - $event" ;
    chomp $event ;
    $event =~ s{(http://|mailto:)(\S*)}{<a href="$1$2">$1$2</a>}g ;
    print CAL "  <li>$event</li>\n" ;
}

print CAL "</ul>\n<p>\n  Generated on $months[$month] $mday $year ",
    "by htmlcal version $version.",
    "\n  Copyright &copy; <a href=\"http://rfbooth.com/\">rfbooth</a> 2001.\n",
    "</p>\n</body>\n</html>" ;

#---------------------------------------------------------------------

######################################################################
# make_event( $eyear, $emonth, $eday )
#
# generates the actual event value.
sub make_event
{
    my $eyear = shift ;
    my $emonth = shift ;
    my $eday = shift ;
    
    if ( $eyear == -1900 ) {
	$eyear = $year ;
	if ( ($emonth < $month ) or
	     ( ($emonth == $month) and ($eday < $mday) )
	     ) {
	    # then look at next year
	    ++$eyear ;
	}
    }
    $delta_day = mil_day( $eday, $emonth , $eyear ) - $today ;
    if ( ($delta_day >= 0) and ( $delta_day < 28 ) ) {
	if ( !(defined($events[$delta_day])) ) {
	    $events[$delta_day] = [ "$eday $months[$emonth]",
				    [ $event ]
				    ] ;
	} else {
	    # slightly heavy referencing voodoo.  Here
	    # $events[$delta_day][1] is a reference to a
	    # list of events.
	    push(@{$events[$delta_day][1]}, $event) ;
	}
    }
}
#---------------------------------------------------------------------

######################################################################
# mday = mil_day(day, month, year)
#
# Takes date as (day_of_month (1-whatever), month (0-11), year-1900)
# and returns days since 1900/1/0 (so 1 Jan 1900 is 1).
#
# the mil is for millenium (ie days since the millenium), but I
# changed my mind.  Leave me alone!
sub mil_day
{
    my $lday = shift ;
    my $lmonth = shift ;
    my $lyear = shift ;

    # first ignore leap years
    my $answer = $lday + $month_offsets[$lmonth] + 365 * $lyear ;
    # it's not a leap year yet until we pass February:
    --$lyear if ( $lmonth < 2 );
    # every 4 years unless divisible by 100, unless div by 400.
    $answer += int($lyear/4) - int($lyear/100) + int(($lyear+300)/400) ;
    return $answer ;
}
#---------------------------------------------------------------------

######################################################################
# make_document_opening
sub make_document_opening
{
    print CAL "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n",
    "<html lang=\"en\">\n<head>\n",
    "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\">\n",
    "<title> Upcoming commitments </title>\n",
    "<meta name=\"generator\" content=\"htmlcal version $version; see rfbooth.com\">\n",
    "<style type=\"text/css\">\n<!--\n",
    "table { background: \#000000 }\n",
    "td.event { background: \#ffffff ; color: \#000000 ; text-align: center }\n",
    "td.empty { background: \#555555 }\n",
    "td.header { background: \#ff0000 ; color: \#ffffff }\n",
    ".date { color: \#ff0000 }\n",
    "body {\n    background: \#ffffff;\n    color: \#000000;",
    "    font-family: helvetica, verdana, sans-serif\n}\n",
    "-->\n</style>\n</head>\n<body>\n<table>\n",
    "  <tr>\n" ;
    my $loopvar ;
    for ( $loopvar = 0 ; $loopvar < 7 ; ++$loopvar ) {
	print CAL "    <td class=\"header\">\n      ",
	$wdays[($loopvar+$wday) % 7], "\n    </td>\n";
    }
    print CAL "  </tr>\n"
}
#---------------------------------------------------------------------

# EOF
######################################################################





