#!/bin/sh
#
# NAME:
#	pscal
#
# SYNOPSIS:
#	pscal [-Pprinter] [other option flags] month year
#
# DESCRIPTION:
#	`Pscal' is a PostScript program to print calendars.
#
#	The file $HOME/.xdiary-items is read and used to print short 
#	messages on specified days.  The .xdiary-items file should 
#	consist of lines of the form 
#		month:day:message string
#	Messages should be 20 characters or less, with no more than 6
#	messages per day.  No spaces should appear from the beginning
#	of a line until after the second colon.
#	Month and day should be numbers in the obvious ranges.
#	12/89 - The item checking has been loosened up in that the
#	following takes place:
#		1. The Shell Variable EFILE is used preferentially
#		2. Then the file Events in the current directory is used
#		3. Finally the $HOME/.xdiary-items file is used.
#	The whole process can be turned off by setting EFILE=/dev/null.
#
# OPTIONS:
#	Any argument whose first character is '-' is passed on to lpr.
#	The shell variables BANNER, LFOOT, CFOOT, and RFOOT become a
#	top centered banner, and left, centered, or right justified
#	footers respectively.  As in:
#
#		BANNER="Schedule 1"; CFOOT=Preliminary; pscal 4 90
#
# AUTHOR:
#	Patrick Wood
#	Copyright (C) 1987 by Pipeline Associates, Inc.
#	Permission is granted to modify and distribute this free of charge.
# 
# HISTORY:
#	@Original From: patwood@unirot.UUCP (Patrick Wood)
#	@Shell stuff added 3/9/87 by King Ables
#	@Made pretty by tjt 1988
#	@Holiday and printer flag passing hacks added Dec 1988 
#	@  by smann@june.cs.washington.edu 
#	@Used the better looking version with 5 rows of days rather than 6
#	@  hacked together with item and banner/footnotes added
#	@  by Joe (No Relation) Wood, 12/89, jlw@lzga.ATT.COM
#	@Fixed "-R" (didn't work at all; now it at least works on 8.5x11)
#	@Also fixed handling of unrecognized arguments
#	@  by Jeff Mogul, 1/90, mogul@decwrl.dec.com
#	@Moon routines added; 1000 changed to 400 in isleap and startday;
#	@  fixed bug involving printing events on isdouble 30,31 days.
#	@  by Mark Hanson, 2/90, cs62a12@wind.ucsd.edu
#	@"Day of year/days remaining" support added.
#	@  by Mark Hanson, 11/6/91, mhanson@sdcc13.ucsd.edu
#	@Re-released on freshmeat.net as version 1.7.
#	@  by Mark Hanson 1999-09-13, mbh@netcom.com
#	@Version 1.8: pushed the "epoch" date to 9600, to avoid fencepost
#	@  error on starting day of 2001. (thanks to yamasaki@math.josai.ac.jp)
#	@  by Mark Hanson 2000-01-25, mbh@netcom.com
#	@Version 1.9:
#	@  - fixed bug where junk was left on the stack in drawfill and
#	@    drawgrid (thanks to ivo@tbi.univie.ac.at)
#	@  - added PostScript DSC comments (thanks to ivo@tbi.univie.ac.at)
#	@  - fix bug where months in the .history file with leading zeros
#	@    were ignored (thanks to danng@nfesc.navy.mil)
#	@  by Mark Hanson 2000-03-26, mbh@netcom.com
#	@Version 2.0:
#	@  - added help: -h and -v options
#	@  - added -L option & western language support (isolatin1 encoding)
#	@  - added -d option to the effect of selecting Moon diameter
#	@  - made `date` work with non english localization
#	@  by J.-P. Demailly 2000-03-31, demailly@ujf-grenoble.fr
#	@  - new modifications to get pscal work along with xdiary
#	@  by J.-P. Demailly 2000-09-21, demailly@ujf-grenoble.fr
#	@Version 2.1:
#	@  - added -e european option (A4 format paper)
#	@  - added -y -Y options (year calendar switches)
#	@  by J.-P. Demailly 2000-09-26, demailly@ujf-grenoble.fr
#
# BUGS:
#	`Pscal' doesn't work for months before 1753.  (Weird stuff happened
#	in September, 1752.)  It also won't work as of January 1, 9600.
#	(Bump up the epoch date if you want it to.)
#
#	A better format for the diary-items would be nice. An escape
#	to allow diary-items messages to be raw PostScript would
#	also be nice.
#	The diary-items should be handled more intelligently (ie, the
#	messages should be clipped to the day).
#

