#	Print a calendar for the specified month, highlighting today's date.
#	Based on algorithms published in Computer Language magazine,
#	December, 1990.  Used with permission.

proc day(jdate)
	# Calculate the day of the month corresponding to a Julian day number.
	local a, b, c, d, e, z, alpha
	@ z = jdate + 1
	# Cope with the Gregorian calendar reform.
	if (z < 2299161) then
		@ a = z
	else
		@ alpha = (z - 1867216.25)//36524.25
		@ a = z + 1 + alpha - alpha//4
	end
	@ b = a + 1524
	@ c = (b - 122.1)//365.25
	@ d = floor(365.25 * c)
	@ e = (b - d)//30.6001
	return b - d - floor(30.6001 * e)
end

proc dayofweek(jdate)
	return (jdate + 2) % 7
end

proc calendar(month, year)
	# Print a calendar for the specified month
	local b_date, e_date, c_date, day, c_day, c_month, c_year, Month, week
	local m, d, y, i, today
	set Month = January February March April May June ^
		July August September October November December
	set dt = `dt`
	set m = $dt:1
	set d = $dt:2
	set y = $dt:3
	for i = 0 to 11 do
		if (m == substr(Month[i], 1, 3)) break
	end
	@ m = i + 1
	@ today = `julian $m $d $y`
	if (year == '') then
		@ year = y
		if (month == '') @ month = m
	end
	if (month !~ '[0-9]*') then
		@ m = "$lower(month)*"
		for i = 0 to 11 do
			if (lower(Month[i]) =~ m) break
		end
		@ month = i + 1
	end
	# Calculate Julian day numbers for the first and last days of the month
	if ((b_date = julian(month, 1, year)) == -1) return
	@ e_date = (month < 12 ? ^
			julian(month + 1, 1, year) : ^
			julian(1, 1, year == -1 ? 1 : year + 1)) - 1
	echo $Month[month - 1] $year
	@ week = "^r^nSun Mon Tue Wed Thu Fri Sat^r^n"
	# Put the first day of the month under the correct day column
	for i = 0 to day = dayofweek(b_date) - 1 do
		@ week = concat(week, "    ")
	end
	# Print all the days
	@ i = 1
	if (b_date == 2299156) then
		#	In October 1582, the Julian calendar was replaced with the
		#	Gregorian calendar and Oct 4 was immediately followed by Oct 15
		#	by decree of Pope Gregory XIII.  However, be aware that Britain
		#	did not adopt the Gregorian calendar until Sept 2, 1752 (which
		#	was followed by Sept 14.)  This routine prints a calendar according
		#	to Pope Gregory's decree.
		for c_date = b_date to e_date do
			@ week = concat(week, printf("%3d ", i++))
			if (i == 5) @ i = 15
			if (c_date != e_date && ++day % 7 == 6) @ week = concat(week, "^r^n")
		end
	else
		for c_date = b_date to e_date do
			@ week = (today == c_date) ?				^
				concat(week, ansi("bright yellow"),	^
					printf("%3d ", i++), ansi()) :	^
				concat(week, printf("%3d ", i++))
			if (c_date != e_date && ++day % 7 == 6) @ week = concat(week, "^r^n")
		end
	end
	calc week
	echo
end

calendar $argv
