

Article 2398 of comp.lang.postscript:
Path: mimsy!tank!eecae!shadooby!mailrus!cornell!uw-beaver!uw-june!smann
>From: [email-masked] (Stephen Mann)
Newsgroups: comp.lang.postscript
Subject: Pscal
Keywords: holidays
Message-ID: <[email-masked]>
Date: 12 May 89 03:02:10 GMT
Distribution: na
Organization: U of Washington, Computer Science, Seattle
Lines: 371

Here's a version of Pscal that has holidays hacked in.  The program
is a Unix C-shell script that sends PostScript directly to a printer.
Documentation appears in the header comments of the script.

Steve
--------
#!/bin/csh -f
#+
#
# NAME:
#	pscal
#
# SYNOPSIS:
#	pscal [-Pprinter] [other printer flags] month year
#
# DESCRIPTION:
#	`Pscal' is a PostScript program to print calendars.
#
#	The file $home/.holiday is read and used to print short messages
#	on specified days.  The .holiday file should consist of lines of
#	the form 
#		month:day:message string
#	Messages should be 20 characters or less, with no more than 4
#	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.
#
# OPTIONS:
#	Any argument whose first character is '-' is passed on to lpr.
#
# AUTHOR:
#	Patrick Wood
#	Copyright (C) 1987 by Pipeline Associates, Inc.
#	Permission is granted to modify and distribute this free of charge.
# 
# HISTORY:
#	@Original From: [email-masked] (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 [email-masked] 
#
# BUGS:
#	`Pscal' doesn't work for months before 1753 (weird stuff happened
#	in September, 1752).
#
#	A better format for the dates of holidays would be nice.
#	An escape to allow holiday messages to be raw PostScript would
#	also be nice.
#	The holiday messages should be handled more intelligently (ie,
#	the messages should be clipped to the day).
#

set printer="-Pps"	# set default printer
set flags

top:
if ($#argv > 0) then
	switch ("$argv[1]")
		case -P*:
			set printer="$argv[1]"
			shift argv
			goto top
		case -*:
			set flags = ($flags $argv[1])
			shift argv
			goto top
		case *:
			if ($?month) then
				set year="$argv[1]"
			else if ($?year) then
				echo "usage: $0 [-Pprinter] month year"
				exit 1
			else
				set month="$argv[1]"
			endif
			shift argv
			goto top
	endsw
endif

if ($?year) then
else 
	echo "usage: $0 [-Pprinter] [-flag1 -flag2 ...] month year"
	exit 1
endif

if ( -e $home/.holiday ) then
    set noglob
    set holidays = \
       (  \[ `grep  ^$month\: $home/.holiday | awk -F: '{print $2,"(",$3,")" }'` ] )
else
    set noglob
    set holidays = (\[ ] )
endif

lpr $printer $flags <<END-OF-CALENDAR
%!
% PostScript program to draw calendar
% Copyright (C) 1987 by Pipeline Associates, Inc.
% Permission is granted to modify and distribute this free of charge.

% /month should be set to a number from 1 to 12
% /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
% won't produce valid calendars before 1800 (weird stuff happened
% in September of 1752)

/month $month def
/year $year def
/titlefont /Times-Bold def
/dayfont /Helvetica-Bold def
/eventfont /Times-Roman def

/holidays $holidays def

/month_names [ (January) (February) (March) (April) (May) (June) (July)
		(August) (September) (October) (November) (December) ] def

/prtnum { 3 string cvs show} def

/drawgrid {		% draw calendar boxes
	dayfont findfont 10 scalefont setfont
	0 1 6 {
		dup dup 100 mul 40 moveto
		[ (Sunday) (Monday) (Tuesday) (Wednesday) (Thursday) (Friday) (Saturday) ] exch get
		100 center
		100 mul 35 moveto
		1.0 setlinewidth
		0 1 5 {
			gsave
			100 0 rlineto 
			0 -80 rlineto
			-100 0 rlineto
			closepath stroke
			grestore
			0 -80 rmoveto
		} for
	} for
} def

/drawnums {		% place day numbers on calendar
	dayfont findfont 30 scalefont setfont
	/start startday def
	/days ndays def
	start 100 mul 5 add 10 rmoveto
	1 1 days {
		/day exch def
		gsave
		day start add 7 mod 0 eq
		{
			submonth 0 eq
			{
				.8 setgray
			} if
		} if
		day start add 7 mod 1 eq
		{
			submonth 0 eq
			{
				.8 setgray
			} if
		} if
		day prtnum
		grestore
		day start add 7 mod 0 eq
		{
			currentpoint exch pop 80 sub 5 exch moveto
		}
		{
			100 0 rmoveto
		} ifelse
	} for
} def

/drawfill {		% place fill squares on calendar
	/start startday def
	/days ndays def
	0 35 rmoveto
	1.0 setlinewidth
	0 1 start 1 sub {
		gsave
		.9 setgray
		100 0 rlineto 
		0 -80 rlineto
		-100 0 rlineto
		closepath fill
		grestore
		100 0 rmoveto
	} for
	submonth 1 eq
	{
		/lastday 42 def
		600 -365 moveto
	}
	{
		/lastday 40 def
		400 -365 moveto
	} ifelse
	lastday -1 ndays start 1 add add
	{
		/day exch def
		gsave
		.9 setgray
		100 0 rlineto 
		0 -80 rlineto
		-100 0 rlineto
		closepath fill
		grestore
		day 7 mod 1 eq
		{
			600 -365 80 add moveto
		}
		{
			-100 0 rmoveto
		} ifelse
	} for
} def

/isleap {		% is this a leap year?
	year 4 mod 0 eq		% multiple of 4
	year 100 mod 0 ne 	% not century
	year 1000 mod 0 eq or and	% unless it's a millenia
}