V=2.1
LANGUAGE=$LANG

if test "$LANGUAGE" = "" ; then
  $LANGUAGE="english"
fi

setdialogs()
{
VERSION="Pscal-$V: a PostScript calendar formatter, internationalized version"

USAGE="\
Pscal is a PostScript program to print calendars.

Usage: pscal [-hveimdnrRtyY]
             [-P printer] [-L language] [-F hfont] [-f font] [-d diameter] 
             [month [year]]

Options: -h  help message
         -v  version numbering
         -e  european paper (A4 format)
         -i  show diary items
         -m  show Moon phases 
	 -d  moon diameter (default = 8)
         -n  show day numbering
         -r  rotate by 90 degrees
         -R  don't rotate 
	 -t  use cat (and echo to stdout)
	 -y  vertical year calendar   (options -i -m -d -n ineffective)
	 -Y  horizontal year calendar (options -i -m -d -n ineffective)
"

YEAR_NAME="(Year)"

MONTH_NAMES="(January) (February) (March) (April) (May) (June) 
(July) (August) (September) (October) (November) (December)"

DAY_NAMES="(Sunday) (Monday) (Tuesday) (Wednesday) 
(Thursday) (Friday) (Saturday)"

if test "$LANGUAGE" = "fr" || test "$LANGUAGE" = "french" ; then

USAGE="\
Pscal est un programme PostScript destin  imprimer les calendriers.

Usage: pscal [-hveimdnrRtyY]
             [-P printer] [-L langage] [-F hfont] [-f font] [-d diamtre] 
             [mois [anne]]

Options: -h  message d'aide
         -v  numro de version
         -e  papier europen (format A4)
         -i  montrer la liste des items journaliers
         -m  montrer les phases de la Lune
	 -d  diamtre de la Lune (dfaut = 8)
         -n  montrer la numrotation des jours
         -r  tourner de 90 degrs (paysage)
         -R  ne pas tourner (portrait)
	 -t  utiliser cat pour sortie sur stdout
	 -y  calendrier annuel vertical (options -i -m -d -n non effectives)
	 -Y  calendrier annuel horizontal (options -i -m -d -n non effectives)
"
VERSION="\
Pscal-$V: formateur PostScript de calendrier, version internationalise"

YEAR_NAME="(Anne)"

MONTH_NAMES="(Janvier) (Fvrier) (Mars) (Avril) (Mai) (Juin) 
(Juillet) (Aot) (Septembre) (Octobre) (Novembre) (Dcembre)"

DAY_NAMES="(Dimanche) (Lundi) (Mardi) (Mercredi) (Jeudi) (Vendredi) (Samedi)"

fi

if test "$LANGUAGE" = "de" || test "$LANGUAGE" = "german" ; then

YEAR_NAME="(Jahr)"

MONTH_NAMES="(Januar) (Februar) (Mrz) (April) (Mai) (Juni) 
(Juli) (August) (September) (Oktober) (November) (Dezember)"

DAY_NAMES="(Sonntag) (Montag) (Dienstag) (Mittwoch) 
(Donnerstag) (Freitag) (Samstag)"

fi

if test "$LANGUAGE" = "es" || test "$LANGUAGE" = "spanish" ; then

YEAR_NAME="(Ao)"

MONTH_NAMES="(Enero) (Febrero) (Marzo) (Abril) (Mayo) (Junio) (Julio)
(Agosto) (Septiembre) (Octubre) (Noviembre) (Diciembre)"

DAY_NAMES="(Domingo) (Lunes) (Martes) (Mircoles)
(Jueves) (Viernes) (Sbado)"

fi

if test "$LANGUAGE" = "ga" || test "$LANGUAGE" = "irish" ; then

YEAR_NAME="(Bliain)"

MONTH_NAMES="(Eanir) (Feabhra) (Marta) (Aibren) (Bealtaine) (Meitheamh)
(Iil) (Lnasa) (Men Fmhair) (Deireadh Fmhair) (Samhain) (Nollaig)"

DAY_NAMES="(Domhnach) (Luan) (Mirt) (Cadaoin)
(Dardaoin) (Aoine) (Satharn)"

fi

if test "$LANGUAGE" = "it" || test "$LANGUAGE" = "italian" ; then

YEAR_NAME="(Anno)"

MONTH_NAMES="(Gennaio) (Febbraio) (Marzo) (Aprile) (Maggio) (Giugno) (Luglio)
(Agosto) (Settembre) (Ottobre) (Novembre) (Dicembre)"

DAY_NAMES="(Domenica) (Luned) (Marted) (Mercoled) (Gioved)
(Venerd) (Sabato)"
   
fi

if test "$LANGUAGE" = "po" || test "$LANGUAGE" = "portuguese" ; then

YEAR_NAME="(Ano)"

MONTH_NAMES="(Janeiro) (Fevereiro) (Maro) (Abril) (Maio) (Junho) (Julho)
(Agosto) (Setembro) (Outubro) (Novembro) (Dezembro)"

DAY_NAMES="(Domingo) (Segunda) (Tera) (Quarta) (Quinta) (Sexta) (Sbado)"
   
fi

LANGUAGE=""
}

