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


include ..\Utilitys.pmt
 
32 var space
 
def bksp    /# -- backspace #/
    8 tochar print
enddef
 
def floor
    .5 + int
enddef
 
def center
    tostr align
enddef
 
def startday    /# year -- day of the week of january 1 #/
    1 - >ps
    tps 365 * tps 4 / floor + tps 100 / floor - ps> 400 / floor + 7 mod
enddef
 
def bisiesto? /# year -- true if leap #/
    dup 4 mod not over 100 mod and swap 400 mod not or
enddef
 
def snoopy
    0 tcolor 15 bcolor
    "snoopy.txt" "r" fopen var f
 
    true 
    while
        f fgets
        dup -1 == if
            drop
            f fclose
            false
        else
            print
            true
        endif   
    endwhile
 
    15 tcolor 0 bcolor
enddef
 
( "JANUARY" "FEBRUARY" "MARCH" "APRIL" "MAY" "JUNE" "JULY" "AUGUST" "SEPTEMBER" "OCTOBER" "NOVEMBER" "DECEMBER" ) var months
"MO TU WE TH FR SA SU" var daysTitle
( 31 28 31 30 31 30 31 31 30 31 30 31 ) var daysPerMonth
daysTitle len nip var monthwidth
 
def makeMonth var days >ps
    monthwidth center daysTitle 2 tolist
 
    1 ps> - 1 + >ps
 
    true
    while
      ( )
      7 for drop
        tps 1 < tps days > or if
            " " 
        else
            tps 
        endif
        2 align 0 put
        ps> 1 + >ps
      endfor
      0 put
      len 8 <
    endwhile
    ps> drop
enddef
 
def print_cal >ps
    tps bisiesto? if daysPerMonth 29 2 set var daysPerMonth endif
    5 space over repeat var spaces
 
    snoopy
 
    3 monthwidth * swap 2 * +
    "--- " tps tostr " ---" chain chain swap center ? nl
 
    ps> startday var inicio
 
    ( )
 
    12 for >ps
        months tps get nip inicio
        daysPerMonth ps> get nip >ps
        tps makeMonth 0 put
        inicio ps> + 7 mod var inicio
    endfor
 
    ( 0 3 ) for var i
        8 for var k
            3 for var j
                i 3 * j + get 
                k get       
                list? if
                    10 tcolor
                    len for
                        get print " " print
                    endfor
                    drop
                    bksp
                else
                    11 tcolor
                    print
                endif
                drop
                spaces print
            endfor
            nl
        endfor
        nl
    endfor
    drop
enddef
 
2020 print_cal