[comp.lang.postscript] A REAL PostScript calendar...

tjt@ati.tis.llnl.gov (Tim Tessin) (04/06/88)

This posting contains a vastly improved postscript calendar based
on the original "pcal" posted here.  It has square days, grey numbers
for weekends and even little calendars for the previous and next month.
(It also has the leap year bug fixed).

It can still stand some improvement (like shading holidays and providing
labels for holidays, perhaps using the "holiday" program and some filters)
but I haven't got time to keep tweeking.  (Play with the weekday labels
and see if you can spruce it up).

Enjoy,
Tim Tessin - Lawrence Livermore National Laboratory 
tjt@tis.llnl.gov
Phone: (415) 423-4560 / 422-8971

------------------------   cut  here ----------------------------
#!/bin/csh -f
#
# Original From: patwood@unirot.UUCP (Patrick Wood)
# 
# The following is a PostScript program to print calendars.  It doesn't
# work on or before 1752.
# 
# Shell stuff added 3/9/87 by King Ables
# 
# Made pretty by tjt 1988
#
set printer=""

top:
if ($#argv > 0) then
	switch ("$argv[1]")
		case -*:
			set printer="$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] month year"
	exit 1
endif

lpr $printer <<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

/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
} def

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

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

/startday {		% starting day-of-week for this month
	/off year 2000 sub def	% offset from start of "epoch"
	off
	off 4 idiv add		% number of leap years
	off 100 idiv sub	% number of centuries
	off 1000 idiv add	% number of millenia
	6 add 7 mod 7 add 	% offset from Jan 1 2000
	/off exch def
	1 1 month 1 sub {
		/idx exch def
		days_month idx 1 sub get
		idx 2 eq
		isleap and
		{
			1 add
		} if
		/off exch off add def
	} for
	off 7 mod		% 0--Sunday, 1--monday, etc.
} 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

/calendar
{
	titlefont findfont 48 scalefont setfont
	0 60 moveto
	/month_name month_names month 1 sub get def
	month_name show
	/yearstring year 10 string cvs def
	700 yearstring stringwidth pop sub 60 moveto
	yearstring show

	0 0 moveto
	drawnums

	0 0 moveto
	drawfill

	0 0 moveto
	drawgrid
} def

90 rotate
50 -120 translate
/submonth 0 def
calendar
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
/submonth 1 def
/year lyear def
/month lmonth def
500 -365 translate
gsave
.138 .138 scale
10 -120 translate
calendar
grestore
/submonth 1 def
/year nyear def
/month nmonth def
100 0 translate
gsave
.138 .138 scale
10 -120 translate
calendar
grestore

showpage

END-OF-CALENDAR

chavez@cookie.dec.com (Dale - 522-2336/3905) (04/12/88)

In response to message received:  6 Apr 88 16:22:08 GMT

>This posting contains a vastly improved postscript calendar based
>on the original "pcal" posted here.  It has square days, grey numbers
>for weekends and even little calendars for the previous and next month.
>(It also has the leap year bug fixed).
 
>It can still stand some improvement (like shading holidays and providing
>labels for holidays, perhaps using the "holiday" program and some filters)
>but I haven't got time to keep tweeking.  (Play with the weekday labels
>and see if you can spruce it up).
 
>Enjoy,
>Tim Tessin - Lawrence Livermore National Laboratory 
>tjt@tis.llnl.gov
>Phone: (415) 423-4560 / 422-8971

What kind of code precedes the Postscript calendar?  It looks somewhat like
C, but when I try and compile using VMS, I get tons of compiler errors.

Dale

mende@porthos.rutgers.edu (Bob Mende pie) (04/12/88)

In article <8804112027.AA19801@decwrl.dec.com> chavez@cookie.dec.com
(Dale - 522-2336/3905) writes:
>
> What kind of code precedes the Postscript calendar?  It looks somewhat like
> C, but when I try and compile using VMS, I get tons of compiler errors.
>
> Dale

  The code that precedes the PostScript calendar is unix cshell
commands.  It is a hack to do the following.

o	allow a command line interface to postscript.
o	allow the month and year to be taken from a command line and
	set in postscript.
o	print the file...

   Now I am sure that there is a way to do a similar hack in vms ...
but I dont know if there is a equivalent of the <<EOF
construct of sh/csh.   If you want to make the calendar remove
everything before the %! and modify the following...

/month $month def		/month month-you-want-1-12 def
/year $year def			/year year-you-want-in-19xx-form def

and then print it by hand ... what the csh code does is take your
command line args and replace $month and $year appropritly.


						/Bob