setdialogs

TFONT=Times-Bold
DFONT=Helvetica-Bold
EFONT=Times-Roman

EUROPEAN="false"
MOON="false"
DAYNUMS="false"
DOITEMS=""

ROTATE=90
SCALE="1.0 1.0"
TRANSLATE="50 -120"
MODE=0
DIAMETER=8


# LPR should be set to whatever you need to direct the output to a laser 
# printer; or you can set it to "cat" or use the -t option if you want the
# PostScript code to go to the standard output.
LPR="cat"

# bounding box for normal (not rotated) output
BOUNDINGBOX="21 45 570 755"

while test $# != 0
do
    case $1 in
	-h)	echo "$USAGE" 1>&2; exit 1;;
	-v)	echo "$VERSION" 1>&2; exit 1;;
	-e)	EUROPEAN="true"; shift 1;;
	-L)	LANGUAGE="$2"; shift 2;;
	-L*)	LANGUAGE=`echo $1 | sed -n 1s/-.//p`; shift 1;;
	-d)	DIAMETER="$2"; shift 2;;
	-d*)	DIAMETER=`echo $1 | sed -n 1s/-.//p`; shift 1;;
	-i)	DOITEMS="true"; shift;;
	-m)	MOON="true"; shift;;
	-n)	DAYNUMS="true"; shift;;
	-P)	test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
		eval ENVAR="$1$2"; shift 2;;
	-P*)	eval ENVAR=$1; shift 1;;
	-F)	test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
		TFONT="$2"; shift 2;;
	-F*)	TFONT=`echo $1 | sed -n 1s/-.//p`; shift 1;;
	-f)	test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
		DFONT="$2"; shift 2;;
	-f*)	DFONT=`echo $1 | sed -n 1s/-.//p`; shift 1;;
	-t)	LPR="cat"; shift 1;;
	-r)	ROTATE=90; shift 1;;
	-R)	ROTATE=0; SCALE="0.76 0.76"; TRANSLATE="50 900";
		BOUNDINGBOX="30 335 570 755"; shift 1;;
	-y)	MODE=1; shift 1;;
	-Y)	MODE=2; shift 1;;
	--|-)	break;;
	-*)	eval ENVAR=\"$ENVAR $1\"; shift 1;;
	*)	break
    esac

    if test "$LANGUAGE" != "" ; then setdialogs ; fi
done

test $# -gt 2 && { echo "$USAGE" 1>&2; exit 1; }

case $# in
    0)	YEAR=`date +"%Y"` ; MONTH=`date +"%m"` ;;
    1)	MONTH=$1; YEAR=`date +"%Y"` ;;
    2)	MONTH=$1 YEAR=$2;;
esac

if [ -n "$XDIARYITEMS" -a -r "$XDIARYITEMS" ]
then
	Files=$XDIARYITEMS
elif [ -r Events ]
then
	Files=Events
elif [ -r $HOME/.xdiary-items ]
then
	Files=$HOME/.xdiary-items
else
	Files=/dev/null
fi

if [ $DOITEMS ]
then
    items=`grep "^0*$MONTH:" $Files | awk -F: '{printf("%s ( %s",$2,$3); \
		for(i = 4; i <= NF; i++) printf(":%s", $i);printf(")\n"); }'`
