🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.postscript
Article #7495

Re: A REAL PostScript calendar...

#7495
From: Alexander Dupuy
Date: Fri, 16 Sep 1988 16:55
447 lines
9669 bytes
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
Technical Details
Message-ID: <5887@columbia.edu>
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!seismo!sundc!pitstop!sun!decwrl!labrea!rutgers!columbia!douglass!dupuy
References: <8809161531.AA21589@decwrl.dec.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!seismo!sundc!pitstop!sun!decwrl!labrea!rutgers!columbia!douglass!dupuy
From: dupuy@douglass.columbia.edu (Alexander Dupuy)
Newsgroups: comp.lang.postscript
Subject: Re: A REAL PostScript calendar...
Message-ID: <5887@columbia.edu>
Date: 16 Sep 88 16:55:28 GMT
References: <8809161531.AA21589@decwrl.dec.com>
Sender: news@columbia.edu
Reply-To: dupuy@douglass.columbia.edu (Alexander Dupuy)
Followup-To: comp.lang.postscript
Organization: Columbia University Computer Science Dept.
Lines: 447