ps... you also could print it on a UNIX(tm) machine.
-- 
mende@aramis.rutgers.edu rutgers!aramis.rutgers.edu!mende mende@zodiac.bitnet

Kids, the seven basic food groups are GUM, PUFF PASTRY, PIZZA,
 PESTICIDES, ANTIBIOTICS, NUTRA-SWEET and MILK DUDS!!

bumpy@cisunx.UUCP (Mike Stopper) (04/14/88)

In article <8804112027.AA19801@decwrl.dec.com> chavez@cookie.dec.com (Dale - 522-2336/3905) writes:
>In response to message received:  6 Apr 88 16:22:08 GMT
>
>What kind of code precedes the Postscript calendar?  It looks somewhat like
>C, but when I try and compile using VMS, I get tons of compiler errors.
>
>Dale


It was Bourne shell script I believe. Also, I have vastly improved the calendar
posted here by converting it into a "C" program, and adding the ability to add
special dates like Christmas, Labor Day, etc... plus up to 30 special days of 
your own, like B-days, Exam dates, etc...  If you want it, you can contact me
at:

	bumpy@unix.cis.pittsburgh.EDU

and I can mail the shar'd stuff to you.  It's not all that long.

-- 
*********************************************************************************                     *                                                        **    Mike Stopper     *    Email: bumpy@unix.cis.pittsburgh.EDU                **    a.k.a. Bumpy     *           bumpy@PITTVMS.BITNET                         **                     *           bumpy@cisunx.UUCP                            **********************************************************************************  As we float down life's rive





r,         *  Disclaimer: Any opinions are my   **  I see the stars glow one by one;       *              own and in no way     **  All angels of the magic constellations,*              are the University of **  Be singing as now.                     *              Pittsburgh's since it **                     Yes--_Hearts_       *              has none of its own.  *********************************************************************************

3021_4346@uwovax.uwo.cdn (Greg Miller) (04/15/88)

In article <Apr.12.00.55.37.1988.2602@porthos.rutgers.edu>, mende@porthos.rutgers.edu (Bob Mende pie) writes:
> In article <8804112027.AA19801@decwrl.dec.com> chavez@cookie.dec.com
> (Dale - 522-2336/3905) writes:
>>
>> What kind of code precedes the Postscript calendar?  It looks somewhat like
>> C, but when I try and compile using VMS, I get tons of compiler errors.
>>
>> Dale
> 
>   The code that precedes the PostScript calendar is unix cshell
> commands.  It is a hack to do the following.
> 
> o	allow a command line interface to postscript.
> o	allow the month and year to be taken from a command line and
> 	set in postscript.
> o	print the file...
> 
>    Now I am sure that there is a way to do a similar hack in vms ...
> but I dont know if there is a equivalent of the <<EOF
> construct of sh/csh.   If you want to make the calendar remove
> everything before the %! and modify the following...
> 
> /month $month def		/month month-you-want-1-12 def
> /year $year def			/year year-you-want-in-19xx-form def
> 
> and then print it by hand ... what the csh code does is take your
> command line args and replace $month and $year appropritly.
> 
> 
> 						/Bob
> 
> ps... you also could print it on a UNIX(tm) machine.
> -- 
> mende@aramis.rutgers.edu rutgers!aramis.rutgers.edu!mende mende@zodiac.bitnet
> 
> Kids, the seven basic food groups are GUM, PUFF PASTRY, PIZZA,
>  PESTICIDES, ANTIBIOTICS, NUTRA-SWEET and MILK DUDS!!

twb@hoqax.UUCP (T.W. Beattie) (04/15/88)

In article <8643@cisunx.UUCP>, bumpy@cisunx.UUCP (Mike Stopper) writes:
> Also, I have vastly improved the calendar
> 
> and I can mail the shar'd stuff to you.  It's not all that long.

My e-mail response reqesting a copy of this calendar was bounced by
	pt.cs.cmu.edu
	
These one way machines are a real pain.
Anyway - I would very much like a copy of the vastly improved calendar
program.

Please either e-mail or post.
TIA, Tombo
ihnp4!hoqaa!twb

amlo@warwick.UUCP (Andrew Lord) (04/15/88)

In article <8643@cisunx.UUCP> Mike Stopper writes:

>I have vastly improved the calendar
>posted here by converting it into a "C" program, and adding the ability to add
>special dates like Christmas, Labor Day, etc... plus up to 30 special days of 
>your own, like B-days, Exam dates, etc...  If you want it, you can contact me
>at:
>        bumpy@unix.cis.pittsburgh.EDU

Could you post this to the network as it is probably of
general interest (besides which I can't seem to reach you
by mail!)

Andy Lord