fi

test $YEAR -lt 100 && YEAR=`expr $YEAR + 2000`

$LPR $ENVAR <<END-OF-CALENDAR
%!PS-Adobe-3.0 EPSF-1.2
%%Title: Calendar
%%Creator: pscal $V
%%CreationDate: `date`
%%BoundingBox: $BOUNDINGBOX
%%DocumentFonts: $TFONT $DFONT $EFONT
%%Pages: 1
%%EndComments
%%BeginProlog
% PostScript program to draw calendar
% Copyright (C) 1987 by Pipeline Associates, Inc.
% Permission is granted to modify and distribute this free of charge.
%
% The number after /month should be set to a number from 1 to 12.
% The number after /year should be set to the year you want.
% You can change the title and date fonts, if you want.
% We figure out the rest.
% This program won't produce valid calendars before 1800 due to the switch
% from Julian to Gregorian calendars in September of 1752 wherever English
% was spoken.

/isolatin1encoding [ 
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /space /exclam /quotedbl 
 /numbersign /dollar /percent /ampersand /quoteright
 /parenleft /parenright /asterisk /plus /comma 
 /hyphen /period /slash /zero /one
 /two /three /four /five /six /seven /eight /nine /colon /semicolon
 /less /equal /greater /question /at /A /B /C /D /E
 /F /G /H /I /J /K /L /M /N /O
 /P /Q /R /S /T /U /V /W /X /Y
 /Z /bracketleft /backslash /bracketright /asciicircum 
 /underscore /quoteleft /a /b /c
 /d /e /f /g /h /i /j /k /l /m
 /n /o /p /q /r /s /t /u /v /w
 /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef /.notdef 
 /.notdef /.notdef /.notdef /.notdef /.notdef
 /space /exclamdown /cent /sterling /currency 
 /yen /brokenbar /section /dieresis /copyright
 /ordfeminine /guillemotleft /logicalnot /hyphen /registered 
 /macron /degree /plusminus /twosuperior /threesuperior
 /acute /mu /paragraph /periodcentered /cedilla 
 /onesuperior /ordmasculine /guillemotright /onequarter /onehalf
 /threequarters /questiondown /Agrave /Aacute /Acircumflex 
 /Atilde /Adieresis /Aring /AE /Ccedilla
 /Egrave /Eacute /Ecircumflex /Edieresis /Igrave 
 /Iacute /Icircumflex /Idieresis /Eth /Ntilde
 /Ograve /Oacute /Ocircumflex /Otilde /Odieresis 
 /multiply /Oslash /Ugrave /Uacute /Ucircumflex
 /Udieresis /Yacute /Thorn /germandbls /agrave 
 /aacute /acircumflex /atilde /adieresis /aring
 /ae /ccedilla /egrave /eacute /ecircumflex 
 /edieresis /igrave /iacute /icircumflex /idieresis
 /eth /ntilde /ograve /oacute /ocircumflex 
 /otilde /odieresis /divide /oslash /ugrave
 /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] def

/isofindfont
{
/new_isofont
exch findfont
dup length dict begin
  {1 index /FID ne {def} {pop pop} ifelse} forall
  /Encoding isolatin1encoding def
  currentdict
end
definefont
} def

/pscaldict 100 dict def
pscaldict begin

% calendar names - change these if you don't speak english
% "August", "April" and "February" could stand to be kerned even if you do
/month_names [ $MONTH_NAMES ] def
/day_names [ $DAY_NAMES ] def

% layout parameters - you can change these, but things may not look nice

/daywidth 100 def
/dayheight 95 def

/titlefontsize 48 def
/weekdayfontsize 12 def
/datefontsize 30 def
/footfontsize 20 def
/eventfontsize 9 def

/topgridmarg 35 def
/leftmarg 35 def
/daytopmarg 10 def
/dayleftmarg 5 def

% layout constants - don't change these, things probably won't work

/rows 5 def
/subrows 6 def

% calendar constants - change these if you want a French revolutionary calendar

/days_week 7 def

/days_month [ 31 28 31 30  31  30  31  31  30  31  30  31 ] def

/days_sofar [  0 31 59 90 120 151 181 212 243 273 304 334 ] def

