[comp.sources.misc] v02i098: personal postscript calendars

wrv@ihlpm.UUCP (Vogel) (04/19/88)

comp.sources.misc: Volume 2, Issue 98
Submitted-By: "Vogel" <wrv@ihlpm.UUCP>
Archive-Name: cal.bs

It prints fancy postscript calendars, however, it allows you to
put your own appointments, etc. in for a given day.  In addition,
it keeps track of changes you've made to your calendar file, and
prints only updated calendar months.  You can run this program
nightly or weekly with a cron or at job.

8<-----8<-----8<-----8<----- < CUT HERE >----->8----->8----->8----->8
#
# cal.bs -> bs program to print personal calendars on postscript printers.
#
# This program looks in your home directory for your calendar file,
# comparing it to a previously hidden copy.  Any months with items
# changed will result in a calendar page being printed for that month.
# It is possible and reasonable to run this program once a day/week
# at 2:00am.  This first time you run it, it will print all calendar
# pages for the current year.  The format of the .calendar file is
# as follows:
#
#   first line should contain:
#   year <whitespace> nnnn
#
#   subsequent lines contain entries as follows:
#   MM/DD <whitespace> text of something happenning on that day.
#
#   example .calendar file:
#   year	1988
#   04/15	Tax day
#   04/16	Darcie's birthday
#   05/30	Memorial Day, party!
#   07/01	My birthday
#   07/04	Fourth of July, party!
#
# rules:
#  1) blank lines are ignored, but no whitespace allowed at beginning of line.
#  2) there can be more than one entry for a single day
#  3) if there is more than one entry for a single day, they MUST
#     appear sequentially in the file.  It is a good idea to keep the
#     entries for a given month sorted.  Months should go sequentially too.
#  4) If there are no entries for a given month, it won't be printed.
#  5) You can specify months into the next year, however you can not
#     specify more than a twelve month span.  I.E., if your first
#     month's entry in the .calendar file is April, then you can fill every
#     month until March of the next year.
#
# To run this program, first see instructions below on modifying the
# thing to work in your environment (very easy).  Then type:
#
# bs cal.bs
#
# Thats it!  If you're system doesn't have bs, complain!  After all,
# its been in UNIX since v7 and is a great language for this kind of
# stuff.
#
# There may be bugs, I threw this together in a real hurry.  Please
# let me know if you find any, and I'll try to fix 'em.
#
# Bill Vogel, AT&T BL, ...ihnp4!ihlpm!wrv
#
########################################
#
# Here is the copyright on the original part of the postscript
# code which is included in a modified form within this program.
#
# PostScript portion of this program to draw calendar ->
#
#   Copyright (C) 1987 by Pipeline Associates, Inc.
#   Permission is granted to modify and distribute this free of charge.
#
########################################
#    
# Things you need to modify:
#
# home  -> your home directory.
# lpcmd -> the command line used which will accept standard input as
#          raw postscript and print it on the local printer.
#
########################################
#                                      #
# BEGIN LINES WHICH NEED MODIFICATION  #
#                                      #
########################################

home  = "/x1/wrv"	# -> your home directory

lpcmd = "!lp -or"	# -> your local printer command for printing raw
                        #    postscript.  Note that the '!' MUST be there.

########################################
#                                      #
# END LINES WHICH NEED MODIFICATION    #
#                                      #
########################################
#

#
# You can change these if you insist on changing the name of the
# calendar file.
#
cf	= home_"/.calendar"
ci	= home_"/.calendar.bak"

#
#	pattern strings.  don't muckety-muck with these.
#
pstr1 = "\([0-9]*\)/\([0-9]*\)[ 	]*\(.*\)"
pstr2 = "year[ 	]\([0-9]*\)"

#
#	initialize month counters
#
for j = 1 12
	mthcnt[j] = 0
	altcnt[j] = 0
next
frstmo = -1

