#!/usr/bin/perl
#
# [1997-01-06] create.cal.pl
# (C) René Scholz
#
# Time-stamp: <2005-12-07 17:24:05, rscholz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# This program was tested under debian 3.0 with:
# - gcal 3.01
# - dvips 5.92b
# - LaTeX, PDFLaTeX: e-TeX (Web2C 7.4.5) 3.14159-2.1 kpathsea version 3.4.5
#
# See the README for a detailed documentation.
############################################################################
use strict;
use vars qw($NAME $VERSION $USAGE $YEAR $MONTH_NAMES %HOLIDAYS %HNAMES $LANGUAGE
$opt_y $opt_h $opt_v $opt_b $opt_c $opt_a $opt_q $opt_Q $opt_d
$opt_w $opt_f $opt_o);
use Getopt::Std;
($NAME = $0) =~ s#.*/##; # get basename from $0
$VERSION = "0.6";
$USAGE=< Generate calendar for the year with german holidays
-b Show only holidays from a specific bundesland (Example: -b DE_TR)
-a Show all (memorial days too)
-o Use additional custom holidays from
-d Print a description of the holidays under the table
-f Print a frame around the description
-q Quiet (show no latex output etc.)
-Q Really Quiet (show no output at all except errors)
-w b/w text (use no text colors)
-v Show version
For a list of known bundeslaender see: \$ gcal -h and look for the option -q
The default is to show all holidays from all bundeslaender.
You can add your own holidays (ex. birthdays) with the option -o .
should have lines like this:
Mark's Birthday + 2005-01-01
EOUSAGE
# -c Show only holidays which are common in all german bundeslaender [TODO]
&scan_cmdline();
&write_holidays();
&write_YEAR_file();
&scan_holidays("holidays.cal");
&scan_holidays($opt_o) if($opt_o);
# create the $month.tex files:
for my $m (1..12) { &month2tex($m); }
$_ = $opt_q ? "> /dev/null" : "";
system "latex -interaction=nonstopmode calendar $_";
if ($?) { print "An error occured while calling latex, return code: $?\n"; }
print "-" x 76 . "\n" unless ($opt_q);
system "pdflatex -interaction=nonstopmode calendar $_";
if ($?) { print "An error occured while calling pdflatex, return code: $?\n"; }
print "-" x 76 . "\n" unless ($opt_q);
$_ = $opt_q ? "-q" : "";
system "dvips $_ -Pcm -Pcmz -o calendar.ps calendar.dvi $_";
if ($?) { print "An error occured while calling dvips: $?\n"; }
unlink qw(calendar.log calendar.aux calendar.out YEAR.tex holidays.cal);
foreach (1..12) { unlink "$_.tex"; }
print "\n" . "-" x 76 unless ($opt_q);
unless ($opt_Q)
{
print "\nOK. All done.\n\n";
print "Used " . (keys %HOLIDAYS) . " Holidays:\n\n";
foreach (sort hsort keys %HOLIDAYS) { print " $_. ($HOLIDAYS{$_})\n"; }
print "\nNow print your new calender 'calendar.pdf' or 'calendar.ps' on a good printer.\n";
}
###################################################################################
# Subroutines #
###################################################################################
# takes the output from "gcal -i -H no $month $YEAR" and creates $month.tex from it.
# sundays and holidays are printed bold.
# Holidays get an other color and an asterix.
sub month2tex
{
my ($month) = @_;
my (@m, $i, $d, $lm, $hnames);
open (G, "gcal -i -H no $month $YEAR|") or die "Can't execute gcal: $!\n";
while ()
{
#if($month == 12) { print; }
next if (/^\s*$|[a-z]+/);
chomp();
s/^\s+|\s+$//g;
s/\s+/ /g;
push (@m, $_);
}
close (G);
open(MONTH_TEX_FILE, "> $month.tex") or die "Cannot write file $month.tex: $!\n";
foreach $lm (0..$#m) # for each week
{
if ($lm eq $#m) # last week of the month?
{
@_ = split(" ", $m[$lm]);
$i = @_ eq 7 ? 6 : @_;
foreach (1..$i)
{
$d = format_day(shift(@_), $month);
print MONTH_TEX_FILE "$d &\t";
}
if (@_ ge 1) # if week is full (has sunday)
{
$d = format_day(shift(@_), $month);
print MONTH_TEX_FILE "{\\bfseries $d}";
}
print MONTH_TEX_FILE " \\\\\\hline\n";
last;
}
# in the first week there may be less than 7 days:
@_ = split(" ", $m[$lm]);
$i = 7 - @_;
foreach (1..$i) { print MONTH_TEX_FILE "&\t"; }
$i = 6 - $i;
foreach (1..$i)
{
$d = format_day(shift(@_), $month);
print MONTH_TEX_FILE "$d &\t";
}
# now output the Sunday:
$d = format_day(shift(@_), $month);
print MONTH_TEX_FILE "{\\bfseries $d}\t\\\\\\hline\n";
}
if ($opt_d ) # print desciption of holidays in this month below the table
{
if (($HNAMES{$month}))
{
$_ = $opt_f ? "|l|" : "l"; # print with frame?
print MONTH_TEX_FILE " \\multicolumn{7}{$_}{";
$_ = "{\\scriptsize\\sffamily $HNAMES{$month}\\hspace{1.55em}}\n";
print MONTH_TEX_FILE "$_}\\\\";
print MONTH_TEX_FILE "\\hline" if($opt_f);
print MONTH_TEX_FILE "\n";
}
else
{
print MONTH_TEX_FILE " \\multicolumn{7}{l}{";
$_ = "{\\scriptsize\\sffamily\\phantom{AbMXxg}}}\\\\\n";
print MONTH_TEX_FILE;
}
}
print MONTH_TEX_FILE " \\end{tabular}\n\\end{center}\n\n";
close (MONTH_TEX_FILE);
}
# creates the LaTeX-code for printing a holiday
sub format_day
{
my ($day, $month, $key) = @_;
$key = $day < 10 ? "0$day." : "$day.";
$key .= $month < 10 ? "0$month" : "$month";
if ($HOLIDAYS{$key})
{
$HNAMES{$month} .= "\$\\ast\$ $HOLIDAYS{$key} ($day.) \\hspace{.5em}";
$day = "{\\phantom{\$^*\$}\\textcolor{holiday}{\\bfseries $day}\$^*\$}";
}
return $day;
}
# read the holidays from gcal-created file and saves them to $HOLIDAYS
sub scan_holidays
{
my ($file) = @_;
open(H, $file) or die "Cannot open file $file: $!\n";
while ()
{
next if (/^\s*$|\#/);
/^(.+) +\+.+-(\d+)-(\d+)/;
my ($desc, $month, $day) = ($1, $2, $3);
$desc =~ s/\s*$//;
$HOLIDAYS{"$day.$month"} = $desc;
}
close (H);
}
# sorts the array %HOLIDAYS as expected
sub hsort
{
my($ad, $am) = split(/\./, $a);
my($bd, $bm) = split(/\./, $b);
return("$am-$ad" cmp "$bm-$bd");
}
sub write_holidays
{
my $gcal_opts = $opt_a ? "-n" : "-N";
# list of bundeslaender for getting holidays from gcal:
@_ = qw(BB BL BR BW HA HS MV NS NW RP SA SH SL SN TR);
$_ = $opt_b || "DE_" . join("+DE_", @_);
$gcal_opts .= " -G -X -u -H no -q $_ --date-format=\"[%>04*Y-%<02*M-%1%>02*D%2]\" $YEAR";
my $gcal_cmd = "gcal $gcal_opts | cut -d= -f1 | sed -e 's/(.*)//;s/ [-*#] / + /' | uniq";
# call gcal and look if german or english version
$_ = `gcal -V`;
die "\nProgram 'gcal' not found on your system.\n" if (/^$/);
$LANGUAGE = /Kompilations-Optionen/ ? "deutsch" : "english";
open (HOLIDAYS, ">holidays.cal") or die "Cannot write holidays.cal: $!\n";
print HOLIDAYS "# Holidays for the year $YEAR (for language: $LANGUAGE)\n#\n";
print HOLIDAYS "# created with: $gcal_cmd >> holidays.cal \n#\n";
close (HOLIDAYS);
system "$gcal_cmd >> holidays.cal";
}
sub scan_cmdline()
{
if (!@ARGV)
{
$YEAR = 1900 + (gmtime(time()))[5];
print "\nNo year given. Assume the current year is: $YEAR\n\n";
print "Is this correct ? (Otherwise use $NAME -y )\n";
print "\n(press return for OK or cancel now with ^C ...)\n";
$_ = <>;
}
else
{
getopts('hy:b:cavqQdwfo:');
die "Version: $VERSION\n" if ($opt_v);
die "$USAGE" if ($opt_h || $opt_y eq "");
if ($YEAR = $opt_y)
{
if ($YEAR < 0) { die "Year was < 0 !$USAGE"; }
}
else { die "$USAGE"; }
}
$opt_q = 1 if ($opt_Q);
}
sub write_YEAR_file()
{
# remember year, day names and month names for calendar.tex:
open (YEARFILE, ">YEAR.tex") or die "Cannot write YEAR.tex: $!\n";
print YEARFILE "\\newcommand{\\YEAR}{$YEAR}\n%\n";
if ($LANGUAGE eq "deutsch")
{
print YEARFILE <