109 lines
3.9 KiB
Plaintext
109 lines
3.9 KiB
Plaintext
#!/usr/local/bin/a68g --script #
|
||
|
||
PROC print calendar = (INT year, page width)VOID: (
|
||
|
||
[]STRING month names = (
|
||
"January","February","March","April","May","June",
|
||
"July","August","September","October","November","December"),
|
||
weekday names = ("Su","Mo","Tu","We","Th","Fr","Sa");
|
||
FORMAT weekday fmt = $g,n(UPB weekday names - LWB weekday names)(" "g)$;
|
||
|
||
# Juggle the calendar format to fit the printer/screen width #
|
||
INT day width = UPB weekday names[1], day gap=1;
|
||
INT month width = (day width+day gap) * UPB weekday names-1;
|
||
INT month heading lines = 2;
|
||
INT month lines = (31 OVER UPB weekday names+month heading lines+2); # +2 for head/tail weeks #
|
||
INT year cols = (page width+1) OVER (month width+1);
|
||
INT year rows = (UPB month names-1)OVER year cols + 1;
|
||
INT month gap = (page width - year cols*month width + 1)OVER year cols;
|
||
INT year width = year cols*(month width+month gap)-month gap;
|
||
INT year lines = year rows*month lines;
|
||
|
||
MODE MONTHBOX = [month lines, month width]CHAR;
|
||
MODE YEARBOX = [year lines, year width]CHAR;
|
||
|
||
INT week start = 1; # Sunday #
|
||
|
||
PROC days in month = (INT year, month)INT:
|
||
CASE month IN 31,
|
||
IF year MOD 4 EQ 0 AND year MOD 100 NE 0 OR year MOD 400 EQ 0 THEN 29 ELSE 28 FI,
|
||
31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||
ESAC;
|
||
|
||
PROC day of week = (INT year, month, day)INT: (
|
||
# Day of the week by Zeller’s Congruence algorithm from 1887 #
|
||
INT y := year, m := month, d := day, c;
|
||
IF m <= 2 THEN m +:= 12; y -:= 1 FI;
|
||
c := y OVER 100;
|
||
y %*:= 100;
|
||
(d - 1 + ((m + 1) * 26) OVER 10 + y + y OVER 4 + c OVER 4 - 2 * c) MOD 7
|
||
);
|
||
|
||
MODE SIMPLEOUT = UNION(STRING, []STRING, INT);
|
||
|
||
PROC cputf = (REF[]CHAR out, FORMAT fmt, SIMPLEOUT argv)VOID:(
|
||
FILE f; STRING s; associate(f,s);
|
||
putf(f, (fmt, argv));
|
||
out[:UPB s]:=s;
|
||
close(f)
|
||
);
|
||
|
||
PROC month repr = (INT year, month)MONTHBOX:(
|
||
MONTHBOX month box; FOR line TO UPB month box DO month box[line,]:=" "* 2 UPB month box OD;
|
||
STRING month name = month names[month];
|
||
|
||
# center the title #
|
||
cputf(month box[1,(month width - UPB month name ) OVER 2+1:], $g$, month name);
|
||
cputf(month box[2,], weekday fmt, weekday names);
|
||
|
||
INT first day := day of week(year, month, 1);
|
||
FOR day TO days in month(year, month) DO
|
||
INT line = (day+first day-week start) OVER UPB weekday names + month heading lines + 1;
|
||
INT char =((day+first day-week start) MOD UPB weekday names)*(day width+day gap) + 1;
|
||
cputf(month box[line,char:char+day width-1],$g(-day width)$, day)
|
||
OD;
|
||
month box
|
||
);
|
||
|
||
PROC year repr = (INT year)YEARBOX:(
|
||
YEARBOX year box;
|
||
FOR line TO UPB year box DO year box[line,]:=" "* 2 UPB year box OD;
|
||
FOR month row FROM 0 TO year rows-1 DO
|
||
FOR month col FROM 0 TO year cols-1 DO
|
||
INT month = month row * year cols + month col + 1;
|
||
IF month > UPB month names THEN
|
||
done
|
||
ELSE
|
||
INT month col width = month width+month gap;
|
||
year box[
|
||
month row*month lines+1 : (month row+1)*month lines,
|
||
month col*month col width+1 : (month col+1)*month col width-month gap
|
||
] := month repr(year, month)
|
||
FI
|
||
OD
|
||
OD;
|
||
done: year box
|
||
);
|
||
|
||
INT center = (year cols*(month width+month gap) - month gap - 1) OVER 2;
|
||
INT indent = (page width - year width) OVER 2;
|
||
|
||
printf((
|
||
$n(indent + center - 9)k g l$, "[Insert Snoopy here]",
|
||
$n(indent + center - 1)k 4d l$, year, $l$,
|
||
$n(indent)k n(year width)(g) l$, year repr(year)
|
||
))
|
||
);
|
||
|
||
main: (
|
||
CO inspired by http://www.ee.ryerson.ca/~elf/hack/realmen.html
|
||
Real Programmers Don't Use PASCAL - Ed Post
|
||
Datamation, volume 29 number 7, July 1983
|
||
THE REAL PROGRAMMER'S NATURAL HABITAT
|
||
"Taped to the wall is a line-printer Snoopy calender for the year 1969."
|
||
CO
|
||
INT mankind stepped on the moon = 1969,
|
||
line printer width = 80; # as at 1969! #
|
||
print calendar(mankind stepped on the moon, line printer width)
|
||
)
|