#
#	parse the calendar file, break it up into an array
#
open("fdc", cf, "r")
while ?(i = fdc)
	if match(i, pstr1)
		month = mstring(1)
		if ( frstmo == -1 ) frstmo = month
		x = mthcnt[month]
		mdata[month, x, 1] = mstring(2)
		mdata[month, x, 2] = mstring(3)
		mthcnt[month] = x + 1
	elif match(i, pstr2)
		year = mstring(1)
	fi
next
close("fdc")

#
#	parse the backup calendar file.
#
if ?eval("open(\"fdi\", ci, \"r\")")
	while ?(i = fdi)
		if match(i, pstr1)
			month = mstring(1)
			x = altcnt[month]
			altdata[month, x, 1] = mstring(2)
			altdata[month, x, 2] = mstring(3)
			altcnt[month] = x + 1
		elif match(i, pstr2)
			altyear = mstring(1)
		fi
	next
	close("fdi")
else
	for j = 1 12
		domonth[j] = 2
	next
fi

#
#	now, go thru and compare months
#
for i = 1 12
	if (altcnt[i] != mthcnt[i]) | (altyear != year)
		domonth[i] = 1
		continue
	fi
	if mthcnt[i]
		for j = 0 mthcnt[i] -1
			if mdata[i, j, 1] != altdata[i, j, 1]
				domonth[i] = 1
				continue
			fi
			if mdata[i, j, 2] != altdata[i, j, 2]
				domonth[i] = 1
				continue
			fi
		next
	fi
next

#
#	make backup copy of the .calendar file.  This may do
#	weird stuff if you don't keep your .calendar writeable or
#	if you run with a funny umask.
#
open("command", "!cp "_cf_" "_ci, "w")
        close("command")

#
#	now, generate the postscript commands for each
#	entry in the file.
#
beginm	=	frstmo
header	=	0
for j = 1 12
	if (domonth[beginm] == 2) | (domonth[beginm] & mthcnt[beginm])
		put = "printing month "_beginm_", year "_year
		if (header == 0)
			header = 1
			open("lpout", lpcmd, "w")
			pheader()
		fi
		pmonth(beginm)
	fi
	beginm = beginm + 1
	if beginm > 12
		beginm = 1
		year = year + 1
	fi
next
#
#	close the output file
#
if ( header ) close("lpout")

#
#	print the postscript commands for one month
#
fun pmonth(m)
	lpout = "/year "_year_" def"
	lpout = "/month "_m_" def"
	lpout = "printmonth"
	oldday = -1

	if ( mthcnt[m] == 0 )
		lpout = "showpage"
		return 0
	fi
	for i = 0 mthcnt[m] - 1
		day = mdata[m, i, 1] # day
		if day != oldday
			if oldday == -1
				lpout = day_" [ "
			else
				lpout = " ] daytext "_day_" [  "
			fi
			oldday = day
		else
			lpout = "(.p)"
		fi
		nb = 0
		s = mdata[m, i, 2]   # text
		while (n = match(s, "[ 	]*\([^ 	][^ 	]*\)"))
			lpout = "("_mstring(1)_")"
			s = substr(s, n+1, 900)
		next
	next
	lpout = "] daytext showpage clear"
nuf

