Create a routine that will generate a text calendar for any year.
Test the calendar by generating a calendar for the year 1969, on a device of the time.
Choose one of the following devices:

 A line printer with a width of 132 characters.
 An IBM 3278 model 4 terminal (80×43 display with accented characters). Target formatting the months of the year to fit nicely across the 80 character width screen. Restrict number of lines in test output to 43.


(Ideally, the program will generate well-formatted calendars for any page width from 20 characters up.)

Kudos (κῦδος) for routines that also transition from Julian to Gregorian calendar.

This task is inspired by Real Programmers Don't Use PASCAL by 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."

For further Kudos see task CALENDAR, where all code is to be in UPPERCASE.

For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.



Related task

   Five weekends


 
clear screen
 
sub snoopy()
	local n, a$
 
	n = open("snoopy.txt", "r")
 
	while(not eof(#n))
		line input #n a$
		print "  "; : print color("black", "white") a$ 
	wend
 
	close #n
end sub
 
sub floor(n)
	return int(n + 0.5)
end sub
 
sub string.rep$(s$, n)
	local i, r$
 
	for i = 1 to n
		r$ = r$ + s$
	next i
 
	return r$
end sub
 
sub center$(s$, width)
	local fill1
 
	fill1 = floor(width - len(s$)) / 2
 
	return string.rep$(" ",fill1) + s$ + string.rep$(" ",fill1)
end sub
 
sub makeMonth(name, skip, days, cal$(), j)
	local cal, curday, line$, i
 
	curday = 1 - skip
	cal = 3
 
	cal$(j, 2) = " " + daysTitle$ + " "
	//cal$(j, 1) = center$(months$(name),len(cal$(j, 2)))
	cal$(j, 1) = left$(months$(name) + string.rep$(" ", 80), len(cal$(j, 2)))
 
	while(cal < 9)
  		line$ = ""
  		for i = 1 to 7
    		    if curday < 1 or curday > days then
      			line$ = line$ + "   "
    		    else
      			line$ = line$ + str$(curday, "###")
    		    end if
    		    curday = curday + 1
  		next
  		cal = cal + 1
  		cal$(j, cal) = line$ + " "
	wend
end sub
 
dim months$(12)
n = token("JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER", months$(), ",")
daysTitle$ = "MO TU WE TH FR SA SU"
dim daysPerMonth(12)
for n = 1 to 12
	read daysPerMonth(n)
next
data 31,28,31,30,31,30,31,31,30,31,30,31
 
sub print_cal(year)
	local i, q, l, m, startday, sep, monthwidth, calwidth, dpm, calendar$(12, 9), line$(3)
 
	startday=mod(((year-1)*365+floor((year-1)/4)-floor((year-1)/100)+floor((year-1)/400)),7)
 	if not mod(year,4) and mod(year,100) or not mod(year,400) then
    	    daysPerMonth(2)=29
  	end if
 
  	sep = 5
  	monthwidth = len(daysTitle$)
	calwidth = 3 * monthwidth + 2 * sep
 
	for i = 1 to 12
    	    dpm = daysPerMonth(i)
    	    makeMonth(i, startday, dpm, calendar$(), i)
    	    startday = mod(startday + dpm, 7)
	next
 
	snoopy()
 	print center$("--- " + str$(year) + " ---", calwidth), "\n"
 
 	print string.rep$(" ", sep + 1);
 	for q = 0 to 3
     	    for l = 1 to 9
       		for m = 1 to 3
         		print calendar$(q * 3 + m, l);
       		next
       		print
       		print string.rep$(" ", sep);
     	    next
     	    print
     	    print string.rep$(" ", sep + 1);
 	next
end sub
 
print_cal(2018)
 