-------------------------------------------------------------------------------
amlo@cs.warwick.ac.uk                         | Department of Computer Science
JANET: amlo@uk.ac.warwick.cs                  | University of Warwick
DARPA: amlo%cs.warwick.ac.uk@cunyvm.cuny.edu  | Coventry, UK
UUCP:  ...!ukc!warwick!amlo                   | CV4 7AL
EARN/BITNET: amlo%uk.ac.warwick.cs@UKACRL     | +44 203 523523 ext 2350
-------------------------------------------------------------------------------

chavez@cookie.dec.com (Dale - 522-2336 CXO-ESDP) (09/16/88)

In response to message received:  14 Apr 88 15:47:35 GMT

Why not just post it here?

dupuy@douglass.columbia.edu (Alexander Dupuy) (09/16/88)

Well, since you asked...

(This is _not_ a shar file)
______________________________________________________________________________
#!/bin/sh -
# 
# PostScript program to print calendars.
# Doesn't deal well with September 1752 or before.
# 
# set ENVAR to PRINTER for BSD spooler, LPDEST for USG spooler
ENVAR=PRINTER

PATH=/usr/ucb:/bin:/usr/bin

eval test \$$ENVAR || eval $ENVAR=PostScript
export $ENVAR

USAGE="Usage: pscal [ -Rrt ] [ -F hfont ] [ -f font ] [ month [ year ] ]"

TFONT=Times-Bold
DFONT=Helvetica-Bold

ROTATE=90

LPR=lpr

while test $# != 0
do
    case $1 in
	-P) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
	    eval $ENVAR="$2"; shift 2;;
	-P*) eval $ENVAR=`echo $1 | sed -n 1s/-.//p`; 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; shift 1;;
	--|-) break;;
	-*) echo "$USAGE" 1>&2; exit 1;;
	*) break
    esac
done

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

case $# in
    0)	set `date`; YEAR=$6
	MONTH=`case $2 in Jan) echo 1;;Feb) echo 2;;Mar) echo 3;;Apr) echo 4;;
		May) echo 5;;Jun) echo 6;;Jul) echo 7;;Aug) echo 8;;
		Sep) echo 9;;Oct) echo 10;;Nov) echo 11;;Dec) echo 12;;esac`;;
    1)	MONTH=$1; set `date`; YEAR=$6;;
    2)	MONTH=$1 YEAR=$2;;
esac

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

$LPR <<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.

% 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.

/month $MONTH def
/year $YEAR def
/titlefont /$TFONT def
/dayfont /$DFONT def

% 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
[ (January) (February) (March) (April) (May) (June) (July)
(August) (September) (October) (November) (December) ]
def

/day_names
[ (Sunday) (Monday) (Tuesday) (Wednesday) (Thursday) (Friday) (Saturday) ]
def

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

/daywidth 100 def
/dayheight 95 def

/titlefontsize 48 def
/weekdayfontsize 10 def
/datefontsize 30 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

/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
} def

/ndays {				% number of days in this month
	days_month month 1 sub get
	month 2 eq			% February
	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 2000 sub def		% offset from start of "epoch"
	off
	off 4 idiv add			% number of leap years
	off 100 idiv sub		% number of centuries
	off 1000 idiv add		% number of millenia
	6 add weekday days_week add 	% offset from Jan 1 2000
	/off exch def
	1 1 month 1 sub {
		/idx exch def
		days_month idx 1 sub get
		idx 2 eq
		isleap and
		{
			1 add
		} if
		/off exch off add def
	} for
	off weekday			% 0--Sunday, 1--monday, etc.
} 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 findfont 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
		} for
	} for
} def

/drawnums {				% place day numbers on calendar
	dayfont findfont datefontsize
	submonth 0 ne
	{
		2.5 mul
	} if scalefont setfont
	/start startday def
	/days 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
			}
			{
				day prtnum
			} 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
/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 findfont 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 findfont datefontsize scalefont setfont
		  (/) show
		grestore
	  } ifelse
	grestore
} def

/drawfill {				% place fill squares on calendar
	/start startday def
	/days 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
	} 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 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 ndays add rows days_week mul 3 sub gt
	start 2 ge and
	
} def

/calendar
{
	titlefont findfont 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
	yearstring show

	0 -5 moveto
	drawnums

	0 -5 moveto
	drawfill

	0 -5 moveto
	drawgrid
} def

$ROTATE rotate
50 -120 translate
/submonth 0 def
calendar
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

showpage

END-OF-CALENDAR
______________________________________________________________________________
(don't forget to cut it here as well)
-- 
inet: dupuy@columbia.edu
uucp: ...!rutgers!columbia!dupuy