fun pheader()
	lpout = "/titlefont /Times-Bold def"
	lpout = "/dayfont /Helvetica-Bold def"
	lpout = "/month_names [ (January) (February) (March) (April) (May) (June) (July)"
	lpout = "		(August) (September) (October) (November) (December) ] def"
	lpout = "/prtnum { 3 string cvs show} def"
	lpout = "/drawgrid {		% draw calendar boxes"
	lpout = "	dayfont findfont 10 scalefont setfont"
	lpout = "	0 1 6 {"
	lpout = "		dup dup 100 mul 40 moveto"
	lpout = "		[ (Sunday) (Monday) (Tuesday) (Wednesday) (Thursday) (Friday) (Saturday) ] exch get"
	lpout = "		100 center"
	lpout = "		100 mul 35 moveto"
	lpout = "		1.0 setlinewidth"
	lpout = "		0 1 5 {"
	lpout = "			gsave"
	lpout = "			100 0 rlineto "
	lpout = "			0 -80 rlineto"
	lpout = "			-100 0 rlineto"
	lpout = "			closepath stroke"
	lpout = "			grestore"
	lpout = "			0 -80 rmoveto"
	lpout = "		} for"
	lpout = "	} for"
	lpout = "} def"
	lpout = "/drawnums {		% place day numbers on calendar"
	lpout = "	dayfont findfont 30 scalefont setfont"
	lpout = "	/start startday def"
	lpout = "	/days ndays def"
	lpout = "	start 100 mul 5 add 10 rmoveto"
	lpout = "	1 1 days {"
	lpout = "		/day exch def"
	lpout = "		gsave"
	lpout = "		day start add 7 mod 1 eq"
	lpout = "		{"
	lpout = "			submonth 0 eq"
	lpout = "			{"
	lpout = "				.8 setgray"
	lpout = "			} if"
	lpout = "		} if"
	lpout = "		day prtnum"
	lpout = "		grestore"
	lpout = "		day start add 7 mod 0 eq"
	lpout = "		{"
	lpout = "			currentpoint exch pop 80 sub 5 exch moveto"
	lpout = "		}"
	lpout = "		{"
	lpout = "			100 0 rmoveto"
	lpout = "		} ifelse"
	lpout = "	} for"
	lpout = "} def"
	lpout = "/drawfill {		% place fill squares on calendar"
	lpout = "	/start startday def"
	lpout = "	/days ndays def"
	lpout = "	0 35 rmoveto"
	lpout = "	1.0 setlinewidth"
	lpout = "	0 1 start 1 sub {"
	lpout = "		gsave"
	lpout = "		.9 setgray"
	lpout = "		100 0 rlineto "
	lpout = "		0 -80 rlineto"
	lpout = "		-100 0 rlineto"
	lpout = "		closepath fill"
	lpout = "		grestore"
	lpout = "		100 0 rmoveto"
	lpout = "	} for"
	lpout = "	submonth 1 eq"
	lpout = "	{"
	lpout = "		/lastday 42 def"
	lpout = "		600 -365 moveto"
	lpout = "	}"
	lpout = "	{"
	lpout = "		/lastday 40 def"
	lpout = "		400 -365 moveto"
	lpout = "	} ifelse"
	lpout = "	lastday -1 ndays start 1 add add"
	lpout = "	{"
	lpout = "		/day exch def"
	lpout = "		gsave"
	lpout = "		.9 setgray"
	lpout = "		100 0 rlineto "
	lpout = "		0 -80 rlineto"
	lpout = "		-100 0 rlineto"
	lpout = "		closepath fill"
	lpout = "		grestore"
	lpout = "		day 7 mod 1 eq"
	lpout = "		{"
	lpout = "			600 -365 80 add moveto"
	lpout = "		}"
	lpout = "		{"
	lpout = "			-100 0 rmoveto"
	lpout = "		} ifelse"
	lpout = "	} for"
	lpout = "} def"
	lpout = "/isleap {		% is this a leap year?"
	lpout = "	year 4 mod 0 eq		% multiple of 4"
	lpout = "	year 100 mod 0 ne 	% not century"
	lpout = "	year 1000 mod 0 eq or and	% unless it's a millenia"
	lpout = "} def"
	lpout = "/days_month [ 31 28 31 30 31 30 31 31 30 31 30 31 ] def"
	lpout = "/ndays {		% number of days in this month"
	lpout = "	days_month month 1 sub get"
	lpout = "	month 2 eq	% Feb"
	lpout = "	isleap and"
	lpout = "	{"
	lpout = "		1 add"
	lpout = "	} if"
	lpout = "} def"
	lpout = "/startday {		% starting day-of-week for this month"
	lpout = "	/off year 2000 sub def	% offset from start of epoch"
	lpout = "	off"
	lpout = "	off 4 idiv add		% number of leap years"
	lpout = "	off 100 idiv sub	% number of centuries"
	lpout = "	off 1000 idiv add	% number of millenia"
	lpout = "	6 add 7 mod 7 add 	% offset from Jan 1 2000"
	lpout = "	/off exch def"
	lpout = "	1 1 month 1 sub {"
	lpout = "		/idx exch def"
	lpout = "		days_month idx 1 sub get"
	lpout = "		idx 2 eq"
	lpout = "		isleap and"
	lpout = "		{"
	lpout = "			1 add"
	lpout = "		} if"
	lpout = "		/off exch off add def"
	lpout = "	} for"
	lpout = "	off 7 mod		% 0--Sunday, 1--monday, etc."
	lpout = "} def"
	lpout = "/center {		% center string in given width"
	lpout = "	/width exch def"
	lpout = "	/str exch def width str "
	lpout = "	stringwidth pop sub 2 div 0 rmoveto str show"
	lpout = "} def"
	lpout = "/calendar"
	lpout = "{"
	lpout = "	titlefont findfont 48 scalefont setfont"
	lpout = "	0 60 moveto"
	lpout = "	/month_name month_names month 1 sub get def"
	lpout = "	month_name show"
	lpout = "	/yearstring year 10 string cvs def"
	lpout = "	700 yearstring stringwidth pop sub 60 moveto"
	lpout = "	yearstring show"
	lpout = "	0 0 moveto"
	lpout = "	drawnums"
	lpout = "	0 0 moveto"
	lpout = "	drawfill"
	lpout = "	0 0 moveto"
	lpout = "	drawgrid"
	lpout = "} def"
	lpout = "/daytext {"
	lpout = "	/Helvetica-Narrow findfont 6 scalefont setfont"
	lpout = "	/mytext	exch def /myday exch def"
	lpout = "	startday myday 1 sub add dup 7 mod 100 mul 5 add % gives column"
	lpout = "	exch 7 idiv -80 mul % gives row"
	lpout = "	dup /ypos exch def moveto"
	lpout = "	/LM currentpoint pop def /RM LM 95 add def"
	lpout = "        mytext { dup (.p) eq { crlf pop} {prstr ( ) show} ifelse } forall"
	lpout = "} def"
	lpout = "/crlf {"
	lpout = "    ypos 8 sub /ypos exch def LM ypos moveto"
	lpout = "} def"
	lpout = "/prstr {"
	lpout = "    dup stringwidth pop currentpoint pop"
	lpout = "    add RM gt {crlf} if show"
	lpout = "} def"
	lpout = "/printmonth {"
	lpout = "	90 rotate"
	lpout = "	50 -120 translate"
	lpout = "	/submonth 0 def"
	lpout = "	calendar"
	lpout = "	month 1 sub 0 eq"
	lpout = "	{"
	lpout = "		/lmonth 12 def"
	lpout = "		/lyear year 1 sub def"
	lpout = "	}"
	lpout = "	{"
	lpout = "		/lmonth month 1 sub def"
	lpout = "		/lyear year def"
	lpout = "	} ifelse"
	lpout = "	month 1 add 13 eq"
	lpout = "	{"
	lpout = "		/nmonth 1 def"
	lpout = "		/nyear year 1 add def"
	lpout = "	} "
	lpout = "	{"
	lpout = "		/nmonth month 1 add def"
	lpout = "		/nyear year def"
	lpout = "	} ifelse"
	lpout = "	/savemonth month def"
	lpout = "	/saveyear year def"
	lpout = "	/submonth 1 def"
	lpout = "	/year lyear def"
	lpout = "	/month lmonth def"
	lpout = "	gsave"
	lpout = "	500 -365 translate"
	lpout = "	gsave"
	lpout = "	.138 .138 scale"
	lpout = "	10 -120 translate"
	lpout = "	calendar"
	lpout = "	grestore"
	lpout = "	/submonth 1 def"
	lpout = "	/year nyear def"
	lpout = "	/month nmonth def"
	lpout = "	100 0 translate"
	lpout = "	gsave"
	lpout = "	.138 .138 scale"
	lpout = "	10 -120 translate"
	lpout = "	calendar"
	lpout = "	grestore"
	lpout = "	/month savemonth def"
	lpout = "	/year saveyear def"
	lpout = "	/submonth 0 def"
	lpout = "	grestore"
	lpout = "} def"
nuf

run
exit