/isleap {				% is this a leap year?
        /theyear exch def
	theyear 4 mod 0 eq		% multiple of 4
	theyear 100 mod 0 ne 		% not century
	theyear 400 mod 0 eq or and	% unless it's divisible by 400
} def

/ndays {				% number of days in this month
	/themonth exch def
	/theyear exch def
	days_month themonth 1 sub get
	month 2 eq			% February
	theyear isleap and
	{
		1 add
	} if
} def

/weekday {				% weekday (range 0-6) for integer date
	days_week mod
} def

/startday {				% starting day-of-week for this month
	/off year 9600 sub def		% offset from start of "epoch"
	off
	off 4 idiv add			% number of leap years
	off 100 idiv sub		% number of centuries
	off 400 idiv add		% number of extra weird days
	6 add weekday days_week add 	% offset from Saturday, Jan 1, 9600
	/off exch def
	1 1 month 1 sub {
		/idx exch def
		days_month idx 1 sub get
		idx 2 eq
		year isleap and
		{
			1 add
		} if
		/off exch off add def
	} for
	off weekday			% 0--Sunday, 1--monday, etc.
} def

/prtevent {		% event-string day prtevent
			%  print out an event
	/start startday def
	/day 2 1 roll def
	day start add 1 sub 7 mod daywidth mul
	day start add 1 sub 7 div truncate dayheight neg mul 
	-5    % offset
	numevents day start add get -10 mul add
	numevents day start add 
	numevents day start add get 1 add put
	add moveto  % move OVER and DOWN appropriate amount
	isdouble {                  % go UP some if it's double and 30 or 31 
   	    { 0 dayheight numevents day 7 sub start add get 10 mul sub rmoveto 
	      (> ) show }
	    { (< ) show } % give a hint as to what day the event is on
	  ifelse 
	} if   
     show
} def

/drawevents {		% read in a file full of events; print
			%  the events for this month
	/numevents
	[0 0 0 0 0 0 0
	 0 0 0 0 0 0 0
	 0 0 0 0 0 0 0
	 0 0 0 0 0 0 0
	 0 0 0 0 0 0 0
	 0 0 0 0 0 0 0] def
	 eventfont isofindfont eventfontsize scalefont setfont
	 0 2 items length 2 sub {
		dup
		1 add items 2 1 roll get       % loads string
		2 1 roll items 2 1 roll get    % loads day
		prtevent
	} for
} def

% ------------------------------------------------------------------------

/prtnum { 3 string cvs show } def

/center {				% center string in given width
	/width exch def
	/str exch def width str 
	stringwidth pop sub 2 div 0 rmoveto str show
} def

/centernum { exch 3 string cvs exch center } def

/drawgrid {				% draw calendar boxes
	titlefont isofindfont weekdayfontsize scalefont setfont
	currentpoint /y0 exch def /x0 exch def
	0 1 days_week 1 sub {
		submonth 0 eq
		{
			x0 y0 moveto
			dup dup daywidth mul 40 rmoveto
			day_names exch get
			daywidth center
		} if
		x0 y0 moveto
		daywidth mul topgridmarg rmoveto
		1.0 setlinewidth
		submonth 0 eq
		{
			/rowsused rows 1 sub def
		}
		{
			/rowsused rows def
		}
		ifelse
		0 1 rowsused {
			gsave
			daywidth 0 rlineto 
			0 dayheight neg rlineto
			daywidth neg 0 rlineto
			closepath stroke
			grestore
			0 dayheight neg rmoveto
			pop
		} for
	} for
} def

/drawnums {				% place day numbers on calendar
	dayfont isofindfont datefontsize
	submonth 0 ne
	{
		2.5 mul
	} if scalefont setfont
	/start startday def
	/days year month ndays def
	start daywidth mul dayleftmarg add daytopmarg rmoveto
	submonth 0 ne
	{
		dayleftmarg neg dayheight -2 div rmoveto
	} if
	1 1 days {
		/day exch def
		gsave
		day start add weekday 0 eq
		{
			submonth 0 eq
			{
				.7 setgray
			} if
		} if
		day start add weekday 1 eq
		{
			submonth 0 eq
			{
				.7 setgray
			} if
		} if
		submonth 0 eq
		{
			isdouble
			{
				day prtdouble
				DAYNUMS day 30 lt and
				{
					day daynumsdouble
				} if
			}
			{
				day prtnum
				DAYNUMS
				{
					day daynums
				} if
			} ifelse
		}
		{
			day daywidth centernum
		} ifelse
		grestore
		day start add weekday 0 eq
		{
			currentpoint exch pop dayheight sub 0 exch moveto
			submonth 0 eq
			{
				dayleftmarg 0 rmoveto
			} if
		}
		{
			daywidth 0 rmoveto
		} ifelse
	} for
} def

