home *** CD-ROM | disk | FTP | other *** search
- /*
- * cal - open a month's calendar on the workbench screen for the
- * user.
- *
- * usage: cal [month [year]]
- *
- * If no args are given, use the current month & year.
- *
- * Month may be either a month name (only the first three characters
- * are used), or the number of the month.
- *
- * Year is the year of the christian era. If the length is exactly two
- * characters, then a '19' is prepended to it. So '9' is the year 9,
- * '09' is the year 1909; '34' is the year 1934, 034 is the year 34.
- *
- * The calendar presented is correct for England & its colonies for
- * periods when there was more than one calendar in general use. For
- * grins, try 'cal 9 1752'
- *
- * Mike Meyer, 1989
- */
-
- arg month year .
-
- /* Set up the months table - from names to numbers, */
- months. = 0
- months.jan = 1
- months.feb = 2
- months.mar = 3
- months.apr = 4
- months.may = 5
- months.jun = 6
- months.jul = 7
- months.aug = 8
- months.sep = 9
- months.oct = 10
- months.nov = 11
- months.dec = 12
-
- /* and now from numbers to days/month & print names */
- months.1 = 'January'
- months.1.days = 31
- months.2 = 'February'
- months.2.days = 1 /* Fixed later */
- months.3 = 'March'
- months.3.days = 31
- months.4 = 'April'
- months.4.days = 30
- months.5 = 'May'
- months.5.days = 31
- months.6 = 'June'
- months.6.days = 30
- months.7 = 'July'
- months.7.days = 31
- months.8 = 'August'
- months.8.days = 31
- months.9 = 'September'
- months.9.days = 30
- months.10 = 'October'
- months.10.days = 31
- months.11 = 'November'
- months.11.days = 30
- months.12 = 'December'
- months.12.days = 31 /* Not needed, but here for completeness */
-
- /* Get the current date for later use*/
- parse value date('Normal') with . mymonth myyear
-
- /* Get a month to work with */
- if datatype(month, 'Numeric') then mymonth = month
- else do
- if month ~= "" then mymonth = month
- mymonth = upper(left(mymonth, 3))
- mymonth = months.mymonth
- end
-
- if months.mymonth.days = 0 then do
- say "Month must be a month name or a number from 1 to 12, not" month
- exit 10
- end
-
- /* Got a valid month, now see about the year */
- select
- when year = "" then nop /* myyear is already right */
- when ~datatype(year, 'Numeric') then do
- say "Year must be a number between 1 and 9999, not" year
- exit 10
- end
- when length(year) = 2 then myyear = '19'year
- otherwise myyear = year
- end
-
- if myyear < 1 | myyear > 9999 then do
- say "Year must be between 1 and 9999 inclusive, not" myyear
- exit 10
- end
-
- /* Figure out what day of the week that month started on */
- firstday = jan1(myyear)
-
- /* Get difference in weekdays between this year & next */
- fudge = (jan1(myyear + 1) + 7 - firstday) // 7
-
- select
- /* this is a regular year */
- when fudge = 1 then months.2.days = 28
-
- /* This is a leap year */
- when fudge = 2 then months.2.days = 29
-
- /* Otherwise, it must be 1752! */
- otherwise
- months.2.days = 29
- months.9.days = 19
- end
-
- do i = 1 to mymonth - 1
- firstday = firstday + months.i.days
- end
-
- firstday = firstday // 7 /* Got the day of the week */
-
- /*
- * Now, go from that to the name of a day of the week. This table is also
- * used for formatting the output. The line at the top of the body consists
- * of these things concatenated together, with a space in between them.
- * The length of that string is the width of the calendar. Finally, we
- * line the numbers up under the last character of each name. All names
- * _must_ be the same length for this to work.
- */
- daynames.0 = 'Sun'
- daynames.1 = 'Mon'
- daynames.2 = 'Tue'
- daynames.3 = 'Wed'
- daynames.4 = 'Thu'
- daynames.5 = 'Fri'
- daynames.6 = 'Sat'
-
- firstday = daynames.firstday /* and now it's name */
-
- /* Get number of days in this month */
- days = months.mymonth.days
-
- /* Next, we set up the header for the calendar. */
- headerline = daynames.0
- do i = 1 to 6
- headerline = headerline daynames.i
- end
- linelength = length(headerline) /* width of calendar */
-
- /* Set up the header for the calender */
- lines.1 = center(months.mymonth myyear, linelength)
- lines.2 = " "
- lines.3 = headerline
- linecount = 4 /* First line of body of calendar */
-
- /* Now set up to put together lines of the body */
- maxline = linecount + 5 /* 6 weeks on a monthly calendar, max */
- do i = linecount + 1 to maxline
- lines.i = ""
- end
-
- width = length(daynames.0)
- lines.linecount = right(1, index(headerline, firstday) - 1 + width)
- do i = 2 to days
- if i > 2 & days < 20 then day = i + 11
- else day = i
-
- if length(lines.linecount) + width <= linelength then
- lines.linecount = lines.linecount right(day, width)
- else do
- linecount = linecount + 1
- lines.linecount = right(day, width)
- end
- end
-
- /* now display it - in a window if possible, to the console if not */
- if ~show('Libraries', 'rexxarplib.library') then do
- if ~addlib('rexxarplib.library', 0, -30) then do
- /* Now rexxarplib, just dump it to the console */
- do i = 1 to linecount
- say lines.i
- end
- exit
- end
- end
-
- /* Got a rexxarplib, so put it in a window */
- outline = lines.1
- do i = 2 to maxline
- outline = outline '\'lines.i
- end
-
- /*
- * We tack a space onto the end here, and in each line, so they will be
- * cleared by postmsg. Sigh.
- */
- call postmsg 0,0, outline ""
- exit
-
- /*
- * jan1 - returns the day of the week that january first falls on for
- * any specific year, 1 through 9999 (assuming they don't change
- * the rules again).
- */
- jan1: procedure
- arg year
-
- /* Julian calendar; one extra day every four years */
- day = 4 + year + (year + 3) % 4
-
- /* Gregorian calendar - lose three days over four centuries */
- if year > 1800 then do
- day = day - (year - 1701) % 100
- day = day + (year - 1601) % 400
- end
-
- /* And the instant changeover in 1752 */
- if year > 1752 then
- day = day + 3
-
- return day // 7
-