/daynums {
	gsave
	/day		exch def
	/sofar		year month day doy def

	0 setgray
	eventfont isofindfont eventfontsize scalefont setfont
	1 eventfontsize rmoveto
	sofar 3 string cvs show
	(/) show

	365
	year isleap {
		1 add
	} if
	sofar sub 3 string cvs show

	grestore
} def	% daynums

/daynumsdouble {
	gsave
	/day		exch def
	/sofar		year month day doy def
	/left		365
			year isleap {
				1 add
			} if
			sofar sub def
	/thefont	eventfont isofindfont eventfontsize 
                        3 mul 4 div scalefont
			def

	0 setgray
	thefont setfont

	currentpoint
	sofar 3 string cvs show
	( / ) show
	left 3 string cvs show
	moveto

	/fsize	datefontsize 2 div 2 add def
	dayfont isofindfont fsize scalefont setfont
	(24/) stringwidth pop 8 add fsize rmoveto

	thefont setfont

	sofar 7 add 3 string cvs show
	( / ) show
	left 7 sub 3 string cvs show

	grestore
} def	% daynumsdouble

/isdouble {				% overlay today with next/last week?
	days start add rows days_week mul gt
	{
		day start add rows days_week mul gt
		{
			true true
		}
		{
			day start add rows 1 sub days_week mul gt
			day days_week add days le and
			{
				false true
			}
			{
				false
			} ifelse
		} ifelse
	}
	{
		false
	} ifelse
} def

/prtdouble {
	gsave
	  dayfont isofindfont datefontsize 2 mul 3 div scalefont setfont
	  exch
	  {
		(23/) stringwidth pop dayheight rmoveto
		prtnum
	  }
	  {
		0 datefontsize 5 div rmoveto
		prtnum
		0 datefontsize -5 div rmoveto
		gsave
		  dayfont isofindfont datefontsize scalefont setfont
		  (/) show
		grestore
	  } ifelse
	grestore
} def

/drawfill {				% place fill squares on calendar
	/start startday def
	/days year month ndays def
	currentpoint /y0 exch def /x0 exch def
	submonth 0 eq
	{
		usefirst
		{
			/fillstart 2 def
		}
		{
			/fillstart 0 def
		}
		ifelse
	}
	{
		/fillstart 0 def
	}
	ifelse
	fillstart daywidth mul topgridmarg rmoveto
	1.0 setlinewidth
	fillstart 1 start 1 sub {
		gsave
		.9 setgray
		daywidth 0 rlineto 
		0 dayheight neg rlineto
		daywidth neg 0 rlineto
		closepath fill
		grestore
		daywidth 0 rmoveto
		pop
	} for
	x0 y0 moveto
	submonth 0 ne
	{
		/lastday rows 1 add days_week mul def
		days_week 1 sub daywidth mul -440 rmoveto
	}
	{
		/lastday rows days_week mul 2 sub fillstart add def
		days_week 3 sub fillstart add daywidth mul
		-440 dayheight add rmoveto
	} ifelse
	lastday -1 year month ndays start 1 add add
	{
		/day exch def
		gsave
		.9 setgray
		daywidth 0 rlineto 
		0 dayheight neg rlineto
		daywidth neg 0 rlineto
		closepath fill
		grestore
		day weekday 1 eq
		{
			x0 y0 moveto
			days_week 1 sub daywidth mul -440 dayheight add rmoveto
		}
		{
			daywidth neg 0 rmoveto
		} ifelse
	} for
} def

/usefirst {				% are last two boxes used by days?
	start year month ndays add rows days_week mul 3 sub gt
	start 2 ge and
	
} def

/calendar
{
	titlefont isofindfont titlefontsize scalefont setfont
	0 60 moveto
	/month_name month_names month 1 sub get def
	month_name show
	/yearstring year 10 string cvs def
	daywidth days_week mul yearstring stringwidth pop sub 60 moveto
	mode 0 eq {
		yearstring show
	} if

	eventflag {
   		                  % Show a centered Banner if any at the Top
		daywidth days_week mul 2 div
		Bannerstring stringwidth pop 2 div sub
		60 moveto
		Bannerstring show
		                           % Show footnotes left-center-right
		eventfont isofindfont footfontsize scalefont setfont
		/bottomrow { dayheight rows mul 5 sub neg } def
		0 bottomrow moveto
		Lfootstring show
		daywidth days_week mul Rfootstring stringwidth pop sub
		bottomrow moveto
		Rfootstring show
		daywidth days_week mul Cfootstring stringwidth pop sub 2 div
		bottomrow moveto
		Cfootstring show
		
	} if

	0 -5 moveto
	drawnums

	0 -5 moveto
	drawfill

	eventflag {
		0 0 moveto
		drawevents
	} if

	0 -5 moveto
	drawgrid
} def

% ------------------------------------------------------------------------

/doy {	% year month day doy -> returns the number of the day of the year
	/theday		exch def
	/themonth	exch def
	/theyear	exch def
	days_sofar themonth 1 sub get
	theyear isleap 
	themonth 2 gt and {
		1 add
	} if
	theday add
} def	% doy

/findphase {		% find the difference between any day and the reference
	/thisday	exch def	% day of the full moon
	/thismonth	exch def	% will probably be one off if the
					% reference is leap yr.
	/thisyear	exch def
	/daysdiff	thisyear thismonth thisday doy
			fullyear fullmonth fullday doy sub 
			longer mul def	% try to be accurate about it
	/yearsdiff	thisyear fullyear sub def
	yearsdiff 0 ne {
		/daysdiff	daysdiff yearsdiff daysperyear mul
				yearsdiff 100 idiv yearsdiff 400 idiv
				sub sub add def
	} if
	daysdiff			% return difference in days
} def	% findphase

/shrink { 2 sqrt div } def

/bignum	1000 def

/transmogrify {
	bignum mul cvi		% take a real number and 'mod it down'
	period bignum mul cvi	% so it is in the range 0->period
	mod			% or -period->0
	bignum div		% the bignum preserves the accuracy
} def	% transmogrify.  Is there a better way to do this?

/domoon {			% draw the moon at the current phase
	/phase	exch def

	0 0 radius		% might as well push these on now
	0 0 radius 

	phase halfperiod lt
	{
		270 90 arc stroke                % line on right, fill on left
		0 radius neg moveto
		270 90 arcn 
	}
	{
		90 270 arc stroke                % line on left, fill on right
		0 radius neg moveto
		270 90 arc 
		/phase phase halfperiod sub def  % get rid of top halfperiod
	} ifelse

	/phase phase quartperiod sub	% scale it down to -r(root2) -> r(root2)
		rect mul def

	phase			% x1
	phase abs shrink	% y1 (need the abs!)
	phase			% x2 
	phase abs shrink neg	% y2 (need the abs!)
	0			% x3
	radius neg		% y3 
	curveto 
	fill
} def	% domoon

/shiftdo {
	startphase day longer mul add
	transmogrify neg period add domoon 
} def	% shiftdo

/drawmoons {
	/fullyear	1991 def	% These are the dates of a full moon,
	/fullmonth	11 def		% any date should work if it is that
	/fullday	21 def		% of a full moon, but I haven't tried
					% too many.

	% I wouldn't make this reference date fall in a leap year, wierdness
	% will probably happen in findphase. You will probably gain or lose a
	% day somewhere. MBH

	/period		29.5306 def
	/daysperyear	365.2422 def
	/longer		daysperyear 365 div def
	/halfperiod	period 2 div def
	/quartperiod	period 4 div def
	/radius		$DIAMETER def
	/rect		radius 2 sqrt mul quartperiod div def
	/startphase	year month 0 findphase transmogrify 
			dup 0 lt { period add } if def
	/start		startday def
	/days		year month ndays def

	gsave
	0.1 setlinewidth
	newpath
	daywidth radius sub 3 sub 15 translate
	start daywidth mul 0 translate
	1 1 days {
		/day exch def
		isdouble
		{		% true if 30,31 -
				% false if 23,24 (left on stack)
			{
				gsave
				radius 2 div dayheight radius 2 div sub
					translate
				0.5 0.5 scale
				shiftdo
				grestore
			}
			{
				gsave
				radius 2 div neg radius 2 div translate
				0.5 0.5 scale
				shiftdo
				grestore
			} ifelse
		}
		{
			shiftdo
		} ifelse
		day start add 1 sub weekday 6 eq
		{
			daywidth 6 mul neg dayheight neg translate
		}
		{
			daywidth 0 translate
		} ifelse
	} for
	grestore
} def	% drawmoons
end
%%EndProlog
%%Page: 1 1

% ------------------------------------------------------------------------
%
% Main Program 
%
% ------------------------------------------------------------------------
pscaldict begin
/titlefont /$TFONT def
/dayfont /$DFONT def
/eventfont /$EFONT def
/items [ $items ] def
/Bannerstring ($BANNER) def
/Lfootstring ($LFOOT) def
/Rfootstring ($RFOOT) def
/Cfootstring ($CFOOT) def
/mode $MODE def
/month $MONTH def
/year $YEAR def
/DAYNUMS $DAYNUMS def

gsave
$EUROPEAN { 0.975 1.045 scale } if 
$SCALE	scale
$ROTATE rotate
$TRANSLATE translate

mode 0 eq
{
	/eventflag true def
	/submonth 0 def
	calendar
	$MOON { drawmoons } if
	/eventflag false def
	month 1 sub 0 eq
	{
		/lmonth 12 def
		/lyear year 1 sub def
	}
	{
		/lmonth month 1 sub def
		/lyear year def
	} ifelse
	month 1 add 13 eq
	{
		/nmonth 1 def
		/nyear year 1 add def
	} 
	{
		/nmonth month 1 add def
		/nyear year def
	} ifelse
	usefirst
	{
		0 30 translate
	}
	{
		days_week 2 sub daywidth mul -350 translate
	}
	ifelse
	/submonth 1 def
	/year lyear def
	/month lmonth def
	gsave
	.138 .138 scale
	12 -120 translate
	calendar
	grestore
	
	/submonth 1 def
	/year nyear def
	/month nmonth def
	daywidth 0 translate
	gsave
	.138 .138 scale
	12 -120 translate
	calendar
	grestore
} if

mode 1 eq
{
	$ROTATE 0 eq { 10 -15 translate }
		     { 0.6 0.6 scale 0 50 translate } ifelse
	titlefont isofindfont titlefontsize scalefont setfont
	0 60 moveto
	$YEAR_NAME show
	590 60 moveto
	year 10 string cvs show
        gsave
	titlefont isofindfont footfontsize scalefont setfont
	0 1 2 { pop
		0 1 6 {	dup 29.7 mul 17 add -800 moveto
			day_names exch get 0 1 getinterval dup
			currentpoint pop exch 1 setgray show
			currentpoint pop sub 3 mul 2 div 0 rmoveto
			0.5 setgray show } for
		237 0 translate
		} for
        grestore
	/eventflag false def
	/submonth 1 def
	0 1 3 {
		/column exch def
		0 1 2 {
			/row exch def
			/month column 3 mul row add 1 add def
			gsave
			row 237 mul 16 -211 column mul add translate
			.3 .3 scale
			calendar
			grestore
		} for 
	} for
} if

mode 2 eq
{
	titlefont isofindfont titlefontsize scalefont setfont
	0 50 moveto
	$YEAR_NAME show
	596 50 moveto
	year 10 string cvs show
        gsave
	titlefont isofindfont footfontsize scalefont setfont
	0 1 3 { pop
		0 1 6 {	dup 22.3 mul 13 add -440 moveto
			day_names exch get 0 1 getinterval dup
			currentpoint pop exch 1 setgray show
			currentpoint pop sub 3 mul 2 div 0 rmoveto
			0.5 setgray show } for
		178 0 translate
		} for
        grestore
	/eventflag false def
	/submonth 1 def
	0 1 2 {
		/column exch def
		0 1 3 {
			/row exch def
			/month row 3 mul column add 1 add def
			gsave
			row 178 mul 16 -158 column mul add translate
			.225 .225 scale
			calendar
			grestore
		} for 
	} for
} if

grestore	
showpage
end
%%EOF
END-OF-CALENDAR
